Skip to content

Commit

Permalink
fix: make fixes to ed25519 sign method, which was being returned as H…
Browse files Browse the repository at this point in the history
…ex causing compatibility issues and improve tests

Signed-off-by: Javier Ribó <[email protected]>
  • Loading branch information
elribonazo committed Sep 27, 2024
1 parent 2b4a59b commit 53ab062
Show file tree
Hide file tree
Showing 15 changed files with 146 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import org.bouncycastle.crypto.signers.Ed25519Signer
*
* @property raw The raw byte array representation of the private key.
*/
actual class KMMEdPrivateKey(val raw: ByteArray) {
actual class KMMEdPrivateKey actual constructor(val rawBuffer: ByteArray) {
/**
* Retrieves the public key associated with a KMMEdPrivateKey.
*
* @return The KMMEdPublicKey object representing the public key.
*/
fun publicKey(): KMMEdPublicKey {
val private = Ed25519PrivateKeyParameters(raw, 0)
val private = Ed25519PrivateKeyParameters(rawBuffer, 0)
val public = private.generatePublicKey()
return KMMEdPublicKey(public.encoded)
}
Expand All @@ -27,7 +27,7 @@ actual class KMMEdPrivateKey(val raw: ByteArray) {
* @return The signature of the message.
*/
actual fun sign(message: ByteArray): ByteArray {
val privateKeyParameters = Ed25519PrivateKeyParameters(raw, 0)
val privateKeyParameters = Ed25519PrivateKeyParameters(rawBuffer, 0)
val signer = Ed25519Signer()
signer.init(true, privateKeyParameters)
signer.update(message, 0, message.size)
Expand All @@ -40,7 +40,7 @@ actual class KMMEdPrivateKey(val raw: ByteArray) {
* @return KMMX25519PrivateKey private key
*/
actual fun x25519PrivateKey(): KMMX25519PrivateKey {
val rawX25519Prv = convertSecretKeyToX25519(this.raw)
val rawX25519Prv = convertSecretKeyToX25519(this.rawBuffer)
return KMMX25519PrivateKey(rawX25519Prv)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import java.io.ByteArrayInputStream
*
* @property raw The raw byte array representation of the public key.
*/
actual class KMMEdPublicKey(val raw: ByteArray) {
actual class KMMEdPublicKey actual constructor(val bytes: ByteArray) {
val raw = bytes;
/**
* Verifies the signature of a message using the provided public key.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import swift.cryptoKit.Ed25519
* @property raw The raw byte array representation of the private key.
*/
@OptIn(ExperimentalForeignApi::class)
public actual class KMMEdPrivateKey(val raw: ByteArray) {
public actual class KMMEdPrivateKey actual constructor(val rawBuffer: ByteArray) {
/**
* Represents a private key for the KMMEd cryptographic system.
*
Expand All @@ -26,7 +26,7 @@ public actual class KMMEdPrivateKey(val raw: ByteArray) {
*/
@Throws(RuntimeException::class)
actual fun sign(message: ByteArray): ByteArray {
val result = Ed25519.signWithPrivateKey(raw.toNSData(), message.toNSData())
val result = Ed25519.signWithPrivateKey(rawBuffer.toNSData(), message.toNSData())
result.failure()?.let { throw RuntimeException(it.localizedDescription()) }
return result.success()?.toByteArray() ?: throw RuntimeException("Null result")
}
Expand All @@ -39,7 +39,7 @@ public actual class KMMEdPrivateKey(val raw: ByteArray) {
*/
@Throws(RuntimeException::class)
fun publicKey(): KMMEdPublicKey {
val result = Ed25519.publicKeyWithPrivateKey(raw.toNSData())
val result = Ed25519.publicKeyWithPrivateKey(rawBuffer.toNSData())
result.failure()?.let { throw RuntimeException(it.localizedDescription()) }
val publicRaw = result.success()?.toByteArray() ?: throw RuntimeException("Null result")
return KMMEdPublicKey(publicRaw)
Expand All @@ -51,7 +51,7 @@ public actual class KMMEdPrivateKey(val raw: ByteArray) {
* @return KMMX25519PrivateKey private key
*/
actual fun x25519PrivateKey(): KMMX25519PrivateKey {
val rawX25519Prv = convertSecretKeyToX25519(this.raw)
val rawX25519Prv = convertSecretKeyToX25519(this.rawBuffer)
return KMMX25519PrivateKey(rawX25519Prv)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import swift.cryptoKit.Ed25519
* @property raw The raw byte array representation of the public key.
*/
@OptIn(ExperimentalForeignApi::class)
public actual class KMMEdPublicKey(val raw: ByteArray = ByteArray(0)) {
public actual class KMMEdPublicKey actual constructor(bytes: ByteArray) {
val raw: ByteArray = bytes;

/**
* Verifies a message signature using a public key.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.hyperledger.identus.apollo.secp256k1

import org.hyperledger.identus.apollo.base64.base64DecodedBytes
import org.hyperledger.identus.apollo.utils.KMMEdPublicKey
import kotlin.test.Test
import kotlin.test.assertTrue

class KMMEdKeyPairTest {

@Test
fun ed_signature_verify() {
val message = "testing".encodeToByteArray()
val edsk = KMMEdPublicKey("z+a8g8i/3yajE/QDIxIF7sP1m/aLKTOfygIuSJanRAg".base64DecodedBytes)
val sig = "zZzeTBYjrpowc+skEMVQSVTzntzXvZGcbBbNY0gHKF6z+e40Q5G3o35lX4Mf0J8iRde/LAn77JdzIh6gQv7hAA".base64DecodedBytes
val verify = edsk.verify(message, sig)
assertTrue(verify)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package org.hyperledger.identus.apollo.secp256k1

import fr.acinq.secp256k1.Secp256k1Native
import kotlin.test.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import kotlin.test.*

class Secp256k1Tests {

@Test
fun verifyValidPrivateKey() {
val secp256k1 = Secp256k1Native
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.hyperledger.identus.apollo.utils
/**
* Definition of the KMMEdPrivateKey functionality
*/
public expect class KMMEdPrivateKey {
public expect class KMMEdPrivateKey(rawBuffer: ByteArray) {

/**
* Method to sign a message using this KMMEdPrivateKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package org.hyperledger.identus.apollo.utils
/**
* Definition of the KMMEdPublicKey functionality
*/
public expect class KMMEdPublicKey {
public expect class KMMEdPublicKey(bytes: ByteArray) {

/**
* Method to verify a signature against the original message
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package org.hyperledger.identus.apollo.utils

import org.hyperledger.identus.apollo.base64.base64DecodedBytes
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

class KMMEdKeyPairTestsIgnored {
private val sk = "MYW4achRIcJkpg+AUHfF8LRe4yC+R6bxySHKRNxC3Ss".base64DecodedBytes
private val pk = "oKpvr2406EzaQL1jxr+xY9E3R1PW4+UbkFsCIgqflHU".base64DecodedBytes
private val sig = "yrGLROG6VuxYGIozboQnblbV3XHrlJGG/IYUPefFVsUbp6VmQtqaHtqI02kDTdaJ86ZX1hOiO4SoAi6gvRWkAA".base64DecodedBytes

private val sk1 = "yhqs9jKnsPIg55eG9RgG9484HR7UMYPDKS7yYb4w53w".base64DecodedBytes
private val pk1 = "ZfKIkRXdo1So5zdiMV2wnwsRTQYEVheJpkBd85BOvvs".base64DecodedBytes
private val sig1 = "TT6dNYar8AKlTkvibsAHzEsG/ArAAVWshewSwGcpY7aFc6OZ5/VAK/Dldj5cZNdTZxhtpXe5sJrSGFicoRdsAw".base64DecodedBytes;

private val sk2 = "WfrIGPy60WOf8D/NYun3byOGjIcYOF0YpMxq5asXfio".base64DecodedBytes
private val pk2 = "6MhfVglYiTf6S16vr1YhkgsCPj1JIWiXyIT0dxAsHyA".base64DecodedBytes
private val sig2 = "XLalfAYDTyGVgNho+pJPzmg75+7VX6fxTlJC6+Lq5EXKVqX5YpBledbw5P/yF9vXJUmwwFc7QqbW0YRi3DY9AA".base64DecodedBytes

@Test
fun testGenerateKeyPair() {
val keyPair = KMMEdKeyPair.generateKeyPair()
Expand All @@ -15,25 +29,15 @@ class KMMEdKeyPairTestsIgnored {
}

@Test
fun testSignMessage() {
fun testVerifyMessage() {
val keyPair = KMMEdKeyPair.generateKeyPair()
val message = "testing".encodeToByteArray()
val sig = keyPair.sign(message)
val msgHash = "testing".encodeToByteArray()
val sig = keyPair.sign(msgHash)
val verified = keyPair.verify(msgHash, sig)

assertNotNull(sig)
assertTrue(verified)
}

// TODO: For some reason this test is failing in JVM and Android but only for generated key pairs commenting for now since has nothing to do with this PR
// @Test
// fun testVerifyMessage() {
// val keyPair = KMMEdKeyPair.generateKeyPair()
// val msgHash = "testing".encodeToByteArray()
// val sig = keyPair.sign(msgHash)
// val verified = keyPair.verify(msgHash, sig)
//
// assertTrue(verified)
// }

@Test
fun testVerifyWithAnotherKeyPairFails() {
val keyPair = KMMEdKeyPair.generateKeyPair()
Expand All @@ -45,4 +49,25 @@ class KMMEdKeyPairTestsIgnored {

assertFalse(verified)
}

@Test
fun testVerifyMessageFromSK() {
val msgHash = "testing".encodeToByteArray()

val testSig = KMMEdPrivateKey(sk).sign(msgHash)
assertTrue(testSig contentEquals sig)
val verified = KMMEdPublicKey(pk).verify(msgHash, testSig)

val testSig1 = KMMEdPrivateKey(sk1).sign(msgHash)
assertTrue(testSig1 contentEquals sig1)
val verified1 = KMMEdPublicKey(pk1).verify(msgHash, testSig1)

val testSig2 = KMMEdPrivateKey(sk2).sign(msgHash)
assertTrue(testSig2 contentEquals sig2)
val verified2 = KMMEdPublicKey(pk2).verify(msgHash, testSig2)

assertTrue(verified)
assertTrue(verified1)
assertTrue(verified2)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import org.hyperledger.identus.apollo.utils.external.eddsa
*/
@OptIn(ExperimentalJsExport::class)
@JsExport
actual class KMMEdPrivateKey(bytes: ByteArray) {
actual class KMMEdPrivateKey actual constructor(rawBuffer: ByteArray) {
val raw: Buffer
val ed25519: eddsa;

private val keyPair: eddsa.KeyPair

init {
val ed25519 = eddsa("ed25519")

raw = Curve25519Parser.parseRaw(bytes)
ed25519 = eddsa("ed25519")
raw = Curve25519Parser.parseRaw(rawBuffer)
keyPair = ed25519.keyFromSecret(raw)
}

Expand Down Expand Up @@ -49,7 +50,7 @@ actual class KMMEdPrivateKey(bytes: ByteArray) {
actual fun sign(message: ByteArray): ByteArray {
val sig = keyPair.sign(Buffer.from(message))

return sig.toHex().encodeToByteArray()
return sig.toBytes().toByteArray()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import org.hyperledger.identus.apollo.utils.external.eddsa
*/
@OptIn(ExperimentalJsExport::class)
@JsExport
actual class KMMEdPublicKey(bytes: ByteArray) {
actual class KMMEdPublicKey actual constructor(bytes: ByteArray) {
val raw: Buffer
val ed25519: eddsa;

private val keyPair: eddsa.KeyPair

init {
val ed25519 = eddsa("ed25519")
ed25519 = eddsa("ed25519")

raw = Curve25519Parser.parseRaw(bytes)
val pub = raw.toString(BufferEncoding.hex)
Expand All @@ -46,6 +48,12 @@ actual class KMMEdPublicKey(bytes: ByteArray) {
* @return Boolean
*/
actual fun verify(message: ByteArray, sig: ByteArray): Boolean {
return keyPair.verify(Buffer.from(message), sig.decodeToString())

return keyPair.verify(
Buffer.from(message),
sig.toHexString()


)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ open external class eddsa(name: String /* "ed25519" */) {
open fun isPoint(param_val: Any): Boolean
open class Signature {
constructor(eddsa: eddsa, sig: _eddsa_Signature)
constructor(eddsa: eddsa, sig: String)
constructor(eddsa: eddsa, sig: Any)
open fun toBytes(): Buffer
open fun toHex(): String
}
Expand Down
Loading

0 comments on commit 53ab062

Please sign in to comment.