Get rid of ecdhRaw and export ecdh with custom hash func
This commit is contained in:
parent
05b4bde6d0
commit
206e5360b8
|
@ -7,3 +7,5 @@ nimble.paths
|
||||||
ci/build_nim.sh
|
ci/build_nim.sh
|
||||||
ci/NimBinaries/
|
ci/NimBinaries/
|
||||||
ci/nim/
|
ci/nim/
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
|
|
@ -72,9 +72,6 @@ const
|
||||||
SkEdchSecretSize* = 32
|
SkEdchSecretSize* = 32
|
||||||
## ECDH-agreed key size
|
## ECDH-agreed key size
|
||||||
|
|
||||||
SkEcdhRawSecretSize* = 33
|
|
||||||
## ECDH-agreed raw key size
|
|
||||||
|
|
||||||
type
|
type
|
||||||
SkPublicKey* {.requiresInit.} = object
|
SkPublicKey* {.requiresInit.} = object
|
||||||
## Representation of public key.
|
## Representation of public key.
|
||||||
|
@ -116,10 +113,7 @@ type
|
||||||
## Representation of ECDH shared secret
|
## Representation of ECDH shared secret
|
||||||
data*: array[SkEdchSecretSize, byte]
|
data*: array[SkEdchSecretSize, byte]
|
||||||
|
|
||||||
SkEcdhRawSecret* {.requiresInit.} = object
|
SkEcdhHashFunc* = secp256k1_ecdh_hash_function
|
||||||
## 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]
|
|
||||||
|
|
||||||
SkResult*[T] = Result[T, cstring]
|
SkResult*[T] = Result[T, cstring]
|
||||||
|
|
||||||
|
@ -607,26 +601,26 @@ func recover*(sig: SkRecoverableSignature, msg: SkMessage): SkResult[SkPublicKey
|
||||||
|
|
||||||
ok(SkPublicKey(data: data))
|
ok(SkPublicKey(data: data))
|
||||||
|
|
||||||
func ecdh*(seckey: SkSecretKey, pubkey: SkPublicKey): SkEcdhSecret =
|
func ecdh*(seckey: SkSecretKey, pubkey: SkPublicKey): SkResult[SkEcdhSecret] =
|
||||||
## Calculate ECDH shared secret.
|
## Calculate ECDH shared secret.
|
||||||
var secret {.noinit.}: array[SkEdchSecretSize, byte]
|
var secret {.noinit.}: array[SkEdchSecretSize, byte]
|
||||||
let res = secp256k1_ecdh(
|
if secp256k1_ecdh(
|
||||||
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
|
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
|
||||||
seckey.data.baseAddr)
|
seckey.data.baseAddr) != 1:
|
||||||
doAssert res == 1, "cannot compute ECDH secret, keys invalid?"
|
return err("cannot compute ECDH secret, keys invalid?")
|
||||||
|
|
||||||
SkEcdhSecret(data: secret)
|
ok(SkEcdhSecret(data: secret))
|
||||||
|
|
||||||
func ecdhRaw*(seckey: SkSecretKey, pubkey: SkPublicKey): SkEcdhRawSecret =
|
func ecdh*[N: static[int]](seckey: SkSecretKey, pubkey: SkPublicKey,
|
||||||
## Calculate ECDH shared secret, ethereum style
|
hashfn: SkEcdhHashFunc, data: pointer): SkResult[array[N, byte]] =
|
||||||
# TODO - deprecate: https://github.com/status-im/nim-eth/issues/222
|
## Calculate ECDH shared secret using custom hash function.
|
||||||
var secret {.noinit.}: array[SkEcdhRawSecretSize, byte]
|
var secret {.noinit.}: array[N, byte]
|
||||||
let res = secp256k1_ecdh_raw(
|
if secp256k1_ecdh(
|
||||||
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
|
secp256k1_context_no_precomp, secret.baseAddr, unsafeAddr pubkey.data,
|
||||||
seckey.data.baseAddr)
|
seckey.data.baseAddr, hashfn, data) != 1:
|
||||||
doAssert res == 1, "cannot compute raw ECDH secret, keys invalid?"
|
return err("cannot compute ECDH secret, keys invalid?")
|
||||||
|
|
||||||
SkEcdhRawSecret(data: secret)
|
ok(secret)
|
||||||
|
|
||||||
func clear*(v: var SkSecretKey) =
|
func clear*(v: var SkSecretKey) =
|
||||||
## Wipe and clear memory of Secp256k1 `private key`.
|
## Wipe and clear memory of Secp256k1 `private key`.
|
||||||
|
@ -640,12 +634,6 @@ func clear*(v: var SkEcdhSecret) =
|
||||||
## result in undefined behaviour or Defect
|
## result in undefined behaviour or Defect
|
||||||
burnMem(v.data)
|
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 `$`*(
|
func `$`*(
|
||||||
v: SkPublicKey | SkSecretKey | SkXOnlyPublicKey | SkSignature | SkRecoverableSignature | SkSchnorrSignature): string =
|
v: SkPublicKey | SkSecretKey | SkXOnlyPublicKey | SkSignature | SkRecoverableSignature | SkSchnorrSignature): string =
|
||||||
toHex(v)
|
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 SkRecoverableSignature): T {.error: "loophole".}
|
||||||
proc default*(T: type SkSchnorrSignature): T {.error: "loophole".}
|
proc default*(T: type SkSchnorrSignature): T {.error: "loophole".}
|
||||||
proc default*(T: type SkEcdhSecret): 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] =
|
func tweakAdd*(secretKey: var SkSecretKey, tweak: openArray[byte]): SkResult[void] =
|
||||||
let res = secp256k1_ec_privkey_tweak_add(
|
let res = secp256k1_ec_privkey_tweak_add(
|
||||||
|
|
|
@ -35,7 +35,7 @@ type
|
||||||
|
|
||||||
secp256k1_ecdh_hash_function* = proc (output: ptr byte,
|
secp256k1_ecdh_hash_function* = proc (output: ptr byte,
|
||||||
x32, y32: ptr byte,
|
x32, y32: ptr byte,
|
||||||
data: pointer) {.cdecl, raises: [].}
|
data: pointer): cint {.cdecl, raises: [].}
|
||||||
|
|
||||||
secp256k1_context* = object
|
secp256k1_context* = object
|
||||||
secp256k1_scratch_space* = 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(ctx, output32, pubkey, privkey,
|
||||||
secp256k1_ecdh_hash_function_default(), nil)
|
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
|
type
|
||||||
secp256k1_xonly_pubkey* = object
|
secp256k1_xonly_pubkey* = object
|
||||||
## Opaque data structure that holds a parsed and valid "x-only" public key.
|
## Opaque data structure that holds a parsed and valid "x-only" public key.
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import ../secp256k1, unittest
|
import
|
||||||
|
../secp256k1,
|
||||||
|
unittest,
|
||||||
|
stew/ptrops
|
||||||
|
|
||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
|
@ -15,13 +18,13 @@ const
|
||||||
1'u8, 0, 0, 0, 0, 0, 0, 0,
|
1'u8, 0, 0, 0, 0, 0, 0, 0,
|
||||||
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,
|
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 =
|
proc workingRng(data: var openArray[byte]): bool =
|
||||||
data[0] += 1
|
data[0] += 1
|
||||||
|
@ -72,3 +75,34 @@ suite "secp256k1":
|
||||||
SkMessage.fromBytes([]).isErr()
|
SkMessage.fromBytes([]).isErr()
|
||||||
SkMessage.fromBytes([0'u8]).isErr()
|
SkMessage.fromBytes([0'u8]).isErr()
|
||||||
SkMessage.fromBytes(array[32, byte](msg0)).isOk()
|
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)
|
||||||
|
|
Loading…
Reference in New Issue