Some fixes and tests for ECIES.
This commit is contained in:
parent
f020ff4712
commit
d8c63e7da1
|
@ -26,6 +26,18 @@ const
|
|||
AuthAckMessageLength* = 210
|
||||
|
||||
type
|
||||
PlainAuthMessage* = object {.packed.}
|
||||
signature: RawSignature
|
||||
keyhash: array[keccak256.sizeDigest, byte]
|
||||
pubkey: PublicKey
|
||||
nonce: array[keccak256.sizeDigest, byte]
|
||||
flag: byte
|
||||
|
||||
PlainAuthAckMessage* = object {.packed.}
|
||||
pubkey: PublicKey
|
||||
nonce: array[keccak256.sizeDigest, byte]
|
||||
flag: byte
|
||||
|
||||
HandshakeFlag* = enum
|
||||
Initiator, ## `Handshake` owner is connection initiator
|
||||
Responder, ## `Handshake` owner is connection responder
|
||||
|
@ -62,8 +74,8 @@ type
|
|||
egressMac*: array[keccak256.sizeDigest, byte]
|
||||
ingressMac*: array[keccak256.sizeDigest, byte]
|
||||
|
||||
PlainAuthMessage* = array[PlainAuthMessageLength, byte]
|
||||
PlainAuthAckMessage* = array[PlainAuthAckMessageLength, byte]
|
||||
# PlainAuthMessage* = array[PlainAuthMessageLength, byte]
|
||||
# PlainAuthAckMessage* = array[PlainAuthAckMessageLength, byte]
|
||||
AuthMessage* = array[AuthMessageLength, byte]
|
||||
AuthAckMessage* = array[AuthAckMessageLength, byte]
|
||||
|
||||
|
@ -95,50 +107,44 @@ proc newHandshake*(flags: set[HandshakeFlag] = {Initiator}): Handshake =
|
|||
result.ephemeral = newKeyPair()
|
||||
|
||||
if Initiator in flags:
|
||||
p = addr result.initiatorNonce[0]
|
||||
if randomBytes(result.initiatorNonce) != len(result.initiatorNonce):
|
||||
raise newException(AuthException, "Could not obtain random data!")
|
||||
else:
|
||||
p = addr result.responderNonce[0]
|
||||
if randomBytes(result.responderNonce) != len(result.responderNonce):
|
||||
raise newException(AuthException, "Could not obtain random data!")
|
||||
|
||||
if randomBytes(p, KeyLength) != KeyLength:
|
||||
raise newException(AuthException, "Could not obtain random data!")
|
||||
|
||||
proc authMessage*(h: var Handshake,
|
||||
proc authMessagePreEIP8*(h: var Handshake,
|
||||
pubkey: PublicKey,
|
||||
output: var PlainAuthMessage): AuthStatus =
|
||||
output: var PlainAuthMessage,
|
||||
flag: int = 0): AuthStatus =
|
||||
## Create plain preEIP8 authentication message.
|
||||
var secret: SharedSecret
|
||||
var signature: Signature
|
||||
var flag = byte(0x00)
|
||||
var flagb = byte(flag)
|
||||
|
||||
if ecdhAgree(h.host.seckey, pubkey, secret) != EccStatus.Success:
|
||||
return(EcdhError)
|
||||
|
||||
if h.initiatorNonce.empty():
|
||||
if randomBytes(addr h.initiatorNonce[0], KeyLength) != KeyLength:
|
||||
return(RandomError)
|
||||
|
||||
var xornonce = h.initiatorNonce
|
||||
xornonce.sxor(secret)
|
||||
|
||||
if signMessage(h.ephemeral.seckey, xornonce, signature) != EccStatus.Success:
|
||||
return(SignatureError)
|
||||
|
||||
copyMem(addr h.remoteHPubkey, unsafeAddr pubkey, sizeof(PublicKey))
|
||||
h.remoteHPubkey = pubkey
|
||||
|
||||
output.signature = signature.getRaw()
|
||||
output.keyhash = keccak256.digest(h.ephemeral.pubkey.getRaw().data).data
|
||||
output.pubkey = cast[PublicKey](h.host.pubkey.getRaw().data)
|
||||
output.nonce = h.initiatorNonce
|
||||
output.flag = flagb
|
||||
|
||||
move(output, signature.getRaw().data, 0, 64)
|
||||
move(output, keccak256.digest(h.ephemeral.pubkey.getRaw().data).data, 65, 96)
|
||||
move(output, h.host.pubkey.getRaw().data, 97, 160)
|
||||
move(output, h.initiatorNonce, 161, 192)
|
||||
output[193] = flag
|
||||
|
||||
proc authAckMessage*(h: var Handshake,
|
||||
output: var PlainAuthAckMessage): AuthStatus =
|
||||
if EIP8 in h.flags:
|
||||
discard
|
||||
else:
|
||||
move(output, h.ephemeral.pubkey.getRaw().data, 0, 63)
|
||||
move(output, h.responderNonce, 64, 95)
|
||||
output[96] = byte(0x00)
|
||||
proc authAckMessagePreEIP8*(h: var Handshake,
|
||||
output: var PlainAuthAckMessage,
|
||||
flag: int = 0): AuthStatus =
|
||||
output.pubkey = cast[PublicKey](h.ephemeral.pubkey.getRaw().data)
|
||||
output.nonce = h.responderNonce
|
||||
output.flag = byte(flag)
|
||||
|
||||
proc encryptAuthMessage*(input: ptr byte, inputlen: int,
|
||||
output: ptr byte, outputlen: int,
|
||||
|
|
|
@ -16,7 +16,6 @@ const
|
|||
PublicKeyLength* = 64
|
||||
SignatureLength* = 65
|
||||
|
||||
|
||||
type
|
||||
EccContext* = ref object of RootRef
|
||||
context*: ptr secp256k1_context
|
||||
|
@ -264,7 +263,7 @@ proc newPrivateKey*(): PrivateKey =
|
|||
## Generates new secret key.
|
||||
let ctx = getSecpContext()
|
||||
while true:
|
||||
if randomBytes(addr result[0], KeyLength) == KeyLength:
|
||||
if randomBytes(result) == KeyLength:
|
||||
if secp256k1_ec_seckey_verify(ctx, cast[ptr cuchar](addr result[0])) == 1:
|
||||
break
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ proc eciesDecrypt*(input: openarray[byte],
|
|||
ctx: HMAC[sha256]
|
||||
secret: SharedSecret
|
||||
|
||||
if len(input) == 0:
|
||||
if len(input) <= 0:
|
||||
return(IncompleteError)
|
||||
|
||||
var header = cast[ptr EciesHeader](unsafeAddr input[0])
|
||||
|
@ -188,7 +188,6 @@ proc eciesDecrypt*(input: openarray[byte],
|
|||
burnMem(material)
|
||||
|
||||
let macsize = eciesMacLength(len(input) - eciesOverheadLength())
|
||||
let datsize = eciesDecryptedLength(len(input))
|
||||
ctx.init(macKey.data)
|
||||
burnMem(macKey)
|
||||
ctx.update(toOpenArray(input, eciesIvPos(), eciesIvPos() + macsize - 1))
|
||||
|
@ -201,6 +200,7 @@ proc eciesDecrypt*(input: openarray[byte],
|
|||
sha256.sizeDigest):
|
||||
return(IncorrectTag)
|
||||
|
||||
let datsize = eciesDecryptedLength(len(input))
|
||||
cipher.init(encKey, header.iv)
|
||||
burnMem(encKey)
|
||||
cipher.decrypt(toOpenArray(input, eciesDataPos(),
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import unittest
|
||||
import ethp2p/ecc, ethp2p/ecies
|
||||
import nimcrypto/utils, nimcrypto/sha2, nimcrypto/hmac
|
||||
import nimcrypto/utils, nimcrypto/sha2, nimcrypto/hmac, nimcrypto/rijndael
|
||||
|
||||
proc compare[A, B](x: openarray[A], y: openarray[B], s: int = 0): bool =
|
||||
result = true
|
||||
|
@ -20,7 +20,19 @@ proc compare[A, B](x: openarray[A], y: openarray[B], s: int = 0): bool =
|
|||
result = false
|
||||
break
|
||||
|
||||
template offsetOf(a, b): int =
|
||||
cast[int](cast[uint](unsafeAddr b) - cast[uint](unsafeAddr a))
|
||||
|
||||
suite "ECIES test suite":
|
||||
test "ECIES structures alignment":
|
||||
var header: EciesHeader
|
||||
check:
|
||||
offsetOf(header, header.version) == 0
|
||||
offsetOf(header, header.pubkey) == 1
|
||||
offsetOf(header, header.iv) == 1 + 64
|
||||
offsetOf(header, header.data) == 1 + 64 + aes128.sizeBlock
|
||||
sizeof(header) == 1 + 64 + aes128.sizeBlock + 1
|
||||
|
||||
test "KDF test vectors":
|
||||
# KDF test
|
||||
# Copied from https://github.com/ethereum/pydevp2p/blob/develop/devp2p/tests/test_ecies.py#L53
|
||||
|
|
Loading…
Reference in New Issue