Get rid of ecdhRaw and export ecdh with custom hash func

This commit is contained in:
jangko 2023-04-20 10:09:47 +07:00
parent 05b4bde6d0
commit 206e5360b8
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
4 changed files with 55 additions and 49 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ nimble.paths
ci/build_nim.sh
ci/NimBinaries/
ci/nim/
*.exe

View File

@ -72,9 +72,6 @@ const
SkEdchSecretSize* = 32
## ECDH-agreed key size
SkEcdhRawSecretSize* = 33
## ECDH-agreed raw key size
type
SkPublicKey* {.requiresInit.} = object
## Representation of public key.
@ -116,10 +113,7 @@ type
## Representation of ECDH shared secret
data*: array[SkEdchSecretSize, byte]
SkEcdhRawSecret* {.requiresInit.} = object
## Representation of ECDH shared secret, with leading `y` byte
# (`y` is 0x02 when pubkey.y is even or 0x03 when odd)
data*: array[SkEcdhRawSecretSize, byte]
SkEcdhHashFunc* = secp256k1_ecdh_hash_function
SkResult*[T] = Result[T, cstring]
@ -607,26 +601,26 @@ func recover*(sig: SkRecoverableSignature, msg: SkMessage): SkResult[SkPublicKey
ok(SkPublicKey(data: data))
func ecdh*(seckey: SkSecretKey, pubkey: SkPublicKey): SkEcdhSecret =
func ecdh*(seckey: SkSecretKey, pubkey: SkPublicKey): SkResult[SkEcdhSecret] =
## Calculate ECDH shared secret.
var secret {.noinit.}: array[SkEdchSecretSize, byte]
let res = secp256k1_ecdh(
if secp256k1_ecdh(
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
seckey.data.baseAddr)
doAssert res == 1, "cannot compute ECDH secret, keys invalid?"
seckey.data.baseAddr) != 1:
return err("cannot compute ECDH secret, keys invalid?")
SkEcdhSecret(data: secret)
ok(SkEcdhSecret(data: secret))
func ecdhRaw*(seckey: SkSecretKey, pubkey: SkPublicKey): SkEcdhRawSecret =
## Calculate ECDH shared secret, ethereum style
# TODO - deprecate: https://github.com/status-im/nim-eth/issues/222
var secret {.noinit.}: array[SkEcdhRawSecretSize, byte]
let res = secp256k1_ecdh_raw(
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
seckey.data.baseAddr)
doAssert res == 1, "cannot compute raw ECDH secret, keys invalid?"
func ecdh*[N: static[int]](seckey: SkSecretKey, pubkey: SkPublicKey,
hashfn: SkEcdhHashFunc, data: pointer): SkResult[array[N, byte]] =
## Calculate ECDH shared secret using custom hash function.
var secret {.noinit.}: array[N, byte]
if secp256k1_ecdh(
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
seckey.data.baseAddr, hashfn, data) != 1:
return err("cannot compute ECDH secret, keys invalid?")
SkEcdhRawSecret(data: secret)
ok(secret)
func clear*(v: var SkSecretKey) =
## Wipe and clear memory of Secp256k1 `private key`.
@ -640,12 +634,6 @@ func clear*(v: var SkEcdhSecret) =
## result in undefined behaviour or Defect
burnMem(v.data)
func clear*(v: var SkEcdhRawSecret) =
## Wipe and clear memory of ECDH `shared secret`.
## After calling this function, the key is invalid and using it elsewhere will
## result in undefined behaviour or Defect
burnMem(v.data)
func `$`*(
v: SkPublicKey | SkSecretKey | SkXOnlyPublicKey | SkSignature | SkRecoverableSignature | SkSchnorrSignature): string =
toHex(v)
@ -665,7 +653,6 @@ proc default*(T: type SkSignature): T {.error: "loophole".}
proc default*(T: type SkRecoverableSignature): T {.error: "loophole".}
proc default*(T: type SkSchnorrSignature): T {.error: "loophole".}
proc default*(T: type SkEcdhSecret): T {.error: "loophole".}
proc default*(T: type SkEcdhRawSecret): T {.error: "loophole".}
func tweakAdd*(secretKey: var SkSecretKey, tweak: openArray[byte]): SkResult[void] =
let res = secp256k1_ec_privkey_tweak_add(

View File

@ -35,7 +35,7 @@ type
secp256k1_ecdh_hash_function* = proc (output: ptr byte,
x32, y32: ptr byte,
data: pointer) {.cdecl, raises: [].}
data: pointer): cint {.cdecl, raises: [].}
secp256k1_context* = object
secp256k1_scratch_space* = object
@ -312,23 +312,6 @@ template secp256k1_ecdh*(ctx: ptr secp256k1_context; output32: ptr byte;
secp256k1_ecdh(ctx, output32, pubkey, privkey,
secp256k1_ecdh_hash_function_default(), nil)
proc secp256k1_ecdh_raw*(ctx: ptr secp256k1_context; output32: ptr byte;
pubkey: ptr secp256k1_pubkey;
input32: ptr byte): cint {.secp.}
## Compute an EC Diffie-Hellman secret in constant time
## Returns: 1: exponentiation was successful
## 0: scalar was invalid (zero or overflow)
## Args: ctx: pointer to a context object (cannot be NULL)
## Out: result: a 33-byte array which will be populated by an ECDH
## secret computed from the point and scalar in form
## of compressed point
## In: pubkey: a pointer to a secp256k1_pubkey containing an
## initialized public key
## privkey: a 32-byte scalar with which to multiply the point
##
## Multikey interface follows
type
secp256k1_xonly_pubkey* = object
## Opaque data structure that holds a parsed and valid "x-only" public key.

View File

@ -1,4 +1,7 @@
import ../secp256k1, unittest
import
../secp256k1,
unittest,
stew/ptrops
{.used.}
@ -15,13 +18,13 @@ const
1'u8, 0, 0, 0, 0, 0, 0, 0,
1'u8, 0, 0, 0, 0, 0, 0, 0,
])
msg2 = array[40, byte]([
msg2: array[40, byte] = [
0'u8, 0, 0, 0, 0, 0, 0, 0,
0'u8, 0, 0, 0, 0, 0, 0, 0,
0'u8, 0, 0, 0, 0, 0, 0, 0,
0'u8, 0, 0, 0, 0, 0, 0, 0,
0'u8, 0, 0, 0, 0, 0, 0, 0,
])
]
proc workingRng(data: var openArray[byte]): bool =
data[0] += 1
@ -72,3 +75,34 @@ suite "secp256k1":
SkMessage.fromBytes([]).isErr()
SkMessage.fromBytes([0'u8]).isErr()
SkMessage.fromBytes(array[32, byte](msg0)).isOk()
test "Custom hash function":
proc customHash(output: ptr byte, x32, y32: ptr byte, data: pointer): cint
{.cdecl, raises: [].} =
# Save x and y as uncompressed public key
output[] = 0x04
copyMem(output.offset(1), x32, 32)
copyMem(output.offset(33), y32, 32)
return 1
proc skone(_: type SkSecretKey): SkSecretKey =
# silence noisy warning: Cannot prove that 'result' is initialized.
result = SkSecretKey.random(workingRng)[]
var data: array[SkRawSecretKeySize, byte]
zeroMem(data[0].addr, data.len)
data[31] = 1
copyMem(result.addr, data[0].addr, data.len)
let
sone = SkSecretKey.skone()
sb32 = SkSecretKey.random(workingRng)[]
pk0 = sone.toPublicKey
pk1 = sb32.toPublicKey
var
# compute using ECDH function with custom hash function
outputEcdh = ecdh[65](sb32, pk0, customHash, nil).get
# compute "explicitly"
pointSer = pk1.toRaw
check equalMem(outputEcdh.addr, pointSer.addr, 65)