Remove ttmath and allow compilation to C, change "private" field names.
This commit is contained in:
parent
98e8886f86
commit
92bdd41643
|
@ -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
|
||||
|
||||
|
@ -30,8 +30,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]
|
||||
|
@ -67,4 +67,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
|
||||
|
|
|
@ -41,14 +41,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"
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -57,8 +59,8 @@ let
|
|||
pubkey: "347746ccb908e583927285fa4bd202f08e2f82f09c920233d89c47c79e48f937d049130e3d1c14cf7b21afefc057f71da73dec8e8ff74ff47dc6a574ccd5d570",
|
||||
raw_sig: (
|
||||
v: 1,
|
||||
r: "41741612198399299636429810387160790514780876799439767175315078161978521003886",
|
||||
s: "47545396818609319588074484786899049290652725314938191835667190243225814114102"
|
||||
r: "5C48EA4F0F2257FA23BD25E6FCB0B75BBE2FF9BBDA0167118DAB2BB6E31BA76E", # Decimal "41741612198399299636429810387160790514780876799439767175315078161978521003886",
|
||||
s: "691DBDAF2A231FC9958CD8EDD99507121F8184042E075CF10F98BA88ABFF1F36" # Decimal "47545396818609319588074484786899049290652725314938191835667190243225814114102"
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -67,7 +69,7 @@ let
|
|||
pubkey: "c06641f0d04f64dba13eac9e52999f2d10a1ff0ca68975716b6583dee0318d91e7c2aed363ed22edeba2215b03f6237184833fd7d4ad65f75c2c1d5ea0abecc0",
|
||||
raw_sig: (
|
||||
v: 0,
|
||||
r: "84467545608142925331782333363288012579669270632210954476013542647119929595395",
|
||||
s: "43529886636775750164425297556346136250671451061152161143648812009114516499167"
|
||||
r: "BABEEFC5082D3CA2E0BC80532AB38F9CFB196FB9977401B2F6A98061F15ED603", # Decimal "84467545608142925331782333363288012579669270632210954476013542647119929595395",
|
||||
s: "603D0AF084BF906B2CDF6CDDE8B2E1C3E51A41AF5E9ADEC7F3643B3F1AA2AADF" # Decimal "43529886636775750164425297556346136250671451061152161143648812009114516499167"
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
@ -19,9 +19,9 @@ suite "Test key and signature data structure":
|
|||
pk = initPrivateKey(person.privkey)
|
||||
signature = pk.sign_msg(MSG)
|
||||
|
||||
check: signature.v == person.raw_sig.v
|
||||
check: signature.r == person.raw_sig.r.u256
|
||||
check: signature.s == person.raw_sig.s.u256
|
||||
check: signature.Fv == person.raw_sig.v
|
||||
check: signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
|
||||
check: 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]:
|
||||
|
@ -29,7 +29,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":
|
||||
|
||||
|
@ -38,9 +38,9 @@ suite "Test key and signature data structure":
|
|||
pk = initPrivateKey(person.privkey)
|
||||
signature = pk.sign_msg(MSG)
|
||||
|
||||
check: signature.v == person.raw_sig.v
|
||||
check: signature.r == person.raw_sig.r.u256
|
||||
check: signature.s == person.raw_sig.s.u256
|
||||
check: signature.Fv == person.raw_sig.v
|
||||
check: signature.Fr == hexToByteArrayBE[32](person.raw_sig.r)
|
||||
check: 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]:
|
||||
|
@ -48,7 +48,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]:
|
||||
|
@ -58,7 +58,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]:
|
||||
|
@ -68,4 +68,4 @@ 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
|
||||
|
|
|
@ -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…
Reference in New Issue