Merge pull request #5 from danielinux/ecc-sign-verify-raw
[ECC] Added ecc_sign_raw and ecc_verify_raw + test casespull/6/head
commit
fda3889766
|
@ -59,6 +59,11 @@ ffi.cdef(
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef unsigned int word32;
|
typedef unsigned int word32;
|
||||||
|
|
||||||
|
typedef struct { ...; } mp_int;
|
||||||
|
|
||||||
|
int mp_init (mp_int * a);
|
||||||
|
int mp_to_unsigned_bin (mp_int * a, unsigned char *b);
|
||||||
|
int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c);
|
||||||
|
|
||||||
typedef struct { ...; } wc_Sha;
|
typedef struct { ...; } wc_Sha;
|
||||||
|
|
||||||
|
@ -96,6 +101,7 @@ ffi.cdef(
|
||||||
int wc_HmacFinal(Hmac*, byte*);
|
int wc_HmacFinal(Hmac*, byte*);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct { ...; } Aes;
|
typedef struct { ...; } Aes;
|
||||||
|
|
||||||
int wc_AesSetKey(Aes*, const byte*, word32, const byte*, int);
|
int wc_AesSetKey(Aes*, const byte*, word32, const byte*, int);
|
||||||
|
@ -172,6 +178,12 @@ ffi.cdef(
|
||||||
const byte* hash, word32 hashlen,
|
const byte* hash, word32 hashlen,
|
||||||
int* stat, ecc_key* key);
|
int* stat, ecc_key* key);
|
||||||
|
|
||||||
|
int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
|
||||||
|
ecc_key* key, mp_int *r, mp_int *s);
|
||||||
|
|
||||||
|
int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
|
||||||
|
word32 hashlen, int* res, ecc_key* key);
|
||||||
|
|
||||||
typedef struct {...; } ed25519_key;
|
typedef struct {...; } ed25519_key;
|
||||||
|
|
||||||
int wc_ed25519_init(ed25519_key* ed25519);
|
int wc_ed25519_init(ed25519_key* ed25519);
|
||||||
|
|
|
@ -530,6 +530,42 @@ class EccPublic(_Ecc):
|
||||||
|
|
||||||
return status[0] == 1
|
return status[0] == 1
|
||||||
|
|
||||||
|
def verify_raw(self, R, S, data):
|
||||||
|
"""
|
||||||
|
Verifies signature from its raw elements **R** and **S**, using the
|
||||||
|
public key data in the object.
|
||||||
|
|
||||||
|
Returns **True** in case of a valid signature, otherwise **False**.
|
||||||
|
"""
|
||||||
|
data = t2b(data)
|
||||||
|
status = _ffi.new("int[1]")
|
||||||
|
mpR = _ffi.new("mp_int[1]")
|
||||||
|
mpS = _ffi.new("mp_int[1]")
|
||||||
|
ret = _lib.mp_init(mpR)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
ret = _lib.mp_init(mpS)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
ret = _lib.mp_read_unsigned_bin(mpR, R, len(R))
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
ret = _lib.mp_read_unsigned_bin(mpS, S, len(S))
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
|
||||||
|
ret = _lib.wc_ecc_verify_hash_ex(mpR, mpS,
|
||||||
|
data, len(data),
|
||||||
|
status, self.native_object)
|
||||||
|
|
||||||
|
if ret < 0:
|
||||||
|
raise WolfCryptError("Verify error (%d)" % ret)
|
||||||
|
|
||||||
|
return status[0] == 1
|
||||||
|
|
||||||
|
|
||||||
class EccPrivate(EccPublic):
|
class EccPrivate(EccPublic):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -650,6 +686,43 @@ class EccPrivate(EccPublic):
|
||||||
|
|
||||||
return _ffi.buffer(signature, signature_size[0])[:]
|
return _ffi.buffer(signature, signature_size[0])[:]
|
||||||
|
|
||||||
|
def sign_raw(self, plaintext, rng=Random()):
|
||||||
|
"""
|
||||||
|
Signs **plaintext**, using the private key data in the object.
|
||||||
|
|
||||||
|
Returns the signature in its two raw components r, s
|
||||||
|
"""
|
||||||
|
plaintext = t2b(plaintext)
|
||||||
|
R = _ffi.new("mp_int[1]");
|
||||||
|
S = _ffi.new("mp_int[1]");
|
||||||
|
|
||||||
|
R_bin = _ffi.new("unsigned char[%d]" % self.size )
|
||||||
|
S_bin = _ffi.new("unsigned char[%d]" % self.size )
|
||||||
|
|
||||||
|
ret = _lib.mp_init(R)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
ret = _lib.mp_init(S)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
ret = _lib.wc_ecc_sign_hash_ex(plaintext, len(plaintext),
|
||||||
|
rng.native_object,
|
||||||
|
self.native_object,
|
||||||
|
R, S)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("Signature error (%d)" % ret)
|
||||||
|
|
||||||
|
ret = _lib.mp_to_unsigned_bin(R, R_bin)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
ret = _lib.mp_to_unsigned_bin(S, S_bin)
|
||||||
|
if ret != 0: # pragma: no cover
|
||||||
|
raise WolfCryptError("wolfCrypt error (%d)" % ret)
|
||||||
|
|
||||||
|
return _ffi.buffer(R_bin, self.size)[:], _ffi.buffer(S_bin, self.size)[:]
|
||||||
|
|
||||||
class _Ed25519(object): # pylint: disable=too-few-public-methods
|
class _Ed25519(object): # pylint: disable=too-few-public-methods
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.native_object = _ffi.new("ed25519_key *")
|
self.native_object = _ffi.new("ed25519_key *")
|
||||||
|
@ -735,6 +808,7 @@ class Ed25519Public(_Ed25519):
|
||||||
return status[0] == 1
|
return status[0] == 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Ed25519Private(Ed25519Public):
|
class Ed25519Private(Ed25519Public):
|
||||||
def __init__(self, key=None, pub=None):
|
def __init__(self, key=None, pub=None):
|
||||||
_Ed25519.__init__(self)
|
_Ed25519.__init__(self)
|
||||||
|
|
|
@ -349,6 +349,23 @@ def test_ecc_sign_verify(ecc_private, ecc_public):
|
||||||
with pytest.raises(WolfCryptError):
|
with pytest.raises(WolfCryptError):
|
||||||
ecc_x963.import_x963(ecc_public.export_x963()[:-1])
|
ecc_x963.import_x963(ecc_public.export_x963()[:-1])
|
||||||
|
|
||||||
|
def test_ecc_sign_verify_raw(ecc_private, ecc_public):
|
||||||
|
plaintext = "Everyone gets Friday off."
|
||||||
|
|
||||||
|
# normal usage, sign with private, verify with public
|
||||||
|
r,s = ecc_private.sign_raw(plaintext)
|
||||||
|
|
||||||
|
assert len(r) + len(s) <= 2 * ecc_private.size
|
||||||
|
assert ecc_public.verify_raw(r, s, plaintext)
|
||||||
|
|
||||||
|
# invalid signature
|
||||||
|
ret = ecc_public.verify_raw(r, s[:-1], plaintext)
|
||||||
|
assert ret == False
|
||||||
|
|
||||||
|
# private object holds both private and public info, so it can also verify
|
||||||
|
# using the known public key.
|
||||||
|
assert ecc_private.verify_raw(r, s, plaintext)
|
||||||
|
|
||||||
|
|
||||||
def test_ecc_make_shared_secret():
|
def test_ecc_make_shared_secret():
|
||||||
a = EccPrivate.make_key(32)
|
a = EccPrivate.make_key(32)
|
||||||
|
|
Loading…
Reference in New Issue