nim-secp256k1/tests/test_secp256k1.nim

109 lines
3.2 KiB
Nim

import
../secp256k1,
unittest,
stew/ptrops
{.used.}
const
msg0 = SkMessage([
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,
])
msg1 = SkMessage([
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] = [
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
true
proc brokenRng(data: var openArray[byte]): bool = false
suite "secp256k1":
test "Key ops":
let
sk = SkSecretKey.random(workingRng).expect("should get a key")
pk = sk.toPublicKey()
check:
SkSecretKey.fromRaw(sk.toRaw())[].toHex() == sk.toHex()
SkSecretKey.fromHex(sk.toHex())[].toHex() == sk.toHex()
SkPublicKey.fromRaw(pk.toRaw())[].toHex() == pk.toHex()
SkPublicKey.fromRaw(pk.toRawCompressed())[].toHex() == pk.toHex()
SkPublicKey.fromHex(pk.toHex())[].toHex() == pk.toHex()
SkXOnlyPublicKey.fromRaw(pk.toXOnly.toRaw())[].toHex() == pk.toXOnly.toHex()
SkXOnlyPublicKey.fromHex(pk.toXOnly.toHex())[].toHex() == pk.toXOnly.toHex()
SkSecretKey.random(brokenRng).isErr
test "Signatures":
let
sk = SkSecretKey.random(workingRng)[]
pk = sk.toPublicKey()
otherPk = SkSecretKey.random(workingRng)[].toPublicKey()
sig = sign(sk, msg0)
sig2 = signRecoverable(sk, msg0)
sig3 = signSchnorr(sk, msg0, workingRng)[]
sig4 = signSchnorr(sk, cast[array[SkMessageSize, byte]](msg0), workingRng)[]
sig5 = signSchnorr(sk, msg2, workingRng)[]
check:
verify(sig, msg0, pk)
not verify(sig, msg0, otherPk)
not verify(sig, msg1, pk)
recover(sig2, msg0)[] == pk
recover(sig2, msg1)[] != pk
SkSignature.fromDer(sig.toDer())[].toHex() == sig.toHex()
verify(sig3, msg0, pk)
sig3 == sig4
verify(sig5, msg2, pk)
test "Message":
check:
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)