Skip to content

Commit

Permalink
fix: add ec pub key validation checks
Browse files Browse the repository at this point in the history
  • Loading branch information
hamada147 authored and goncalo-frade-iohk committed Nov 20, 2023
1 parent 1788dd1 commit 8eb52b5
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 25 deletions.
6 changes: 2 additions & 4 deletions cryptography/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ kotlin {
implementation(project(":utils"))
implementation(project(":secure-random"))
implementation(project(":hashing"))
implementation("com.ionspin.kotlin:bignum:0.3.7")
implementation(project(":base64"))
implementation("com.ionspin.kotlin:bignum:0.3.7")
implementation("org.kotlincrypto.macs:hmac-sha2:0.3.0")
}
}
Expand All @@ -134,9 +134,7 @@ kotlin {
}
val jvmMain by getting {
dependencies {
dependencies {
api("fr.acinq.secp256k1:secp256k1-kmp:0.9.0")
}
api("fr.acinq.secp256k1:secp256k1-kmp:0.9.0")
implementation("fr.acinq.secp256k1:secp256k1-kmp-jni-jvm:0.9.0")
implementation("com.google.guava:guava:30.1-jre")
implementation("org.bouncycastle:bcprov-jdk15on:1.68")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import io.iohk.atala.prism.apollo.hashing.SHA256
actual class Secp256k1Lib {
actual fun createPublicKey(privateKey: ByteArray, compressed: Boolean): ByteArray {
val pubKey = Secp256k1.pubkeyCreate(privateKey)
if (compressed) {
return Secp256k1.pubKeyCompress(pubKey)
if (Secp256k1Helper.validatePublicKey(pubKey)) {
if (compressed) {
return Secp256k1.pubKeyCompress(pubKey)
}
return pubKey
} else {
throw Secp256k1Exception("invalid public key")
}
return pubKey
}

actual fun derivePrivateKey(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.iohk.atala.prism.apollo.secp256k1

import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.integer.Sign

class Secp256k1Helper {
companion object {
fun validatePublicKey(pubKey: ByteArray): Boolean {
val x = BigInteger.fromByteArray(pubKey.sliceArray(1..32), Sign.POSITIVE)
val y = BigInteger.fromByteArray(pubKey.sliceArray(33..64), Sign.POSITIVE)
val b = BigInteger(7)
val p = BigInteger.parseString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10)
return ((y * y - x * x * x - b) mod p) == BigInteger.ZERO
}
}
}

public class Secp256k1Exception : RuntimeException {
public constructor() : super()
public constructor(message: String?) : super(message)
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package io.iohk.atala.prism.apollo.secp256k1

import fr.acinq.secp256k1.Secp256k1Exception
import fr.acinq.secp256k1.Secp256k1Native
import io.iohk.atala.prism.apollo.hashing.SHA256

actual class Secp256k1Lib {
actual fun createPublicKey(privateKey: ByteArray, compressed: Boolean): ByteArray {
val publicKey = Secp256k1Native.pubkeyCreate(privateKey)
if (compressed) {
return Secp256k1().publicKeyCompress(publicKey)
val pubKey = Secp256k1Native.pubkeyCreate(privateKey)
if (Secp256k1Helper.validatePublicKey(pubKey)) {
if (compressed) {
return Secp256k1Native.pubKeyCompress(pubKey)
}
return pubKey
} else {
throw Secp256k1Exception("invalid public key")
}
return publicKey
}

actual fun derivePrivateKey(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import io.iohk.atala.prism.apollo.hashing.SHA256
actual class Secp256k1Lib {
actual fun createPublicKey(privateKey: ByteArray, compressed: Boolean): ByteArray {
val pubKey = Secp256k1.pubkeyCreate(privateKey)
if (compressed) {
return Secp256k1.pubKeyCompress(pubKey)
if (Secp256k1Helper.validatePublicKey(pubKey)) {
if (compressed) {
return Secp256k1.pubKeyCompress(pubKey)
}
return pubKey
} else {
throw Secp256k1Exception("invalid public key")
}
return pubKey
}

actual fun derivePrivateKey(
Expand Down
6 changes: 5 additions & 1 deletion secp256k1-kmp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ plugins {
kotlin {
explicitApi()

val commonMain by sourceSets.getting
val commonMain by sourceSets.getting {
dependencies {
api("com.ionspin.kotlin:bignum:0.3.7")
}
}

jvm {
compilations.all {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,17 @@ public interface Secp256k1 {
* Serialize a public key to compact form (33 bytes).
*/
public fun pubKeyCompress(pubkey: ByteArray): ByteArray {
return when {
pubkey.size == 33 && (pubkey[0] == 2.toByte() || pubkey[0] == 3.toByte()) -> pubkey
pubkey.size == 65 && pubkey[0] == 4.toByte() -> {
val compressed = pubkey.copyOf(33)
compressed[0] = if (pubkey.last() % 2 == 0) 2.toByte() else 3.toByte()
compressed
val pubKey =
when {
pubkey.size == 33 && (pubkey[0] == 2.toByte() || pubkey[0] == 3.toByte()) -> pubkey
pubkey.size == 65 && pubkey[0] == 4.toByte() -> {
val compressed = pubkey.copyOf(33)
compressed[0] = if (pubkey.last() % 2 == 0) 2.toByte() else 3.toByte()
compressed
}
else -> throw Secp256k1Exception("invalid public key")
}
else -> throw Secp256k1Exception("invalid public key")
}
return pubKey
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ public object Secp256k1Native : Secp256k1 {
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
val nData = toNat(data)
val nSig = toNat(signature)
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32u, pubkey.ptr) == 1
}
}

Expand All @@ -252,7 +252,7 @@ public object Secp256k1Native : Secp256k1 {
return nSig.readBytes(64)
}
}

public override fun cleanup() {
secp256k1_context_destroy(ctx)
}
Expand Down

0 comments on commit 8eb52b5

Please sign in to comment.