mirror of https://github.com/status-im/nim-eth.git
Addded non-recoverable signature type and routines
This commit is contained in:
parent
658e5a3cc8
commit
091239a710
|
@ -13,7 +13,8 @@ import secp256k1, nimcrypto/sysrand, nimcrypto/utils
|
|||
const
|
||||
KeyLength* = 256 div 8
|
||||
CompressedPubKeyLength* = 33
|
||||
RawSignatureSize* = KeyLength * 2 + 1
|
||||
RawSignatureNRSize* = KeyLength * 2 # Non-recoverable signature
|
||||
RawSignatureSize* = RawSignatureNRSize + 1 # Recoverable
|
||||
RawPublicKeySize* = KeyLength * 2
|
||||
InvalidPrivateKey = "Invalid private key!"
|
||||
InvalidPublicKey = "Invalid public key!"
|
||||
|
@ -33,6 +34,11 @@ type
|
|||
## Representation of ECDH shared secret
|
||||
data*: array[KeyLength, byte]
|
||||
|
||||
SharedSecretFull* = object
|
||||
## Representation of ECDH shared secret, with leading `y` byte
|
||||
# (`y` is 0x02 when pubkey.y is even or 0x03 when odd)
|
||||
data*: array[1 + KeyLength, byte]
|
||||
|
||||
KeyPair* = object
|
||||
## Representation of private/public keys pair
|
||||
seckey*: PrivateKey
|
||||
|
@ -41,6 +47,9 @@ type
|
|||
Signature* = secp256k1_ecdsa_recoverable_signature
|
||||
## Representation of signature
|
||||
|
||||
SignatureNR* = secp256k1_ecdsa_signature
|
||||
## Representation of non-recoverable signature
|
||||
|
||||
Secp256k1Exception* = object of Exception
|
||||
## Exceptions generated by `libsecp256k1`
|
||||
|
||||
|
@ -175,12 +184,23 @@ proc recoverPublicKey*(data: openarray[byte],
|
|||
|
||||
result = EthKeysStatus.Success
|
||||
|
||||
proc recoverSignature*(data: openarray[byte],
|
||||
signature: var Signature): EthKeysStatus =
|
||||
proc parseCompact*(signature: var SignatureNR, data: openarray[byte]): EthKeysStatus =
|
||||
let ctx = getSecpContext()
|
||||
let length = len(data)
|
||||
if length == RawSignatureNRSize:
|
||||
if secp256k1_ecdsa_signature_parse_compact(ctx, addr signature,
|
||||
cast[ptr cuchar](unsafeAddr data[0])) != 1:
|
||||
return(EthKeysStatus.Error)
|
||||
else:
|
||||
setErrorMsg(InvalidSignature)
|
||||
return(EthKeysStatus.Error)
|
||||
result = EthKeysStatus.Success
|
||||
|
||||
proc parseCompact*(signature: var Signature, data: openarray[byte]): EthKeysStatus =
|
||||
## Unserialize signature from `data`.
|
||||
let ctx = getSecpContext()
|
||||
let length = len(data)
|
||||
if length < RawSignatureSize:
|
||||
if length != RawSignatureSize:
|
||||
setErrorMsg(InvalidSignature)
|
||||
return(EthKeysStatus.Error)
|
||||
var recid = cint(data[KeyLength * 2])
|
||||
|
@ -190,6 +210,14 @@ proc recoverSignature*(data: openarray[byte],
|
|||
return(EthKeysStatus.Error)
|
||||
result = EthKeysStatus.Success
|
||||
|
||||
proc recoverSignature*(data: openarray[byte],
|
||||
signature: var Signature): EthKeysStatus {.deprecated.} =
|
||||
## Deprecated, use `parseCompact` instead
|
||||
if data.len < RawSignatureSize:
|
||||
setErrorMsg(InvalidSignature)
|
||||
return(EthKeysStatus.Error)
|
||||
signature.parseCompact(data.toOpenArray(0, RawSignatureSize - 1))
|
||||
|
||||
proc initPublicKey*(hexstr: string): PublicKey =
|
||||
## Create new public key from hexadecimal string representation.
|
||||
var o = fromHex(stripSpaces(hexstr))
|
||||
|
@ -212,6 +240,16 @@ proc initSignature*(data: openarray[byte]): Signature =
|
|||
if recoverSignature(data, result) != EthKeysStatus.Success:
|
||||
raise newException(EthKeysException, libsecp256k1ErrorMsg())
|
||||
|
||||
proc ecdhAgree*(seckey: PrivateKey, pubkey: PublicKey,
|
||||
secret: var SharedSecretFull): EthKeysStatus =
|
||||
## Calculate ECDH shared secret.
|
||||
let ctx = getSecpContext()
|
||||
if secp256k1_ecdh_raw(ctx, cast[ptr cuchar](addr secret.data),
|
||||
unsafeAddr pubkey,
|
||||
cast[ptr cuchar](unsafeAddr seckey)) != 1:
|
||||
return(EthKeysStatus.Error)
|
||||
return(EthKeysStatus.Success)
|
||||
|
||||
proc ecdhAgree*(seckey: PrivateKey, pubkey: PublicKey,
|
||||
secret: var SharedSecret): EthKeysStatus =
|
||||
## Calculate ECDH shared secret.
|
||||
|
@ -255,15 +293,6 @@ proc getRawCompressed*(pubkey: PublicKey): array[CompressedPubKeyLength, byte] {
|
|||
## Converts public key `pubkey` to serialized form.
|
||||
pubkey.toRaw(result, true)
|
||||
|
||||
proc getRaw*(s: Signature): array[RawSignatureSize, byte] {.noinit.} =
|
||||
## Converts signature `s` to serialized form.
|
||||
let ctx = getSecpContext()
|
||||
var recid = cint(0)
|
||||
if secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||
ctx, cast[ptr cuchar](unsafeAddr result), addr recid, unsafeAddr s) != 1:
|
||||
raiseSecp256k1Error()
|
||||
result[64] = uint8(recid)
|
||||
|
||||
proc toRaw*(s: Signature, data: var openarray[byte]) =
|
||||
## Converts signature `s` to serialized form and store it in `data`.
|
||||
let ctx = getSecpContext()
|
||||
|
@ -274,6 +303,22 @@ proc toRaw*(s: Signature, data: var openarray[byte]) =
|
|||
raiseSecp256k1Error()
|
||||
data[64] = uint8(recid)
|
||||
|
||||
proc getRaw*(s: Signature): array[RawSignatureSize, byte] {.noinit.} =
|
||||
## Converts signature `s` to serialized form.
|
||||
s.toRaw(result)
|
||||
|
||||
proc toRaw*(s: SignatureNR, data: var openarray[byte]) =
|
||||
## Converts signature `s` to serialized form and store it in `data`.
|
||||
doAssert(len(data) == RawSignatureNRSize)
|
||||
let ctx = getSecpContext()
|
||||
if secp256k1_ecdsa_signature_serialize_compact(ctx, cast[ptr cuchar](addr data[0]),
|
||||
unsafeAddr s) != 1:
|
||||
raiseSecp256k1Error()
|
||||
|
||||
proc getRaw*(s: SignatureNR): array[RawSignatureNRSize, byte] {.noinit.} =
|
||||
## Converts signature `s` to serialized form.
|
||||
s.toRaw(result)
|
||||
|
||||
proc recoverSignatureKey*(data: openarray[byte],
|
||||
msg: openarray[byte],
|
||||
pubkey: var PublicKey): EthKeysStatus =
|
||||
|
@ -330,3 +375,34 @@ proc signRawMessage*(data: openarray[byte], seckey: PrivateKey,
|
|||
return(EthKeysStatus.Error)
|
||||
return(EthKeysStatus.Success)
|
||||
|
||||
proc signRawMessage*(data: openarray[byte], seckey: PrivateKey,
|
||||
signature: var SignatureNR): EthKeysStatus =
|
||||
## Sign message `data` of `KeyLength` size using private key `seckey` and
|
||||
## store result into `signature`.
|
||||
let ctx = getSecpContext()
|
||||
let length = len(data)
|
||||
if length != KeyLength:
|
||||
setErrorMsg(MessageSizeError)
|
||||
return(EthKeysStatus.Error)
|
||||
if secp256k1_ecdsa_sign(ctx, addr signature,
|
||||
cast[ptr cuchar](unsafeAddr data[0]),
|
||||
cast[ptr cuchar](unsafeAddr seckey),
|
||||
nil, nil) != 1:
|
||||
return(EthKeysStatus.Error)
|
||||
return(EthKeysStatus.Success)
|
||||
|
||||
proc verifySignatureRaw*(signature: SignatureNR, message: openarray[byte],
|
||||
publicKey: PublicKey): EthKeysStatus =
|
||||
## Verify `signature` using original `message` (32 bytes) and `publicKey`.
|
||||
let ctx = getSecpContext()
|
||||
if len(message) != KeyLength:
|
||||
setErrorMsg(MessageSizeError)
|
||||
return(EthKeysStatus.Error)
|
||||
|
||||
if secp256k1_ecdsa_verify(ctx, unsafeAddr signature,
|
||||
cast[ptr cuchar](unsafeAddr message[0]),
|
||||
unsafeAddr publicKey) != 1:
|
||||
setErrorMsg(VerificationFailed)
|
||||
return(EthKeysStatus.Error)
|
||||
|
||||
return(EthKeysStatus.Success)
|
||||
|
|
Loading…
Reference in New Issue