Browse Source

server -> app encryption

connman
Aditya Kulkarni 5 years ago
parent
commit
4baf8586c7
  1. 47
      app/src/main/java/com/adityapk/zcash/zqwandroid/DataModel.kt

47
app/src/main/java/com/adityapk/zcash/zqwandroid/DataModel.kt

@ -9,6 +9,7 @@ import com.beust.klaxon.json
import okhttp3.WebSocket
import org.libsodium.jni.NaCl
import org.libsodium.jni.Sodium
import java.math.BigInteger
object DataModel {
@ -33,7 +34,7 @@ object DataModel {
}
fun String.hexStringToByteArray(byteSize: Int) : ByteArray {
val s = "00".repeat(byteSize - this.length / 2)
val s = "00".repeat(byteSize - (this.length / 2) ) + this
return ByteArray(byteSize) { s.substring(it * 2, it * 2 + 2).toInt(16).toByte() }
}
@ -71,6 +72,11 @@ object DataModel {
fun parseResponse(response: String) : Boolean {
val json = Parser.default().parse(StringBuilder(response)) as JsonObject
// Check if input string is encrypted
if (json.containsKey("nonce")) {
return parseResponse(decrypt(json["nonce"].toString(), json["payload"].toString()))
}
return when (json.string("command")) {
"getInfo" -> {
mainResponseData = Klaxon().parse<MainResponse>(response)
@ -129,6 +135,28 @@ object DataModel {
}
fun decrypt(nonceHex: String, encHex: String) : String {
// Decrypt the hex string into a regular string and return
// First make sure the remote nonce is valid
checkAndUpdateRemoteNonce(nonceHex);
val encsize = encHex.length / 2
val encbin = encHex.hexStringToByteArray(encHex.length / 2)
val decrypted = ByteArray(encsize - Sodium.crypto_secretbox_macbytes())
val noncebin = nonceHex.hexStringToByteArray(Sodium.crypto_secretbox_noncebytes())
Sodium.crypto_secretbox_open_easy(decrypted, encbin, encsize, noncebin, secret);
val s = String(decrypted)
println("Decrypted to: ${String(decrypted)}")
return String(decrypted)
}
fun encrypt(s : String) : String {
// Take the string, encrypt it and send it as the payload with the nonce in a Json string
val msg = s.toByteArray()
@ -151,16 +179,27 @@ object DataModel {
return j.toJsonString()
}
fun checkAndUpdateRemoteNonce(remoteNonce: String) {
val settings = ZQWApp.appContext!!.getSharedPreferences("Nonce", 0)
val prevNonceHex = settings.getString("remotenonce", "00".repeat(Sodium.crypto_secretbox_noncebytes()))
// The problem is the nonces are hex encoded in little endian, but the BigDecimal contructor expects the nonces
// in big endian format. So flip the endian-ness of the hex strings for comparision
check(BigInteger(remoteNonce.chunked(2).reversed().joinToString(""), 16) > BigInteger(prevNonceHex.chunked(2).reversed().joinToString(""), 16))
val editor = settings.edit()
editor.putString("remotenonce", remoteNonce)
editor.apply()
}
fun incAndGetLocalNonce() : ByteArray {
val settings = ZQWApp.appContext!!.getSharedPreferences("Nonce", 0)
val nonceHex = settings.getString("localnonce", "00".repeat(Sodium.crypto_secretbox_noncebytes()))
val nonce = nonceHex!!.hexStringToByteArray(Sodium.crypto_secretbox_noncebytes())
// sodium_increment assumes little endian, but we are big endian
nonce.reverse()
Sodium.sodium_increment(nonce, nonce.size)
Sodium.sodium_increment(nonce, nonce.size)
nonce.reverse()
val editor = settings.edit()
editor.putString("localnonce", nonce.toHexString())

Loading…
Cancel
Save