mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-12 09:53:38 +00:00
Update SOGS signature construction
This commit is contained in:
parent
b51013f050
commit
301fe537e4
@ -8,7 +8,7 @@ import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
import org.session.libsignal.utilities.Base64
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SodiumUtilitiesTest {
|
||||
@ -26,27 +26,25 @@ class SodiumUtilitiesTest {
|
||||
assertThat(keyPair.publicKey.asHexString.lowercase(), equalTo(blindedKey))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sharedBlindedEncryptionKey() {
|
||||
val key = ByteArray(0)
|
||||
val encryptionKey = SodiumUtilities.sharedBlindedEncryptionKey(key, key, key, key)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sogsSignature() {
|
||||
// val expectedSignature = "K1N3A+H4dxV/wiN6Mr9cEj9TWUUqxESDoGW1cmoqDp7zMzCuCraTQKPX1tIiPuOBmFvB8VSUuYsHZrfGis1hDA=="
|
||||
// val expectedSignature = "xxLpXHbomAJMB9AtGMyqvBsXrdd2040y+Ol/IKzElWfKJa3EYZRv1GLO6CTLhrDFUwVQe8PPltyGs54Kd7O5Cg=="
|
||||
val expectedSignature = "gYqpWZX6fnF4Gb2xQM3xaXs0WIYEI49+B8q4mUUEg8Rw0ObaHUWfoWjMHMArAtP9QlORfiydsKWz1o6zdPVeCQ=="
|
||||
val expectedSignature = "K1N3A+H4dxV/wiN6Mr9cEj9TWUUqxESDoGW1cmoqDp7zMzCuCraTQKPX1tIiPuOBmFvB8VSUuYsHZrfGis1hDA=="
|
||||
val keyPair = SodiumUtilities.blindedKeyPair(serverPublicKey, KeyPair(pubKey, secKey))!!
|
||||
|
||||
val signature = SodiumUtilities.sogsSignature(
|
||||
ByteArray(0),
|
||||
val message = serverPublicKey.toByteArray()
|
||||
.plus(Base64.decode("CaLsVaBSL9jarS5SwzJd8g=="))
|
||||
.plus("1647896537".toByteArray(Charsets.US_ASCII))
|
||||
.plus("GET".toByteArray())
|
||||
.plus("/room/sudoku/messages/recent?limit=25".toByteArray())
|
||||
.plus(ByteArray(0))
|
||||
val signature = Base64.encodeBytes(SodiumUtilities.sogsSignature(
|
||||
message,
|
||||
secKey.asBytes,
|
||||
keyPair.secretKey.asBytes,
|
||||
keyPair.publicKey.asBytes
|
||||
)!!
|
||||
)!!)
|
||||
|
||||
assertThat(signature.toHexString(), equalTo(expectedSignature))
|
||||
assertThat(signature, equalTo(expectedSignature))
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory
|
||||
import com.goterl.lazysodium.LazySodiumAndroid
|
||||
import com.goterl.lazysodium.SodiumAndroid
|
||||
import com.goterl.lazysodium.interfaces.GenericHash
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.functional.bind
|
||||
@ -153,8 +154,27 @@ object OpenGroupApiV4 {
|
||||
SodiumUtilities.IdPrefix.BLINDED,
|
||||
keyPair.publicKey.asBytes
|
||||
).hexString
|
||||
var bodyHash = ByteArray(0)
|
||||
if (request.parameters != null) {
|
||||
val parameterBytes = JsonUtil.toJson(request.parameters).toByteArray()
|
||||
val parameterHash = ByteArray(GenericHash.BYTES_MAX)
|
||||
if (sodium.cryptoGenericHash(
|
||||
parameterHash,
|
||||
parameterHash.size,
|
||||
parameterBytes,
|
||||
parameterBytes.size.toLong()
|
||||
)) {
|
||||
bodyHash = parameterHash
|
||||
}
|
||||
}
|
||||
val messageBytes = publicKey.toByteArray()
|
||||
.plus(nonce)
|
||||
.plus("$timestamp".toByteArray(Charsets.US_ASCII))
|
||||
.plus(request.verb.rawValue.toByteArray())
|
||||
.plus(urlRequest.url().toString().toByteArray())
|
||||
.plus(bodyHash)
|
||||
signature = SodiumUtilities.sogsSignature(
|
||||
urlRequest.toString().toByteArray(),
|
||||
messageBytes,
|
||||
ed25519KeyPair.secretKey.asBytes,
|
||||
keyPair.secretKey.asBytes,
|
||||
keyPair.publicKey.asBytes
|
||||
@ -630,7 +650,8 @@ object OpenGroupApiV4 {
|
||||
room = null,
|
||||
server = server,
|
||||
endpoint = "rooms",
|
||||
isAuthRequired = false
|
||||
isAuthRequired = false,
|
||||
isBlinded = true
|
||||
)
|
||||
return send(request).map { json ->
|
||||
val rawRooms = json["rooms"] as? List<Map<*, *>> ?: throw Error.ParsingFailed
|
||||
|
@ -3,7 +3,6 @@ package org.session.libsession.messaging.utilities
|
||||
import com.goterl.lazysodium.LazySodiumAndroid
|
||||
import com.goterl.lazysodium.SodiumAndroid
|
||||
import com.goterl.lazysodium.interfaces.GenericHash
|
||||
import com.goterl.lazysodium.interfaces.Hash
|
||||
import com.goterl.lazysodium.interfaces.Sign
|
||||
import com.goterl.lazysodium.utils.Key
|
||||
import com.goterl.lazysodium.utils.KeyPair
|
||||
@ -47,8 +46,8 @@ object SodiumUtilities {
|
||||
|
||||
/* Constructs a "blinded" key pair (`ka, kA`) based on an open group server `publicKey` and an ed25519 `keyPair` */
|
||||
fun blindedKeyPair(serverPublicKey: String, edKeyPair: KeyPair): KeyPair? {
|
||||
if (edKeyPair.publicKey.asBytes.size != Sign.PUBLICKEYBYTES ||
|
||||
edKeyPair.secretKey.asBytes.size != Sign.SECRETKEYBYTES) return null
|
||||
// if (edKeyPair.publicKey.asBytes.size != Sign.PUBLICKEYBYTES ||
|
||||
// edKeyPair.secretKey.asBytes.size != Sign.SECRETKEYBYTES) return null
|
||||
val kBytes = generateBlindingFactor(serverPublicKey)
|
||||
val aBytes = generatePrivateKeyScalar(edKeyPair.secretKey.asBytes)
|
||||
// Generate the blinded key pair `ka`, `kA`
|
||||
@ -74,16 +73,16 @@ object SodiumUtilities {
|
||||
fun sogsSignature(
|
||||
message: ByteArray,
|
||||
secretKey: ByteArray,
|
||||
ka: ByteArray, /*blindedSecretKey*/
|
||||
kA: ByteArray /*blindedPublicKey*/
|
||||
blindedSecretKey: ByteArray, /*ka*/
|
||||
blindedPublicKey: ByteArray /*kA*/
|
||||
): ByteArray? {
|
||||
// H_rh = sha512(s.encode()).digest()[32:]
|
||||
val h_rh = ByteArray(Hash.SHA512_BYTES)
|
||||
val h_rh = ByteArray(GenericHash.BYTES)
|
||||
if (!sodium.cryptoHashSha512(h_rh, secretKey, secretKey.size.toLong())) return null
|
||||
|
||||
// r = salt.crypto_core_ed25519_scalar_reduce(sha512_multipart(H_rh, kA, message_parts))
|
||||
val combinedData = h_rh + kA + message
|
||||
val combinedHash = ByteArray(Hash.SHA512_BYTES)
|
||||
val combinedData = h_rh + blindedPublicKey + message
|
||||
val combinedHash = ByteArray(GenericHash.BYTES)
|
||||
if (!sodium.cryptoHashSha512(combinedHash, combinedData, combinedData.size.toLong())) return null
|
||||
val rHash = ByteArray(Sign.CURVE25519_PUBLICKEYBYTES)
|
||||
sodium.cryptoCoreEd25519ScalarReduce(rHash, combinedHash)
|
||||
@ -92,23 +91,23 @@ object SodiumUtilities {
|
||||
}
|
||||
|
||||
// sig_R = salt.crypto_scalarmult_ed25519_base_noclamp(r)
|
||||
val sig_R = ByteArray(Sign.SECRETKEYBYTES)
|
||||
val sig_R = ByteArray(Sign.ED25519_PUBLICKEYBYTES)
|
||||
if (!sodium.cryptoScalarMultBase(sig_R, rHash)) return null
|
||||
|
||||
// HRAM = salt.crypto_core_ed25519_scalar_reduce(sha512_multipart(sig_R, kA, message_parts))
|
||||
val hRamData = sig_R + kA + message
|
||||
val hRamHash = ByteArray(Hash.SHA512_BYTES)
|
||||
val hRamData = sig_R + blindedPublicKey + message
|
||||
val hRamHash = ByteArray(GenericHash.BYTES)
|
||||
if (!sodium.cryptoHashSha512(hRamHash, hRamData, hRamData.size.toLong())) return null
|
||||
val hRam = ByteArray(Sign.CURVE25519_PUBLICKEYBYTES)
|
||||
val hRam = ByteArray(Sign.ED25519_PUBLICKEYBYTES)
|
||||
sodium.cryptoCoreEd25519ScalarReduce(hRam, hRamHash)
|
||||
if (hRam.all { it.toInt() == 0 }) {
|
||||
return null
|
||||
}
|
||||
// sig_s = salt.crypto_core_ed25519_scalar_add(r, salt.crypto_core_ed25519_scalar_mul(HRAM, ka))
|
||||
val sig_sMul = ByteArray(Sign.CURVE25519_PUBLICKEYBYTES)
|
||||
val sig_s = ByteArray(Sign.CURVE25519_PUBLICKEYBYTES)
|
||||
if (sodium.cryptoScalarMult(sig_sMul, hRam, ka)) {
|
||||
sodium.cryptoCoreEd25519ScalarReduce(sig_s/*, rHash*/, sig_sMul)
|
||||
val sig_sMul = ByteArray(Sign.ED25519_PUBLICKEYBYTES)
|
||||
val sig_s = ByteArray(Sign.ED25519_PUBLICKEYBYTES)
|
||||
if (sodium.cryptoScalarMult(sig_sMul, hRam, blindedSecretKey)) {
|
||||
sodium.cryptoCoreEd25519ScalarAdd(sig_s, rHash, sig_sMul)
|
||||
} else return null
|
||||
|
||||
return sig_R + sig_s
|
||||
|
@ -490,14 +490,14 @@ object OnionRequestAPI {
|
||||
"headers" to headers
|
||||
)
|
||||
val requestData = JsonUtil.toJson(requestPayload).toByteArray()
|
||||
val prefixData = "l${requestData.size}".toByteArray()
|
||||
val suffixData = "e".toByteArray()
|
||||
val prefixData = "l${requestData.size}".toByteArray(Charsets.US_ASCII)
|
||||
val suffixData = "e".toByteArray(Charsets.US_ASCII)
|
||||
if (request.body() != null) {
|
||||
val bodyPayload = mapOf(
|
||||
"body" to body
|
||||
)
|
||||
val bodyData = JsonUtil.toJson(bodyPayload).toByteArray()
|
||||
val bodyLengthData = "${bodyData.size}".toByteArray()
|
||||
val bodyLengthData = "${bodyData.size}".toByteArray(Charsets.US_ASCII)
|
||||
prefixData + requestData + bodyLengthData + bodyData + suffixData
|
||||
} else {
|
||||
prefixData + requestData + suffixData
|
||||
|
Loading…
x
Reference in New Issue
Block a user