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 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;
|
||||
|
||||
|
@ -96,6 +101,7 @@ ffi.cdef(
|
|||
int wc_HmacFinal(Hmac*, byte*);
|
||||
|
||||
|
||||
|
||||
typedef struct { ...; } Aes;
|
||||
|
||||
int wc_AesSetKey(Aes*, const byte*, word32, const byte*, int);
|
||||
|
@ -172,6 +178,12 @@ ffi.cdef(
|
|||
const byte* hash, word32 hashlen,
|
||||
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;
|
||||
|
||||
int wc_ed25519_init(ed25519_key* ed25519);
|
||||
|
|
|
@ -530,6 +530,42 @@ class EccPublic(_Ecc):
|
|||
|
||||
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):
|
||||
@classmethod
|
||||
|
@ -650,6 +686,43 @@ class EccPrivate(EccPublic):
|
|||
|
||||
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
|
||||
def __init__(self):
|
||||
self.native_object = _ffi.new("ed25519_key *")
|
||||
|
@ -735,6 +808,7 @@ class Ed25519Public(_Ed25519):
|
|||
return status[0] == 1
|
||||
|
||||
|
||||
|
||||
class Ed25519Private(Ed25519Public):
|
||||
def __init__(self, key=None, pub=None):
|
||||
_Ed25519.__init__(self)
|
||||
|
|
|
@ -349,6 +349,23 @@ def test_ecc_sign_verify(ecc_private, ecc_public):
|
|||
with pytest.raises(WolfCryptError):
|
||||
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():
|
||||
a = EccPrivate.make_key(32)
|
||||
|
|
Loading…
Reference in New Issue