mirror of https://github.com/vacp2p/nim-libp2p.git
Add raw init functions for ecnist.nim
Add ECDHE helpers for ecnist.nim Add test vectors for ECDHE.
This commit is contained in:
parent
411d9f0b9c
commit
14686714c0
|
@ -549,7 +549,7 @@ proc init*(sig: var EcSignature, data: openarray[byte]): Asn1Status =
|
||||||
|
|
||||||
proc init*[T: EcPKI](sospk: var T, data: string): Asn1Status {.inline.} =
|
proc init*[T: EcPKI](sospk: var T, data: string): Asn1Status {.inline.} =
|
||||||
## Initialize EC `private key`, `public key` or `signature` ``sospk`` from
|
## Initialize EC `private key`, `public key` or `signature` ``sospk`` from
|
||||||
## hexadecimal string representation ``data``.
|
## ASN.1 DER hexadecimal string representation ``data``.
|
||||||
##
|
##
|
||||||
## Procedure returns ``Asn1Status``.
|
## Procedure returns ``Asn1Status``.
|
||||||
result = sospk.init(fromHex(data))
|
result = sospk.init(fromHex(data))
|
||||||
|
@ -583,6 +583,114 @@ proc init*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
|
||||||
## string representation ``data`` and return constructed object.
|
## string representation ``data`` and return constructed object.
|
||||||
result = t.init(fromHex(data))
|
result = t.init(fromHex(data))
|
||||||
|
|
||||||
|
proc initRaw*(key: var EcPrivateKey, data: openarray[byte]): bool =
|
||||||
|
## Initialize EC `private key` or `scalar` ``key`` from raw binary
|
||||||
|
## representation ``data``.
|
||||||
|
##
|
||||||
|
## Length of ``data`` array must be ``SecKey256Length``, ``SecKey384Length``
|
||||||
|
## or ``SecKey521Length``.
|
||||||
|
##
|
||||||
|
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||||
|
var curve: cint
|
||||||
|
if len(data) == SecKey256Length:
|
||||||
|
curve = cast[cint](Secp256r1)
|
||||||
|
result = true
|
||||||
|
elif len(data) == SecKey384Length:
|
||||||
|
curve = cast[cint](Secp384r1)
|
||||||
|
result = true
|
||||||
|
elif len(data) == SecKey521Length:
|
||||||
|
curve = cast[cint](Secp521r1)
|
||||||
|
result = true
|
||||||
|
if result:
|
||||||
|
result = false
|
||||||
|
if checkScalar(data, curve) == 1'u32:
|
||||||
|
let length = len(data)
|
||||||
|
key = new EcPrivateKey
|
||||||
|
key.buffer = newSeq[byte](length)
|
||||||
|
copyMem(addr key.buffer[0], unsafeAddr data[0], length)
|
||||||
|
key.key.x = cast[ptr cuchar](addr key.buffer[0])
|
||||||
|
key.key.xlen = length
|
||||||
|
key.key.curve = curve
|
||||||
|
result = true
|
||||||
|
|
||||||
|
proc initRaw*(pubkey: var EcPublicKey, data: openarray[byte]): bool =
|
||||||
|
## Initialize EC public key ``pubkey`` from raw binary representation
|
||||||
|
## ``data``.
|
||||||
|
##
|
||||||
|
## Length of ``data`` array must be ``PubKey256Length``, ``PubKey384Length``
|
||||||
|
## or ``PubKey521Length``.
|
||||||
|
##
|
||||||
|
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||||
|
var curve: cint
|
||||||
|
if len(data) > 0:
|
||||||
|
if data[0] == 0x04'u8:
|
||||||
|
if len(data) == PubKey256Length:
|
||||||
|
curve = cast[cint](Secp256r1)
|
||||||
|
result = true
|
||||||
|
elif len(data) == PubKey384Length:
|
||||||
|
curve = cast[cint](Secp384r1)
|
||||||
|
result = true
|
||||||
|
elif len(data) == PubKey521Length:
|
||||||
|
curve = cast[cint](Secp521r1)
|
||||||
|
result = true
|
||||||
|
if result:
|
||||||
|
result = false
|
||||||
|
if checkPublic(data, curve) != 0:
|
||||||
|
let length = len(data)
|
||||||
|
pubkey = new EcPublicKey
|
||||||
|
pubkey.buffer = newSeq[byte](length)
|
||||||
|
copyMem(addr pubkey.buffer[0], unsafeAddr data[0], length)
|
||||||
|
pubkey.key.q = cast[ptr cuchar](addr pubkey.buffer[0])
|
||||||
|
pubkey.key.qlen = length
|
||||||
|
pubkey.key.curve = curve
|
||||||
|
result = true
|
||||||
|
|
||||||
|
proc initRaw*(sig: var EcSignature, data: openarray[byte]): bool =
|
||||||
|
## Initialize EC signature ``sig`` from raw binary representation ``data``.
|
||||||
|
##
|
||||||
|
## Length of ``data`` array must be ``Sig256Length``, ``Sig384Length``
|
||||||
|
## or ``Sig521Length``.
|
||||||
|
##
|
||||||
|
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||||
|
var curve: cint
|
||||||
|
let length = len(data)
|
||||||
|
if (length == Sig256Length) or (length == Sig384Length) or
|
||||||
|
(length == Sig521Length):
|
||||||
|
result = true
|
||||||
|
if result:
|
||||||
|
sig = new EcSignature
|
||||||
|
sig.buffer = @data
|
||||||
|
|
||||||
|
proc initRaw*[T: EcPKI](sospk: var T, data: string): bool {.inline.} =
|
||||||
|
## Initialize EC `private key`, `public key` or `signature` ``sospk`` from
|
||||||
|
## raw hexadecimal string representation ``data``.
|
||||||
|
##
|
||||||
|
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||||
|
result = sospk.initRaw(fromHex(data))
|
||||||
|
|
||||||
|
proc initRaw*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcPrivateKey =
|
||||||
|
## Initialize EC private key from raw binary representation ``data`` and
|
||||||
|
## return constructed object.
|
||||||
|
if not result.initRaw(data):
|
||||||
|
raise newException(EcKeyIncorrectError, "Incorrect private key")
|
||||||
|
|
||||||
|
proc initRaw*(t: typedesc[EcPublicKey], data: openarray[byte]): EcPublicKey =
|
||||||
|
## Initialize EC public key from raw binary representation ``data`` and
|
||||||
|
## return constructed object.
|
||||||
|
if not result.initRaw(data):
|
||||||
|
raise newException(EcKeyIncorrectError, "Incorrect public key")
|
||||||
|
|
||||||
|
proc initRaw*(t: typedesc[EcSignature], data: openarray[byte]): EcSignature =
|
||||||
|
## Initialize EC signature from raw binary representation ``data`` and
|
||||||
|
## return constructed object.
|
||||||
|
if not result.initRaw(data):
|
||||||
|
raise newException(EcKeyIncorrectError, "Incorrect signature")
|
||||||
|
|
||||||
|
proc initRaw*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
|
||||||
|
## Initialize EC `private key`, `public key` or `signature` from raw
|
||||||
|
## hexadecimal string representation ``data`` and return constructed object.
|
||||||
|
result = t.initRaw(fromHex(data))
|
||||||
|
|
||||||
proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey =
|
proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey =
|
||||||
## Return scalar multiplication of ``pub`` and ``sec``.
|
## Return scalar multiplication of ``pub`` and ``sec``.
|
||||||
##
|
##
|
||||||
|
@ -604,6 +712,42 @@ proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey =
|
||||||
if res != 0:
|
if res != 0:
|
||||||
result = key
|
result = key
|
||||||
|
|
||||||
|
proc toSecret*(pubkey: EcPublicKey, seckey: EcPrivateKey,
|
||||||
|
data: var openarray[byte]): int =
|
||||||
|
## Calculate ECDHE shared secret using Go's elliptic/curve approach, using
|
||||||
|
## remote public key ``pubkey`` and local private key ``seckey`` and store
|
||||||
|
## shared secret to ``data``.
|
||||||
|
##
|
||||||
|
## Returns number of bytes (octets) needed to store shared secret, or ``0``
|
||||||
|
## on error.
|
||||||
|
##
|
||||||
|
## ``data`` array length must be at least 32 bytes for `secp256r1`, 48 bytes
|
||||||
|
## for `secp384r1` and 66 bytes for `secp521r1`.
|
||||||
|
var mult = scalarMul(pubkey, seckey)
|
||||||
|
var length = 0
|
||||||
|
if not isNil(mult):
|
||||||
|
if seckey.key.curve == BR_EC_SECP256R1:
|
||||||
|
result = 32
|
||||||
|
elif seckey.key.curve == BR_EC_SECP384R1:
|
||||||
|
result = 48
|
||||||
|
elif seckey.key.curve == BR_EC_SECP521R1:
|
||||||
|
result = 66
|
||||||
|
if len(data) >= result:
|
||||||
|
var qplus1 = cast[pointer](cast[uint](mult.key.q) + 1'u)
|
||||||
|
copyMem(addr data[0], qplus1, result)
|
||||||
|
|
||||||
|
proc getSecret*(pubkey: EcPublicKey, seckey: EcPrivateKey): seq[byte] =
|
||||||
|
## Calculate ECDHE shared secret using Go's elliptic curve approach, using
|
||||||
|
## remote public key ``pubkey`` and local private key ``seckey`` and return
|
||||||
|
## shared secret.
|
||||||
|
##
|
||||||
|
## If error happens length of result array will be ``0``.
|
||||||
|
var data: array[66, byte]
|
||||||
|
let res = toSecret(pubkey, seckey, data)
|
||||||
|
if res > 0:
|
||||||
|
result = newSeq[byte](res)
|
||||||
|
copyMem(addr result[0], addr data[0], res)
|
||||||
|
|
||||||
proc sign*[T: byte|char](seckey: EcPrivateKey,
|
proc sign*[T: byte|char](seckey: EcPrivateKey,
|
||||||
message: openarray[T]): EcSignature =
|
message: openarray[T]): EcSignature =
|
||||||
## Get ECDSA signature of data ``message`` using private key ``seckey``.
|
## Get ECDSA signature of data ``message`` using private key ``seckey``.
|
||||||
|
|
|
@ -229,6 +229,68 @@ const
|
||||||
C05CB9C3A2DA"""
|
C05CB9C3A2DA"""
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# ECDHE test vectors was made using Go's elliptic/curve
|
||||||
|
|
||||||
|
ECDHEPrivateKeys = [
|
||||||
|
"978edaa0671f5a37ec5372b62689e9328af71b6fb4ac3be24d195ca082b0f2fa",
|
||||||
|
"a849c80cb4f507ab24569473c2b94a84608088e7cb448816ba60d91ade3c8470",
|
||||||
|
"a23bf3eb7c515aab57974845d6b8c05c108bc7c5c68b2aa18bc9a05c4668993e",
|
||||||
|
"1b35c3c3efea9ad4e78f47063cf17bc14ddb89bd9a8980b744a19b92076ae88d",
|
||||||
|
"24c97a005fc6ce93c96f072d37bf8aeab0b97f2135845655c16df24e09cceafa",
|
||||||
|
"fa52527eb5cd88d751807d05332164a66c9ae5bc4a4c37e7f21f1f64daad19d9",
|
||||||
|
"""fab46775d806e9135f5db2ee65bc32b530b2db7a3a85f25d69ffe4f39a7f3c01
|
||||||
|
98d863ae1ed71ed3e5b9bbf882020c25""",
|
||||||
|
"""8494fb7f48c31617414fb444d3e0f28225a4ee04aee8e518cb6fece1c5603141
|
||||||
|
525bc96ef570a8361ed1abe74b467daa""",
|
||||||
|
"""760a6543f29654b9b4e7a67a328d6f61895f29df53c031dd457342ba103fe452
|
||||||
|
776791b52a4fd156e5cd0ec005a59ad0""",
|
||||||
|
"""15c44a82d4ab43cef6d8a33c01d41bfeaab21ee1aba6ecb7eff8db31c681337b
|
||||||
|
3b11e785df0c7cf2f838be395591810b""",
|
||||||
|
"""16a646076ec966b59655343875980adb7aa25dbf8480b1fad73c0a4699f9262c
|
||||||
|
bab67a8768754064afd68e1a12e405e6""",
|
||||||
|
"""bfe6d3a1e67f2e75d6204aff913b62163d6bc1ca2a281c0c6a95fbc989adddf8
|
||||||
|
836ada035aa400ba8b47480bcc7b95c3""",
|
||||||
|
"""01920b49ce0ecf2a672ca2843d300140dde242af772ec89e4ad57dadf1610bb0
|
||||||
|
912f613a3e29193a04691a5b4e8ae6130d8b610642c88f99cdd2b5b9e9269c26
|
||||||
|
1fa5""",
|
||||||
|
"""015a7286a1ecc521e49ffed6b9740b2e7ebdb3762cb6be5f4c173c26686105c5
|
||||||
|
73a06d59814c89b67c642e2fc85de46e4242565e64ec82d8ada5ac3e1ab1be4e
|
||||||
|
091f""",
|
||||||
|
"""011a8d01ac83d3f7b1ac8ef06afb75ec7c1b176cf01405686cb2ead34f8bc278
|
||||||
|
0972d2e348d49bdc0cb3fbf6414f7815aa4ea83eeed71a6a2fde7070bc074735
|
||||||
|
86c3""",
|
||||||
|
"""014c09dcf8cc8d7fe59c5b2d9edf5c6a0a42700f540f1670e46be35e7edc8ed4
|
||||||
|
01d32513cc9167a386623abd458cef9bd9facd0aa9b1d671b02c19bd71938b00
|
||||||
|
d957""",
|
||||||
|
"""0172a4ee2f85ba7ea47e0fee1410344211df58415fbac933c793d138d75c4dd1
|
||||||
|
664cfaf58e13c040f11191438dbf7394e36d7c3b2025d31af19fc6485b979a77
|
||||||
|
2f39""",
|
||||||
|
"""011b3b6ac868ae156c66b140d92092167193e88f04909be61b3592c7006296e3
|
||||||
|
cc1dab37955fea9e5ab24047c2ef717e402a88bd616ef27c68cf6976e68b6c69
|
||||||
|
b326"""
|
||||||
|
]
|
||||||
|
|
||||||
|
ECDHESecrets = [
|
||||||
|
"0e6c0eb060c5e33b7125ab72fa70b21b472b64e137ac11238da14838dfb1603c",
|
||||||
|
"1b42c4831dca82787ff4f411b3774165e788ead225bd34291d6582f714849984",
|
||||||
|
"568ff01d85d325e31ee0eafb1be4ce7695aa996c5d8d8a804052f819b4c6baae",
|
||||||
|
"""595e63e5b14747b2c87f7042122327fbf9409ccecad2d794f706e84150ea8d0d
|
||||||
|
67d0b2cdf3a7b2491db83188f64bc5c2""",
|
||||||
|
"""ad60579d3d6ab4d512d3e493d8d432fd0c5f91de61cf9375141c7521db792273
|
||||||
|
88482177eb2c96e789830ff51ffe1955""",
|
||||||
|
"""6a04cfb7cb3514b8326bac52ff09d24e320d2662b9a7964a58c1fe32c25167e5
|
||||||
|
d96dc59193b0d9a7463652a3e7096daf""",
|
||||||
|
"""0037b9b156c934a594ce991ec904c28b257de50930076b9702186c0f0c4affae
|
||||||
|
02d3c5ff1c896339dbcb9f9d11a86a4c27d705a22e4a5297cb389cbb1bf55e47
|
||||||
|
c07c""",
|
||||||
|
"""00f7916c1119c46d4c499f5c73cae3279466b104f87ef4c5092f38148b2dad84
|
||||||
|
c18ecf7ce439ec59799c086557453484b454722d23135291d9d4ffe6e1719f16
|
||||||
|
3d25""",
|
||||||
|
"""018c54bd7cb4aab23b07760c48e563a1828ff521442e5388eb62f916c33a8db2
|
||||||
|
ec8bc6a5c8c41b3ebb09f0cf66bbae602d355161c97597b088060bb8456a4458
|
||||||
|
35ab"""
|
||||||
|
]
|
||||||
|
|
||||||
suite "EC NIST-P256/384/521 test suite":
|
suite "EC NIST-P256/384/521 test suite":
|
||||||
|
|
||||||
test "[secp256r1] Private key serialize/deserialize test":
|
test "[secp256r1] Private key serialize/deserialize test":
|
||||||
|
@ -279,6 +341,21 @@ suite "EC NIST-P256/384/521 test suite":
|
||||||
isNil(shared2) == false
|
isNil(shared2) == false
|
||||||
shared1 == shared2
|
shared1 == shared2
|
||||||
|
|
||||||
|
test "[secp256r1] ECDHE test vectors":
|
||||||
|
for i in 0..<3:
|
||||||
|
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
|
||||||
|
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
|
||||||
|
var seckey1 = EcPrivateKey.initRaw(key1)
|
||||||
|
var seckey2 = EcPrivateKey.initRaw(key2)
|
||||||
|
var pubkey1 = seckey1.getKey()
|
||||||
|
var pubkey2 = seckey2.getKey()
|
||||||
|
var secret1 = getSecret(pubkey2, seckey1)
|
||||||
|
var secret2 = getSecret(pubkey1, seckey2)
|
||||||
|
var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
|
||||||
|
check:
|
||||||
|
secret1 == expsecret
|
||||||
|
secret2 == expsecret
|
||||||
|
|
||||||
test "[secp256r1] ECDSA test vectors":
|
test "[secp256r1] ECDSA test vectors":
|
||||||
for i in 0..<2:
|
for i in 0..<2:
|
||||||
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
||||||
|
@ -371,6 +448,21 @@ suite "EC NIST-P256/384/521 test suite":
|
||||||
isNil(shared2) == false
|
isNil(shared2) == false
|
||||||
shared1 == shared2
|
shared1 == shared2
|
||||||
|
|
||||||
|
test "[secp384r1] ECDHE test vectors":
|
||||||
|
for i in 3..<6:
|
||||||
|
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
|
||||||
|
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
|
||||||
|
var seckey1 = EcPrivateKey.initRaw(key1)
|
||||||
|
var seckey2 = EcPrivateKey.initRaw(key2)
|
||||||
|
var pubkey1 = seckey1.getKey()
|
||||||
|
var pubkey2 = seckey2.getKey()
|
||||||
|
var secret1 = getSecret(pubkey2, seckey1)
|
||||||
|
var secret2 = getSecret(pubkey1, seckey2)
|
||||||
|
var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
|
||||||
|
check:
|
||||||
|
secret1 == expsecret
|
||||||
|
secret2 == expsecret
|
||||||
|
|
||||||
test "[secp384r1] ECDSA test vectors":
|
test "[secp384r1] ECDSA test vectors":
|
||||||
for i in 2..<4:
|
for i in 2..<4:
|
||||||
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
||||||
|
@ -463,6 +555,21 @@ suite "EC NIST-P256/384/521 test suite":
|
||||||
isNil(shared2) == false
|
isNil(shared2) == false
|
||||||
shared1 == shared2
|
shared1 == shared2
|
||||||
|
|
||||||
|
test "[secp384r1] ECDHE test vectors":
|
||||||
|
for i in 6..<9:
|
||||||
|
var key1 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2]))
|
||||||
|
var key2 = fromHex(stripSpaces(ECDHEPrivateKeys[i * 2 + 1]))
|
||||||
|
var seckey1 = EcPrivateKey.initRaw(key1)
|
||||||
|
var seckey2 = EcPrivateKey.initRaw(key2)
|
||||||
|
var pubkey1 = seckey1.getKey()
|
||||||
|
var pubkey2 = seckey2.getKey()
|
||||||
|
var secret1 = getSecret(pubkey2, seckey1)
|
||||||
|
var secret2 = getSecret(pubkey1, seckey2)
|
||||||
|
var expsecret = fromHex(stripSpaces(ECDHESecrets[i]))
|
||||||
|
check:
|
||||||
|
secret1 == expsecret
|
||||||
|
secret2 == expsecret
|
||||||
|
|
||||||
test "[secp521r1] ECDSA test vectors":
|
test "[secp521r1] ECDSA test vectors":
|
||||||
for i in 4..<6:
|
for i in 4..<6:
|
||||||
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
var sk = EcPrivateKey.init(stripSpaces(SignatureSecKeys[i]))
|
||||||
|
|
Loading…
Reference in New Issue