mirror of
https://github.com/status-im/nim-eth-keys.git
synced 2025-02-17 11:46:40 +00:00
parent
6383b00bc2
commit
b4f513c847
@ -9,7 +9,7 @@ srcDir = "src"
|
||||
|
||||
requires "nim >= 0.18.0", "keccak_tiny >= 0.1.0", "ttmath >= 0.1.0", "nimSHA2", "secp256k1"
|
||||
|
||||
proc test(name: string, lang: string = "cpp") =
|
||||
proc test(name: string, lang: string = "c") =
|
||||
if not dirExists "build":
|
||||
mkDir "build"
|
||||
if not dirExists "nimcache":
|
||||
@ -19,9 +19,12 @@ proc test(name: string, lang: string = "cpp") =
|
||||
switch("out", ("./build/" & name))
|
||||
setCommand lang, "tests/" & name & ".nim"
|
||||
|
||||
task test, "Run all tests - libsecp256k1 backend":
|
||||
task test, "Run all tests - C & libsecp256k1 backend":
|
||||
test "all_tests"
|
||||
|
||||
task test_cpp, "Run all tests - C++ & libsecp256k1 backend":
|
||||
test "all_tests", "cpp"
|
||||
|
||||
task test_backend_native, "Run all tests - pure Nim backend":
|
||||
switch("define", "backend_native")
|
||||
test "all_tests"
|
||||
test "all_tests", "cpp"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ../datatypes
|
||||
import ../datatypes, ../private/conversion_bytes
|
||||
import secp256k1, keccak_tiny
|
||||
|
||||
const SECP256K1_CONTEXT_ALL = SECP256K1_CONTEXT_VERIFY or SECP256K1_CONTEXT_SIGN
|
||||
|
@ -8,42 +8,19 @@
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ./private/conversion_bytes
|
||||
export toHex, hexToByteArrayBE, hexToSeqByteBE
|
||||
|
||||
|
||||
# Note: Fields are intentionally kept private
|
||||
# Note: Fields F should be private, it is intentionally ugly to directly access them
|
||||
# See private field access issue: https://github.com/nim-lang/Nim/issues/7390
|
||||
type
|
||||
PublicKey* = object
|
||||
Fraw_key: array[64, byte]
|
||||
Fraw_key*: array[64, byte]
|
||||
|
||||
PrivateKey* = object
|
||||
Fraw_key: array[32, byte]
|
||||
Fpublic_key: PublicKey
|
||||
Fraw_key*: array[32, byte]
|
||||
Fpublic_key*: PublicKey
|
||||
|
||||
Signature* {.packed.}= object
|
||||
Fr: array[32, byte]
|
||||
Fs: array[32, byte]
|
||||
Fv: range[0.byte .. 1.byte]
|
||||
Fr*: array[32, byte]
|
||||
Fs*: array[32, byte]
|
||||
Fv*: range[0.byte .. 1.byte] # This should be 27..28 as per Ethereum but it's 0..1 in eth-keys ...
|
||||
|
||||
|
||||
# "Public" accessors, only exposed to internal modules
|
||||
|
||||
template genAccessors(name: untyped, fieldType, objType: typedesc): untyped =
|
||||
# Access
|
||||
proc name*(obj: objType): fieldType {.noSideEffect, inline, noInit.} =
|
||||
obj.`F name`
|
||||
|
||||
# Assignement
|
||||
proc `name=`*(obj: var objType, value: fieldType): fieldType {.noSideEffect, inline.} =
|
||||
obj.`F name` = value
|
||||
|
||||
# Mutable
|
||||
proc `name`*(obj: var objType): var fieldType {.noSideEffect, inline.} =
|
||||
obj.`F name`
|
||||
|
||||
genAccessors(raw_key, array[64, byte], PublicKey)
|
||||
genAccessors(raw_key, array[32, byte], PrivateKey)
|
||||
genAccessors(public_key, PublicKey, PrivateKey)
|
||||
genAccessors(s, array[32, byte], Signature)
|
||||
genAccessors(r, array[32, byte], Signature)
|
||||
genAccessors(v, range[0.byte .. 1.byte], Signature)
|
||||
|
@ -13,7 +13,7 @@
|
||||
# Note: for now only a native pure Nim backend is supported
|
||||
# In the future alternative, proven crypto backend will be added like libsecpk1
|
||||
|
||||
import ./datatypes
|
||||
import ./datatypes, ./private/conversion_bytes
|
||||
|
||||
import keccak_tiny
|
||||
|
||||
@ -31,8 +31,8 @@ else:
|
||||
# Initialization
|
||||
|
||||
proc initPrivateKey*(hexString: string): PrivateKey {.noInit.} =
|
||||
hexToByteArrayBE(hexString, result.raw_key)
|
||||
result.public_key = private_key_to_public_key(result)
|
||||
hexToByteArrayBE(hexString, result.Fraw_key)
|
||||
result.Fpublic_key = private_key_to_public_key(result)
|
||||
|
||||
proc initPublicKey*(hexString: string): PublicKey {.noInit.} =
|
||||
var b: array[65, byte]
|
||||
@ -68,4 +68,4 @@ proc sign_msg*(key: PrivateKey, message_hash: Hash[256]): Signature {.inline.} =
|
||||
ecdsa_sign(key, message_hash)
|
||||
|
||||
proc `$`*(key: PrivateKey): string {.inline.} =
|
||||
key.raw_key.toHex()
|
||||
key.Fraw_key.toHex()
|
||||
|
@ -9,9 +9,15 @@
|
||||
|
||||
when defined(backend_native):
|
||||
echo "\nBackend tested: native\n"
|
||||
when defined(c):
|
||||
{.fatal: "The native backend require C++ compilation for ttmath.}".}
|
||||
else:
|
||||
echo "\nBackend tested: libsecp256k1\n"
|
||||
when not defined(cpp):
|
||||
echo "C backend chosen. Skipping ttmath_hex_bytes_conversion test"
|
||||
|
||||
import ./test_hex_bytes_conversion,
|
||||
./test_private_public_key_consistency,
|
||||
when defined(cpp):
|
||||
import ./test_ttmath_hex_bytes_conversion
|
||||
|
||||
import ./test_private_public_key_consistency,
|
||||
./test_key_and_signature_datastructures
|
||||
|
@ -42,14 +42,16 @@ let
|
||||
MSG* = "message"
|
||||
MSGHASH* = keccak256(MSG)
|
||||
|
||||
# Conversion done through https://www.mobilefish.com/services/big_number/big_number.php
|
||||
|
||||
let
|
||||
alice* = testKeySig(
|
||||
privkey: "9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501",
|
||||
pubkey: "5eed5fa3a67696c334762bb4823e585e2ee579aba3558d9955296d6c04541b426078dbd48d74af1fd0c72aa1a05147cf17be6b60bdbed6ba19b08ec28445b0ca",
|
||||
raw_sig: (
|
||||
v: 1,
|
||||
r: "80536744857756143861726945576089915884233437828013729338039544043241440681784",
|
||||
s: "1902566422691403459035240420865094128779958320521066670269403689808757640701"
|
||||
r: "B20E2EA5D3CBAA83C1E0372F110CF12535648613B479B64C1A8C1A20C5021F38", # Decimal "80536744857756143861726945576089915884233437828013729338039544043241440681784",
|
||||
s: "434D07EC5795E3F789794351658E80B7FAF47A46328F41E019D7B853745CDFD" # Decimal "1902566422691403459035240420865094128779958320521066670269403689808757640701"
|
||||
),
|
||||
serialized_sig: "b20e2ea5d3cbaa83c1e0372f110cf12535648613b479b64c1a8c1a20c5021f380434d07ec5795e3f789794351658e80b7faf47a46328f41e019d7b853745cdfd01"
|
||||
)
|
||||
@ -59,8 +61,8 @@ let
|
||||
pubkey: "347746ccb908e583927285fa4bd202f08e2f82f09c920233d89c47c79e48f937d049130e3d1c14cf7b21afefc057f71da73dec8e8ff74ff47dc6a574ccd5d570",
|
||||
raw_sig: (
|
||||
v: 1,
|
||||
r: "41741612198399299636429810387160790514780876799439767175315078161978521003886",
|
||||
s: "47545396818609319588074484786899049290652725314938191835667190243225814114102"
|
||||
r: "5C48EA4F0F2257FA23BD25E6FCB0B75BBE2FF9BBDA0167118DAB2BB6E31BA76E", # Decimal "41741612198399299636429810387160790514780876799439767175315078161978521003886",
|
||||
s: "691DBDAF2A231FC9958CD8EDD99507121F8184042E075CF10F98BA88ABFF1F36" # Decimal "47545396818609319588074484786899049290652725314938191835667190243225814114102"
|
||||
),
|
||||
serialized_sig: "5c48ea4f0f2257fa23bd25e6fcb0b75bbe2ff9bbda0167118dab2bb6e31ba76e691dbdaf2a231fc9958cd8edd99507121f8184042e075cf10f98ba88abff1f3601"
|
||||
)
|
||||
@ -70,8 +72,8 @@ let
|
||||
pubkey: "c06641f0d04f64dba13eac9e52999f2d10a1ff0ca68975716b6583dee0318d91e7c2aed363ed22edeba2215b03f6237184833fd7d4ad65f75c2c1d5ea0abecc0",
|
||||
raw_sig: (
|
||||
v: 0,
|
||||
r: "84467545608142925331782333363288012579669270632210954476013542647119929595395",
|
||||
s: "43529886636775750164425297556346136250671451061152161143648812009114516499167"
|
||||
r: "BABEEFC5082D3CA2E0BC80532AB38F9CFB196FB9977401B2F6A98061F15ED603", # Decimal "84467545608142925331782333363288012579669270632210954476013542647119929595395",
|
||||
s: "603D0AF084BF906B2CDF6CDDE8B2E1C3E51A41AF5E9ADEC7F3643B3F1AA2AADF" # Decimal "43529886636775750164425297556346136250671451061152161143648812009114516499167"
|
||||
),
|
||||
serialized_sig: "babeefc5082d3ca2e0bc80532ab38f9cfb196fb9977401b2f6a98061f15ed603603d0af084bf906b2cdf6cdde8b2e1c3e51a41af5e9adec7f3643b3f1aa2aadf00"
|
||||
)
|
||||
|
@ -7,7 +7,7 @@
|
||||
#
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ../src/eth_keys,
|
||||
import ../src/eth_keys, ../src/private/conversion_bytes,
|
||||
./config
|
||||
|
||||
import unittest
|
||||
@ -20,9 +20,9 @@ suite "Test key and signature data structure":
|
||||
signature = pk.sign_msg(MSG)
|
||||
|
||||
check:
|
||||
signature.v == person.raw_sig.v
|
||||
signature.r == person.raw_sig.r.u256
|
||||
signature.s == person.raw_sig.s.u256
|
||||
signature.Fv == person.raw_sig.v
|
||||
signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
|
||||
signature.Fs == hexToByteArrayBE[32](person.raw_sig.s)
|
||||
|
||||
test "Signing from private key object (ported from official eth-keys)":
|
||||
for person in [alice, bob, eve]:
|
||||
@ -30,7 +30,7 @@ suite "Test key and signature data structure":
|
||||
pk = initPrivateKey(person.privkey)
|
||||
signature = pk.sign_msg(MSG)
|
||||
|
||||
check: verify_msg(pk.public_key, MSG, signature)
|
||||
check: verify_msg(pk.Fpublic_key, MSG, signature)
|
||||
|
||||
test "Hash signing from private key object":
|
||||
for person in [alice, bob, eve]:
|
||||
@ -39,9 +39,9 @@ suite "Test key and signature data structure":
|
||||
signature = pk.sign_msg(MSG)
|
||||
|
||||
check:
|
||||
signature.v == person.raw_sig.v
|
||||
signature.r == person.raw_sig.r.u256
|
||||
signature.s == person.raw_sig.s.u256
|
||||
signature.Fv == person.raw_sig.v
|
||||
signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
|
||||
signature.Fs == hexToByteArrayBE[32](person.raw_sig.s)
|
||||
|
||||
test "Hash signing from private key object (ported from official eth-keys)":
|
||||
for person in [alice, bob, eve]:
|
||||
@ -49,7 +49,7 @@ suite "Test key and signature data structure":
|
||||
pk = initPrivateKey(person.privkey)
|
||||
signature = pk.sign_msg(MSGHASH)
|
||||
|
||||
check: verify_msg(pk.public_key, MSGHASH, signature)
|
||||
check: verify_msg(pk.Fpublic_key, MSGHASH, signature)
|
||||
|
||||
test "Recover public key from message":
|
||||
for person in [alice, bob, eve]:
|
||||
@ -59,7 +59,7 @@ suite "Test key and signature data structure":
|
||||
|
||||
recovered_pubkey = recover_pubkey_from_msg(MSG, signature)
|
||||
|
||||
check: pk.public_key == recovered_pubkey
|
||||
check: pk.Fpublic_key == recovered_pubkey
|
||||
|
||||
test "Recover public key from message hash":
|
||||
for person in [alice, bob, eve]:
|
||||
@ -69,7 +69,7 @@ suite "Test key and signature data structure":
|
||||
|
||||
recovered_pubkey = recover_pubkey_from_msg(MSGHASH, signature)
|
||||
|
||||
check: pk.public_key == recovered_pubkey
|
||||
check: pk.Fpublic_key == recovered_pubkey
|
||||
|
||||
test "Signature serialization and deserialization":
|
||||
for person in [alice, bob, eve]:
|
||||
|
@ -17,6 +17,6 @@ suite "Testing private -> public key conversion":
|
||||
for person in [alice, bob, eve]:
|
||||
let privkey = initPrivateKey(person.privkey)
|
||||
|
||||
let computed_pubkey = $privkey.public_key
|
||||
let computed_pubkey = $privkey.Fpublic_key
|
||||
|
||||
check: computed_pubkey == person.pubkey
|
||||
check: computed_pubkey == person.pubkey
|
||||
|
@ -10,6 +10,7 @@
|
||||
import ../src/private/[conversion_bytes, conversion_ttmath]
|
||||
import unittest, ttmath, strutils # TODO remove ttmath needs if backend libsecp256k1
|
||||
|
||||
import ./config
|
||||
|
||||
suite "Testing conversion functions: Hex, Bytes, Endianness":
|
||||
let
|
||||
@ -27,3 +28,19 @@ suite "Testing conversion functions: Hex, Bytes, Endianness":
|
||||
|
||||
test "uint256 -> big-endian array -> hex":
|
||||
check: SECPK1_N.toByteArrayBE.toHex == SECPK1_N_HEX
|
||||
|
||||
suite "Confirming consistency: hex vs decimal conversion":
|
||||
# Conversion done through https://www.mobilefish.com/services/big_number/big_number.php
|
||||
|
||||
test "Alice signature":
|
||||
check: alice.raw_sig.r.hexToUInt256 == "80536744857756143861726945576089915884233437828013729338039544043241440681784".u256
|
||||
check: alice.raw_sig.s.hexToUInt256 == "1902566422691403459035240420865094128779958320521066670269403689808757640701".u256
|
||||
|
||||
test "Bob signature":
|
||||
check: alice.raw_sig.r.hexToUInt256 == "41741612198399299636429810387160790514780876799439767175315078161978521003886".u256
|
||||
check: alice.raw_sig.s.hexToUInt256 == "47545396818609319588074484786899049290652725314938191835667190243225814114102".u256
|
||||
|
||||
test "Eve signature":
|
||||
check: alice.raw_sig.r.hexToUInt256 == "84467545608142925331782333363288012579669270632210954476013542647119929595395".u256
|
||||
check: alice.raw_sig.s.hexToUInt256 == "43529886636775750164425297556346136250671451061152161143648812009114516499167".u256
|
||||
|
Loading…
x
Reference in New Issue
Block a user