diff options
| author | J08nY | 2020-02-11 20:44:45 +0100 |
|---|---|---|
| committer | J08nY | 2020-02-11 20:44:45 +0100 |
| commit | 11bd56b296f1620932f098a6037f0807e7f6616f (patch) | |
| tree | 2a791114a710ab49af523cf1ba2144646ef9ad90 /pyecsca/ec/signature.py | |
| parent | 4e2bd346baf2db39391deb49e9bdb9d89f94101a (diff) | |
| download | pyecsca-11bd56b296f1620932f098a6037f0807e7f6616f.tar.gz pyecsca-11bd56b296f1620932f098a6037f0807e7f6616f.tar.zst pyecsca-11bd56b296f1620932f098a6037f0807e7f6616f.zip | |
Diffstat (limited to 'pyecsca/ec/signature.py')
| -rw-r--r-- | pyecsca/ec/signature.py | 169 |
1 files changed, 113 insertions, 56 deletions
diff --git a/pyecsca/ec/signature.py b/pyecsca/ec/signature.py index 90ed9fb..569367e 100644 --- a/pyecsca/ec/signature.py +++ b/pyecsca/ec/signature.py @@ -5,11 +5,11 @@ from typing import Optional, Any from asn1crypto.core import Sequence, SequenceOf, Integer from public import public -from .context import getcontext +from .context import Action from .formula import AdditionFormula -from .params import DomainParameters from .mod import Mod from .mult import ScalarMultiplier +from .params import DomainParameters from .point import Point @@ -20,7 +20,7 @@ class SignatureResult(object): s: int def __init__(self, r: int, s: int, data: Optional[bytes] = None, digest: Optional[bytes] = None, - nonce: Optional[int] = None, privkey: Optional[int] = None, + nonce: Optional[int] = None, privkey: Optional[Mod] = None, pubkey: Optional[Point] = None): self.r = r self.s = s @@ -51,17 +51,66 @@ class SignatureResult(object): @public +class ECDSAAction(Action): + """An ECDSA action base class.""" + params: DomainParameters + hash_algo: Optional[Any] + msg: bytes + + def __init__(self, params: DomainParameters, hash_algo: Optional[Any], + msg: bytes): + super().__init__() + self.params = params + self.hash_algo = hash_algo + self.msg = msg + + def __repr__(self): + return f"{self.__class__.__name__}({self.params}, {self.hash_algo}, {self.msg})" + + +@public +class ECDSASignAction(ECDSAAction): + """An ECDSA signing.""" + privkey: Mod + + def __init__(self, params: DomainParameters, hash_algo: Optional[Any], msg: bytes, + privkey: Mod): + super().__init__(params, hash_algo, msg) + self.privkey = privkey + + def __repr__(self): + return f"{self.__class__.__name__}({self.params}, {self.hash_algo}, {self.msg}, {self.privkey})" + + +@public +class ECDSAVerifyAction(ECDSAAction): + """An ECDSA verification.""" + signature: SignatureResult + pubkey: Point + + def __init__(self, params: DomainParameters, hash_algo: Optional[Any], msg: bytes, + signature: SignatureResult, pubkey: Point): + super().__init__(params, hash_algo, msg) + self.signature = signature + self.pubkey = pubkey + + def __repr__(self): + return f"{self.__class__.__name__}({self.params}, {self.hash_algo}, {self.msg}, {self.signature}, {self.pubkey})" + + +@public class Signature(object): """An EC based signature primitive. (ECDSA)""" mult: ScalarMultiplier - group: DomainParameters + params: DomainParameters add: Optional[AdditionFormula] pubkey: Optional[Point] - privkey: Optional[int] + privkey: Optional[Mod] hash_algo: Optional[Any] - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None, + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None, hash_algo: Optional[Any] = None): if pubkey is None and privkey is None: raise ValueError @@ -71,7 +120,7 @@ class Signature(object): elif isinstance(mult.formulas["add"], AdditionFormula): add = mult.formulas["add"] self.mult = mult - self.group = group + self.params = params self.add = add self.pubkey = pubkey self.privkey = privkey @@ -89,19 +138,19 @@ class Signature(object): def _get_nonce(self, nonce: Optional[int]) -> Mod: if nonce is None: - return Mod(secrets.randbelow(self.group.order), self.group.order) + return Mod.random(self.params.order) else: - return Mod(nonce, self.group.order) + return Mod(nonce, self.params.order) def _do_sign(self, nonce: Mod, digest: bytes) -> SignatureResult: z = int.from_bytes(digest, byteorder="big") - if len(digest) * 8 > self.group.order.bit_length(): - z >>= len(digest) * 8 - self.group.order.bit_length() - self.mult.init(self.group, self.group.generator) + if len(digest) * 8 > self.params.order.bit_length(): + z >>= len(digest) * 8 - self.params.order.bit_length() + self.mult.init(self.params, self.params.generator) point = self.mult.multiply(int(nonce)) - affine_point = point.to_affine() # TODO: add to context - r = Mod(int(affine_point.x), self.group.order) - s = nonce.inverse() * (Mod(z, self.group.order) + r * self.privkey) + affine_point = point.to_affine() + r = Mod(int(affine_point.x), self.params.order) + s = nonce.inverse() * (Mod(z, self.params.order) + r * self.privkey) return SignatureResult(int(r), int(s), digest=digest, nonce=int(nonce), privkey=self.privkey) @@ -116,29 +165,30 @@ class Signature(object): """Sign data.""" if not self.can_sign: raise RuntimeError("This instance cannot sign.") - k = self._get_nonce(nonce) - if self.hash_algo is None: - digest = data - else: - digest = self.hash_algo(data).digest() - return self._do_sign(k, digest) + with ECDSASignAction(self.params, self.hash_algo, data, self.privkey): + k = self._get_nonce(nonce) + if self.hash_algo is None: + digest = data + else: + digest = self.hash_algo(data).digest() + return self._do_sign(k, digest) def _do_verify(self, signature: SignatureResult, digest: bytes) -> bool: - if self.pubkey is None: + if self.pubkey is None or self.add is None: return False z = int.from_bytes(digest, byteorder="big") - if len(digest) * 8 > self.group.order.bit_length(): - z >>= len(digest) * 8 - self.group.order.bit_length() - c = Mod(signature.s, self.group.order).inverse() - u1 = Mod(z, self.group.order) * c - u2 = Mod(signature.r, self.group.order) * c - self.mult.init(self.group, self.group.generator) + if len(digest) * 8 > self.params.order.bit_length(): + z >>= len(digest) * 8 - self.params.order.bit_length() + c = Mod(signature.s, self.params.order).inverse() + u1 = Mod(z, self.params.order) * c + u2 = Mod(signature.r, self.params.order) * c + self.mult.init(self.params, self.params.generator) p1 = self.mult.multiply(int(u1)) - self.mult.init(self.group, self.pubkey) + self.mult.init(self.params, self.pubkey) p2 = self.mult.multiply(int(u2)) - p = getcontext().execute(self.add, p1, p2, **self.group.curve.parameters)[0] - affine = p.to_affine() # TODO: add to context - v = Mod(int(affine.x), self.group.order) + p = self.add(p1, p2, **self.params.curve.parameters)[0] + affine = p.to_affine() + v = Mod(int(affine.x), self.params.order) return signature.r == int(v) def verify_hash(self, signature: SignatureResult, digest: bytes) -> bool: @@ -151,62 +201,69 @@ class Signature(object): """Verify data.""" if not self.can_verify: raise RuntimeError("This instance cannot verify.") - if self.hash_algo is None: - digest = data - else: - digest = self.hash_algo(data).digest() - return self._do_verify(signature, digest) + with ECDSAVerifyAction(self.params, self.hash_algo, data, signature, self.pubkey): + if self.hash_algo is None: + digest = data + else: + digest = self.hash_algo(data).digest() + return self._do_verify(signature, digest) @public class ECDSA_NONE(Signature): """ECDSA with raw message input.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey) @public class ECDSA_SHA1(Signature): """ECDSA with SHA1.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey, hashlib.sha1) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey, hashlib.sha1) @public class ECDSA_SHA224(Signature): """ECDSA with SHA224.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey, hashlib.sha224) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey, hashlib.sha224) @public class ECDSA_SHA256(Signature): """ECDSA with SHA256.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey, hashlib.sha256) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey, hashlib.sha256) @public class ECDSA_SHA384(Signature): """ECDSA with SHA384.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey, hashlib.sha384) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey, hashlib.sha384) @public class ECDSA_SHA512(Signature): """ECDSA with SHA512.""" - def __init__(self, mult: ScalarMultiplier, group: DomainParameters, add: Optional[AdditionFormula] = None, - pubkey: Optional[Point] = None, privkey: Optional[int] = None): - super().__init__(mult, group, add, pubkey, privkey, hashlib.sha512) + def __init__(self, mult: ScalarMultiplier, params: DomainParameters, + add: Optional[AdditionFormula] = None, + pubkey: Optional[Point] = None, privkey: Optional[Mod] = None): + super().__init__(mult, params, add, pubkey, privkey, hashlib.sha512) |
