def _decrypt(self, ciphertext): if not 0 < ciphertext < self._n: raise ValueError("Ciphertext too large") if not self.has_private(): raise TypeError("This is not a private key") # Blinded RSA decryption (to prevent timing attacks): # Step 1: Generate random secret blinding factor r, # such that 0 < r < n-1 r = Integer.random_range(min_inclusive=1, max_exclusive=self._n) # Step 2: Compute c' = c * r**e mod n cp = Integer(ciphertext) * pow(r, self._e, self._n) % self._n # Step 3: Compute m' = c'**d mod n (ordinary RSA decryption) m1 = pow(cp, self._d % (self._p - 1), self._p) m2 = pow(cp, self._d % (self._q - 1), self._q) h = m2 - m1 while h < 0: h += self._q h = (h * self._u) % self._q mp = h * self._p + m1 # Step 4: Compute m = m**(r-1) mod n result = (r.inverse(self._n) * mp) % self._n # Verify no faults occured if ciphertext != pow(result, self._e, self._n): raise ValueError("Fault detected in RSA decryption") return result
def _import_openssh_private_ecc(data, password): from ._openssh import (import_openssh_private_generic, read_bytes, read_string, check_padding) ssh_name, decrypted = import_openssh_private_generic(data, password) name, decrypted = read_string(decrypted) if name not in _curves: raise UnsupportedEccFeature("Unsupported ECC curve %s" % name) curve = _curves[name] modulus_bytes = (curve.modulus_bits + 7) // 8 public_key, decrypted = read_bytes(decrypted) if bord(public_key[0]) != 4: raise ValueError("Only uncompressed OpenSSH EC keys are supported") if len(public_key) != 2 * modulus_bytes + 1: raise ValueError("Incorrect public key length") point_x = Integer.from_bytes(public_key[1:1 + modulus_bytes]) point_y = Integer.from_bytes(public_key[1 + modulus_bytes:]) point = EccPoint(point_x, point_y, curve=name) private_key, decrypted = read_bytes(decrypted) d = Integer.from_bytes(private_key) _, padded = read_string(decrypted) # Comment check_padding(padded) return EccKey(curve=name, d=d, point=point)
def test_several_lengths(self): prng = SHAKE128.new().update(b('Test')) for length in range(1, 100): base = Integer.from_bytes(prng.read(length)) modulus2 = Integer.from_bytes(prng.read(length)) | 1 exponent2 = Integer.from_bytes(prng.read(length)) expected = pow(base, exponent2, modulus2) result = monty_pow(base, exponent2, modulus2) self.assertEqual(result, expected)
def test_probable_prime(candidate, randfunc=None): """Test if a number is prime. A number is qualified as prime if it passes a certain number of Miller-Rabin tests (dependent on the size of the number, but such that probability of a false positive is less than 10^-30) and a single Lucas test. For instance, a 1024-bit candidate will need to pass 4 Miller-Rabin tests. :Parameters: candidate : integer The number to test for primality. randfunc : callable The routine to draw random bytes from to select Miller-Rabin bases. :Returns: ``PROBABLE_PRIME`` if the number if prime with very high probability. ``COMPOSITE`` if the number is a composite. For efficiency reasons, ``COMPOSITE`` is also returned for small primes. """ if randfunc is None: randfunc = Random.new().read if not isinstance(candidate, Integer): candidate = Integer(candidate) # First, check trial division by the smallest primes if int(candidate) in _sieve_base: return PROBABLY_PRIME try: map(candidate.fail_if_divisible_by, _sieve_base) except ValueError: return COMPOSITE # These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30, # with p(k, t) being the probability that a randomly chosen k-bit number # is composite but still survives t MR iterations. mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10), (620, 7), (740, 6), (890, 5), (1200, 4), (1700, 3), (3700, 2)) bit_size = candidate.size_in_bits() try: mr_iterations = list(filter(lambda x: bit_size < x[0], mr_ranges))[0][1] except IndexError: mr_iterations = 1 if miller_rabin_test(candidate, mr_iterations, randfunc=randfunc) == COMPOSITE: return COMPOSITE if lucas_test(candidate) == COMPOSITE: return COMPOSITE return PROBABLY_PRIME
def xy(self): modulus_bytes = self.size_in_bytes() xb = bytearray(modulus_bytes) yb = bytearray(modulus_bytes) result = _ec_lib.ec_ws_get_xy(c_uint8_ptr(xb), c_uint8_ptr(yb), c_size_t(modulus_bytes), self._point.get()) if result: raise ValueError("Error %d while encoding an EC point" % result) return (Integer(bytes_to_long(xb)), Integer(bytes_to_long(yb)))
def _sign(self, M, K): if (not hasattr(self, 'x')): raise TypeError('Private key not available in this object') p1 = self.p - 1 K = Integer(K) if (K.gcd(p1) != 1): raise ValueError('Bad K value: GCD(K,p-1)!=1') a = pow(self.g, K, self.p) t = (Integer(M) - self.x * a) % p1 while t < 0: t = t + p1 b = (t * K.inverse(p1)) % p1 return list(map(int, (a, b)))
def construct(**kwargs): """Build a new ECC key (private or public) starting from some base components. Args: curve (string): Mandatory. It must be "P-256", "prime256v1" or "secp256r1". d (integer): Only for a private key. It must be in the range ``[1..order-1]``. point_x (integer): Mandatory for a public key. X coordinate (affine) of the ECC point. point_y (integer): Mandatory for a public key. Y coordinate (affine) of the ECC point. Returns: :class:`EccKey` : a new ECC key object """ point_x = kwargs.pop("point_x", None) point_y = kwargs.pop("point_y", None) if "point" in kwargs: raise TypeError("Unknown keyword: point") if None not in (point_x, point_y): kwargs["point"] = EccPoint(point_x, point_y) # Validate that the point is on the P-256 curve eq1 = pow(Integer(point_y), 2, _curve.p) x = Integer(point_x) eq2 = pow(x, 3, _curve.p) x *= -3 eq2 += x eq2 += _curve.b eq2 %= _curve.p if eq1 != eq2: raise ValueError("The point is not on the curve") # Validate that the private key matches the public one d = kwargs.get("d", None) if d is not None and "point" in kwargs: pub_key = _curve.G * d if pub_key.x != point_x or pub_key.y != point_y: raise ValueError("Private and public ECC keys do not match") return EccKey(**kwargs)
def verify(self, msg_hash, signature): """Check if a certain (EC)DSA signature is authentic. :parameter msg_hash: The hash that was carried out over the message. This is an object belonging to the :mod:`crypto.Hash` module. Under mode *'fips-186-3'*, the hash must be a FIPS approved secure hash (SHA-1 or a member of the SHA-2 family), of cryptographic strength appropriate for the DSA key. For instance, a 3072/256 DSA key can only be used in combination with SHA-512. :type msg_hash: hash object :parameter signature: The signature that needs to be validated :type signature: byte string :raise ValueError: if the signature is not authentic """ if not self._valid_hash(msg_hash): raise ValueError("Hash is not sufficiently strong") if self._encoding == 'binary': if len(signature) != (2 * self._order_bytes): raise ValueError("The signature is not authentic (length)") r_prime, s_prime = [ Integer.from_bytes(x) for x in (signature[:self._order_bytes], signature[self._order_bytes:]) ] else: try: der_seq = DerSequence().decode(signature, strict=True) except (ValueError, IndexError): raise ValueError("The signature is not authentic (DER)") if len(der_seq) != 2 or not der_seq.hasOnlyInts(): raise ValueError( "The signature is not authentic (DER content)") r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1]) if not (0 < r_prime < self._order) or not (0 < s_prime < self._order): raise ValueError("The signature is not authentic (d)") z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) result = self._key._verify(z, (r_prime, s_prime)) if not result: raise ValueError("The signature is not authentic") # Make PyCrypto code to fail return False
def __mul__(self, scalar): """Return a new point, the scalar product of this one""" if scalar < 0: raise ValueError("Scalar multiplication only defined for non-negative integers") # Trivial results if scalar == 0 or self.is_point_at_infinity(): return self.point_at_infinity() elif scalar == 1: return self.copy() # Scalar randomization scalar_blind = Integer.random(exact_bits=64) * _curve.order + scalar # Montgomery key ladder r = [self.point_at_infinity().copy(), self.copy()] bit_size = int(scalar_blind.size_in_bits()) scalar_int = int(scalar_blind) for i in range(bit_size, -1, -1): di = scalar_int >> i & 1 r[di ^ 1] += r[di] r[di].double() return r[0]
def __init__(self, **kwargs): """Create a new ECC key Keywords: curve : string It must be *"P-256"*, *"prime256v1"* or *"secp256r1"*. d : integer Only for a private key. It must be in the range ``[1..order-1]``. point : EccPoint Mandatory for a public key. If provided for a private key, the implementation will NOT check whether it matches ``d``. """ kwargs_ = dict(kwargs) self.curve = kwargs_.pop("curve", None) self._d = kwargs_.pop("d", None) self._point = kwargs_.pop("point", None) if kwargs_: raise TypeError("Unknown parameters: " + str(kwargs_)) if self.curve not in _curve.names: raise ValueError("Unsupported curve (%s)", self.curve) if self._d is None: if self._point is None: raise ValueError("Either private or public ECC component must be specified") else: self._d = Integer(self._d) if not 1 <= self._d < _curve.order: raise ValueError("Invalid ECC private component")
def __init__(self, x, y): self._x = Integer(x) self._y = Integer(y) # Buffers self._common = Integer(0) self._tmp1 = Integer(0) self._x3 = Integer(0) self._y3 = Integer(0)
def _import_public_der(curve_oid, ec_point): """Convert an encoded EC point into an EccKey object curve_name: string with the OID of the curve ec_point: byte string with the EC point (not DER encoded) """ for curve_name, curve in _curves.items(): if curve.oid == curve_oid: break else: raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) # See 2.2 in RFC5480 and 2.3.3 in SEC1 # The first byte is: # - 0x02: compressed, only X-coordinate, Y-coordinate is even # - 0x03: compressed, only X-coordinate, Y-coordinate is odd # - 0x04: uncompressed, X-coordinate is followed by Y-coordinate # # PAI is in theory encoded as 0x00. modulus_bytes = curve.p.size_in_bytes() point_type = bord(ec_point[0]) # Uncompressed point if point_type == 0x04: if len(ec_point) != (1 + 2 * modulus_bytes): raise ValueError("Incorrect EC point length") x = Integer.from_bytes(ec_point[1:modulus_bytes + 1]) y = Integer.from_bytes(ec_point[modulus_bytes + 1:]) # Compressed point elif point_type in (0x02, 0x3): if len(ec_point) != (1 + modulus_bytes): raise ValueError("Incorrect EC point length") x = Integer.from_bytes(ec_point[1:]) y = (x**3 - x * 3 + curve.b).sqrt(curve.p) # Short Weierstrass if point_type == 0x02 and y.is_odd(): y = curve.p - y if point_type == 0x03 and y.is_even(): y = curve.p - y else: raise ValueError("Incorrect EC point encoding") return construct(curve=curve_name, point_x=x, point_y=y)
def _bits2int(self, bstr): """See 2.3.2 in RFC6979""" result = Integer.from_bytes(bstr) q_len = self._order.size_in_bits() b_len = len(bstr) * 8 if b_len > q_len: result >>= (b_len - q_len) return result
def __init__(self, key, encoding, order, randfunc): super(FipsDsaSigScheme, self).__init__(key, encoding, order) self._randfunc = randfunc L = Integer(key.p).size_in_bits() if (L, self._order_bits) not in self._fips_186_3_L_N: error = ("L/N (%d, %d) is not compliant to FIPS 186-3" % (L, self._order_bits)) raise ValueError(error)
def generate_probable_prime(**kwargs): """Generate a random probable prime. The prime will not have any specific properties (e.g. it will not be a *strong* prime). Random numbers are evaluated for primality until one passes all tests, consisting of a certain number of Miller-Rabin tests with random bases followed by a single Lucas test. The number of Miller-Rabin iterations is chosen such that the probability that the output number is a non-prime is less than 1E-30 (roughly 2^{-100}). This approach is compliant to `FIPS PUB 186-4`__. :Keywords: exact_bits : integer The desired size in bits of the probable prime. It must be at least 160. randfunc : callable An RNG function where candidate primes are taken from. prime_filter : callable A function that takes an Integer as parameter and returns True if the number can be passed to further primality tests, False if it should be immediately discarded. :Return: A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1). .. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf """ exact_bits = kwargs.pop("exact_bits", None) randfunc = kwargs.pop("randfunc", None) prime_filter = kwargs.pop("prime_filter", lambda x: True) if kwargs: raise ValueError("Unknown parameters: " + kwargs.keys()) if exact_bits is None: raise ValueError("Missing exact_bits parameter") if exact_bits < 160: raise ValueError("Prime number is not big enough.") if randfunc is None: randfunc = Random.new().read result = COMPOSITE while result == COMPOSITE: candidate = Integer.random(exact_bits=exact_bits, randfunc=randfunc) | 1 if not prime_filter(candidate): continue result = test_probable_prime(candidate, randfunc) return candidate
def _verify(self, m, sig): r, s = sig y, q, p, g = [self._key[comp] for comp in ['y', 'q', 'p', 'g']] if not (0 < r < q) or not (0 < s < q): return False w = Integer(s).inverse(q) u1 = (w * m) % q u2 = (w * r) % q v = (pow(g, u1, p) * pow(y, u2, p) % p) % q return v == r
def _decrypt(self, M): if (not hasattr(self, 'x')): raise TypeError('Private key not available in this object') r = Integer.random_range(min_inclusive=2, max_exclusive=self.p - 1, randfunc=self._randfunc) a_blind = (pow(self.g, r, self.p) * M[0]) % self.p ax = pow(a_blind, self.x, self.p) plaintext_blind = (ax.inverse(self.p) * M[1]) % self.p plaintext = (plaintext_blind * pow(self.y, r, self.p)) % self.p return int(plaintext)
def _sign(self, z, k): assert 0 < k < _curve.order blind = Integer.random_range(min_inclusive=1, max_exclusive=_curve.order) blind_d = self._d * blind inv_blind_k = (blind * k).inverse(_curve.order) r = (_curve.G * k).x % _curve.order s = inv_blind_k * (blind * z + blind_d * r) % _curve.order return (r, s)
def __repr__(self): attrs = [] for k in self._keydata: if k == 'p': bits = Integer(self.p).size_in_bits() attrs.append("p(%d)" % (bits, )) elif hasattr(self, k): attrs.append(k) if self.has_private(): attrs.append("private") # PY3K: This is meant to be text, do not change to bytes (data) return "<%s @0x%x %s>" % (self.__class__.__name__, id(self), ",".join(attrs))
def construct(tup): r"""Construct an ElGamal key from a tuple of valid ElGamal components. The modulus *p* must be a prime. The following conditions must apply: .. math:: \begin{align} &1 < g < p-1 \\ &g^{p-1} = 1 \text{ mod } 1 \\ &1 < x < p-1 \\ &g^x = y \text{ mod } p \end{align} Args: tup (tuple): A tuple with either 3 or 4 integers, in the following order: 1. Modulus (*p*). 2. Generator (*g*). 3. Public key (*y*). 4. Private key (*x*). Optional. Raises: ValueError: when the key being imported fails the most basic ElGamal validity checks. Returns: an :class:`ElGamalKey` object """ obj = ElGamalKey() if len(tup) not in [3, 4]: raise ValueError('argument for construct() wrong length') for i in range(len(tup)): field = obj._keydata[i] setattr(obj, field, Integer(tup[i])) fmt_error = test_probable_prime(obj.p) == COMPOSITE fmt_error |= obj.g <= 1 or obj.g >= obj.p fmt_error |= pow(obj.g, obj.p - 1, obj.p) != 1 fmt_error |= obj.y < 1 or obj.y >= obj.p if len(tup) == 4: fmt_error |= obj.x <= 1 or obj.x >= obj.p fmt_error |= pow(obj.g, obj.x, obj.p) != obj.y if fmt_error: raise ValueError("Invalid ElGamal key components") return obj
def _import_private_der(encoded, passphrase, curve_oid=None): # See RFC5915 https://tools.ietf.org/html/rfc5915 # # ECPrivateKey ::= SEQUENCE { # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # privateKey OCTET STRING, # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, # publicKey [1] BIT STRING OPTIONAL # } private_key = DerSequence().decode(encoded, nr_elements=(3, 4)) if private_key[0] != 1: raise ValueError("Incorrect ECC private key version") try: parameters = DerObjectId(explicit=0).decode(private_key[2]).value if curve_oid is not None and parameters != curve_oid: raise ValueError("Curve mismatch") curve_oid = parameters except ValueError: pass if curve_oid is None: raise ValueError("No curve found") for curve_name, curve in _curves.items(): if curve.oid == curve_oid: break else: raise UnsupportedEccFeature("Unsupported ECC curve (OID: %s)" % curve_oid) scalar_bytes = DerOctetString().decode(private_key[1]).payload modulus_bytes = curve.p.size_in_bytes() if len(scalar_bytes) != modulus_bytes: raise ValueError("Private key is too small") d = Integer.from_bytes(scalar_bytes) # Decode public key (if any) if len(private_key) == 4: public_key_enc = DerBitString(explicit=1).decode(private_key[3]).value public_key = _import_public_der(curve_oid, public_key_enc) point_x = public_key.pointQ.x point_y = public_key.pointQ.y else: point_x = point_y = None return construct(curve=curve_name, d=d, point_x=point_x, point_y=point_y)
def _sign(self, m, k): if not self.has_private(): raise TypeError("DSA public key cannot be used for signing") if not (1 < k < self.q): raise ValueError("k is not between 2 and q-1") x, q, p, g = [self._key[comp] for comp in ['x', 'q', 'p', 'g']] blind_factor = Integer.random_range(min_inclusive=1, max_exclusive=q) inv_blind_k = (blind_factor * k).inverse(q) blind_x = x * blind_factor r = pow(g, k, p) % q # r = (g**k mod p) mod q s = (inv_blind_k * (blind_factor * m + blind_x * r)) % q return map(int, (r, s))
def _check_private_key(self, rsaObj): from crypto.Math.Numbers import Integer # Check capabilities self.assertEqual(1, rsaObj.has_private()) # Sanity check key data self.assertEqual(rsaObj.n, rsaObj.p * rsaObj.q) # n = pq lcm = int(Integer(rsaObj.p-1).lcm(rsaObj.q-1)) self.assertEqual(1, rsaObj.d * rsaObj.e % lcm) # ed = 1 (mod LCM(p-1, q-1)) self.assertEqual(1, rsaObj.p * rsaObj.u % rsaObj.q) # pu = 1 (mod q) self.assertEqual(1, rsaObj.p > 1) # p > 1 self.assertEqual(1, rsaObj.q > 1) # q > 1 self.assertEqual(1, rsaObj.e > 1) # e > 1 self.assertEqual(1, rsaObj.d > 1) # d > 1
def init_p256(): p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 p256_modulus = long_to_bytes(p, 32) p256_b = long_to_bytes(b, 32) p256_order = long_to_bytes(order, 32) ec_p256_context = VoidPointer() result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(), c_uint8_ptr(p256_modulus), c_uint8_ptr(p256_b), c_uint8_ptr(p256_order), c_size_t(len(p256_modulus)), c_ulonglong(getrandbits(64))) if result: raise ImportError("Error %d initializing P-256 context" % result) context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_free_context) p256 = _Curve( Integer(p), Integer(b), Integer(order), Integer(Gx), Integer(Gy), None, 256, "1.2.840.10045.3.1.7", # ANSI X9.62 context, "NIST P-256", "ecdsa-sha2-nistp256") global p256_names _curves.update(dict.fromkeys(p256_names, p256))
def init_p384(): p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973 Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7 Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F p384_modulus = long_to_bytes(p, 48) p384_b = long_to_bytes(b, 48) p384_order = long_to_bytes(order, 48) ec_p384_context = VoidPointer() result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(), c_uint8_ptr(p384_modulus), c_uint8_ptr(p384_b), c_uint8_ptr(p384_order), c_size_t(len(p384_modulus)), c_ulonglong(getrandbits(64))) if result: raise ImportError("Error %d initializing P-384 context" % result) context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_free_context) p384 = _Curve( Integer(p), Integer(b), Integer(order), Integer(Gx), Integer(Gy), None, 384, "1.3.132.0.34", # SEC 2 context, "NIST P-384", "ecdsa-sha2-nistp384") global p384_names _curves.update(dict.fromkeys(p384_names, p384))
def init_p521(): p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00 order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409 Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66 Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650 p521_modulus = long_to_bytes(p, 66) p521_b = long_to_bytes(b, 66) p521_order = long_to_bytes(order, 66) ec_p521_context = VoidPointer() result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(), c_uint8_ptr(p521_modulus), c_uint8_ptr(p521_b), c_uint8_ptr(p521_order), c_size_t(len(p521_modulus)), c_ulonglong(getrandbits(64))) if result: raise ImportError("Error %d initializing P-521 context" % result) context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_free_context) p521 = _Curve( Integer(p), Integer(b), Integer(order), Integer(Gx), Integer(Gy), None, 521, "1.3.132.0.35", # SEC 2 context, "NIST P-521", "ecdsa-sha2-nistp521") global p521_names _curves.update(dict.fromkeys(p521_names, p521))
def sign(self, msg_hash): """Produce the DSA/ECDSA signature of a message. :parameter msg_hash: The hash that was carried out over the message. The object belongs to the :mod:`crypto.Hash` package. Under mode *'fips-186-3'*, the hash must be a FIPS approved secure hash (SHA-1 or a member of the SHA-2 family), of cryptographic strength appropriate for the DSA key. For instance, a 3072/256 DSA key can only be used in combination with SHA-512. :type msg_hash: hash object :return: The signature as a *byte string* :raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key :raise TypeError: if the (EC)DSA key has no private half """ if not self._valid_hash(msg_hash): raise ValueError("Hash is not sufficiently strong") # Generate the nonce k (critical!) nonce = self._compute_nonce(msg_hash) # Perform signature using the raw API z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes]) sig_pair = self._key._sign(z, nonce) # Encode the signature into a single byte string if self._encoding == 'binary': output = b"".join( [long_to_bytes(x, self._order_bytes) for x in sig_pair]) else: # Dss-sig ::= SEQUENCE { # r INTEGER, # s INTEGER # } # Ecdsa-Sig-Value ::= SEQUENCE { # r INTEGER, # s INTEGER # } output = DerSequence(sig_pair).encode() return output
def _import_pkcs1_private(encoded, *kwargs): # RSAPrivateKey ::= SEQUENCE { # version Version, # modulus INTEGER, -- n # publicExponent INTEGER, -- e # privateExponent INTEGER, -- d # prime1 INTEGER, -- p # prime2 INTEGER, -- q # exponent1 INTEGER, -- d mod (p-1) # exponent2 INTEGER, -- d mod (q-1) # coefficient INTEGER -- (inverse of q) mod p # } # # Version ::= INTEGER der = DerSequence().decode(encoded, nr_elements=9, only_ints_expected=True) if der[0] != 0: raise ValueError("No PKCS#1 encoding of an RSA private key") return construct(der[1:6] + [Integer(der[4]).inverse(der[5])])
def _import_openssh_private_rsa(data, password): from ._openssh import (import_openssh_private_generic, read_bytes, read_string, check_padding) ssh_name, decrypted = import_openssh_private_generic(data, password) if ssh_name != "ssh-rsa": raise ValueError("This SSH key is not RSA") n, decrypted = read_bytes(decrypted) e, decrypted = read_bytes(decrypted) d, decrypted = read_bytes(decrypted) iqmp, decrypted = read_bytes(decrypted) p, decrypted = read_bytes(decrypted) q, decrypted = read_bytes(decrypted) _, padded = read_string(decrypted) # Comment check_padding(padded) build = [Integer.from_bytes(x) for x in (n, e, d, q, p, iqmp)] return construct(build)
def _get_weak_domain(self): from crypto.Math.Numbers import Integer from crypto.Math import Primality p = Integer(4) while p.size_in_bits() != 1024 or Primality.test_probable_prime( p) != Primality.PROBABLY_PRIME: q1 = Integer.random(exact_bits=80) q2 = Integer.random(exact_bits=80) q = q1 * q2 z = Integer.random(exact_bits=1024 - 160) p = z * q + 1 h = Integer(2) g = 1 while g == 1: g = pow(h, z, p) h += 1 return (p, q, g)