win32 platform

This commit is contained in:
j 2016-01-31 20:14:46 +05:30
commit c1666978b2
1122 changed files with 348397 additions and 0 deletions

View file

@ -0,0 +1,40 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class AsymmetricSignatureContext(object):
@abc.abstractmethod
def update(self, data):
"""
Processes the provided bytes and returns nothing.
"""
@abc.abstractmethod
def finalize(self):
"""
Returns the signature as bytes.
"""
@six.add_metaclass(abc.ABCMeta)
class AsymmetricVerificationContext(object):
@abc.abstractmethod
def update(self, data):
"""
Processes the provided bytes and returns nothing.
"""
@abc.abstractmethod
def verify(self):
"""
Raises an exception if the bytes provided to update do not match the
signature or the signature does not match the public key.
"""

View file

@ -0,0 +1,166 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
import six
from cryptography import utils
class DHPrivateNumbers(object):
def __init__(self, x, public_numbers):
if not isinstance(x, six.integer_types):
raise TypeError("x must be an integer.")
if not isinstance(public_numbers, DHPublicNumbers):
raise TypeError("public_numbers must be an instance of "
"DHPublicNumbers.")
self._x = x
self._public_numbers = public_numbers
def __eq__(self, other):
if not isinstance(other, DHPrivateNumbers):
return NotImplemented
return (
self._x == other._x and
self._public_numbers == other._public_numbers
)
def __ne__(self, other):
return not self == other
public_numbers = utils.read_only_property("_public_numbers")
x = utils.read_only_property("_x")
class DHPublicNumbers(object):
def __init__(self, y, parameter_numbers):
if not isinstance(y, six.integer_types):
raise TypeError("y must be an integer.")
if not isinstance(parameter_numbers, DHParameterNumbers):
raise TypeError(
"parameters must be an instance of DHParameterNumbers.")
self._y = y
self._parameter_numbers = parameter_numbers
def __eq__(self, other):
if not isinstance(other, DHPublicNumbers):
return NotImplemented
return (
self._y == other._y and
self._parameter_numbers == other._parameter_numbers
)
def __ne__(self, other):
return not self == other
y = utils.read_only_property("_y")
parameter_numbers = utils.read_only_property("_parameter_numbers")
class DHParameterNumbers(object):
def __init__(self, p, g):
if (
not isinstance(p, six.integer_types) or
not isinstance(g, six.integer_types)
):
raise TypeError("p and g must be integers")
self._p = p
self._g = g
def __eq__(self, other):
if not isinstance(other, DHParameterNumbers):
return NotImplemented
return (
self._p == other._p and
self._g == other._g
)
def __ne__(self, other):
return not self == other
p = utils.read_only_property("_p")
g = utils.read_only_property("_g")
@six.add_metaclass(abc.ABCMeta)
class DHParameters(object):
@abc.abstractmethod
def generate_private_key(self):
"""
Generates and returns a DHPrivateKey.
"""
@six.add_metaclass(abc.ABCMeta)
class DHParametersWithSerialization(DHParameters):
@abc.abstractmethod
def parameter_numbers(self):
"""
Returns a DHParameterNumbers.
"""
@six.add_metaclass(abc.ABCMeta)
class DHPrivateKey(object):
@abc.abstractproperty
def key_size(self):
"""
The bit length of the prime modulus.
"""
@abc.abstractmethod
def public_key(self):
"""
The DHPublicKey associated with this private key.
"""
@abc.abstractmethod
def parameters(self):
"""
The DHParameters object associated with this private key.
"""
@six.add_metaclass(abc.ABCMeta)
class DHPrivateKeyWithSerialization(DHPrivateKey):
@abc.abstractmethod
def private_numbers(self):
"""
Returns a DHPrivateNumbers.
"""
@six.add_metaclass(abc.ABCMeta)
class DHPublicKey(object):
@abc.abstractproperty
def key_size(self):
"""
The bit length of the prime modulus.
"""
@abc.abstractmethod
def parameters(self):
"""
The DHParameters object associated with this public key.
"""
@six.add_metaclass(abc.ABCMeta)
class DHPublicKeyWithSerialization(DHPublicKey):
@abc.abstractmethod
def public_numbers(self):
"""
Returns a DHPublicNumbers.
"""

View file

@ -0,0 +1,229 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
import six
from cryptography import utils
@six.add_metaclass(abc.ABCMeta)
class DSAParameters(object):
@abc.abstractmethod
def generate_private_key(self):
"""
Generates and returns a DSAPrivateKey.
"""
@six.add_metaclass(abc.ABCMeta)
class DSAParametersWithNumbers(DSAParameters):
@abc.abstractmethod
def parameter_numbers(self):
"""
Returns a DSAParameterNumbers.
"""
@six.add_metaclass(abc.ABCMeta)
class DSAPrivateKey(object):
@abc.abstractproperty
def key_size(self):
"""
The bit length of the prime modulus.
"""
@abc.abstractmethod
def public_key(self):
"""
The DSAPublicKey associated with this private key.
"""
@abc.abstractmethod
def parameters(self):
"""
The DSAParameters object associated with this private key.
"""
@abc.abstractmethod
def signer(self, signature_algorithm):
"""
Returns an AsymmetricSignatureContext used for signing data.
"""
@six.add_metaclass(abc.ABCMeta)
class DSAPrivateKeyWithSerialization(DSAPrivateKey):
@abc.abstractmethod
def private_numbers(self):
"""
Returns a DSAPrivateNumbers.
"""
@abc.abstractmethod
def private_bytes(self, encoding, format, encryption_algorithm):
"""
Returns the key serialized as bytes.
"""
@six.add_metaclass(abc.ABCMeta)
class DSAPublicKey(object):
@abc.abstractproperty
def key_size(self):
"""
The bit length of the prime modulus.
"""
@abc.abstractmethod
def parameters(self):
"""
The DSAParameters object associated with this public key.
"""
@abc.abstractmethod
def verifier(self, signature, signature_algorithm):
"""
Returns an AsymmetricVerificationContext used for signing data.
"""
@abc.abstractmethod
def public_numbers(self):
"""
Returns a DSAPublicNumbers.
"""
@abc.abstractmethod
def public_bytes(self, encoding, format):
"""
Returns the key serialized as bytes.
"""
DSAPublicKeyWithSerialization = DSAPublicKey
def generate_parameters(key_size, backend):
return backend.generate_dsa_parameters(key_size)
def generate_private_key(key_size, backend):
return backend.generate_dsa_private_key_and_parameters(key_size)
def _check_dsa_parameters(parameters):
if utils.bit_length(parameters.p) not in [1024, 2048, 3072]:
raise ValueError("p must be exactly 1024, 2048, or 3072 bits long")
if utils.bit_length(parameters.q) not in [160, 256]:
raise ValueError("q must be exactly 160 or 256 bits long")
if not (1 < parameters.g < parameters.p):
raise ValueError("g, p don't satisfy 1 < g < p.")
def _check_dsa_private_numbers(numbers):
parameters = numbers.public_numbers.parameter_numbers
_check_dsa_parameters(parameters)
if numbers.x <= 0 or numbers.x >= parameters.q:
raise ValueError("x must be > 0 and < q.")
if numbers.public_numbers.y != pow(parameters.g, numbers.x, parameters.p):
raise ValueError("y must be equal to (g ** x % p).")
class DSAParameterNumbers(object):
def __init__(self, p, q, g):
if (
not isinstance(p, six.integer_types) or
not isinstance(q, six.integer_types) or
not isinstance(g, six.integer_types)
):
raise TypeError(
"DSAParameterNumbers p, q, and g arguments must be integers."
)
self._p = p
self._q = q
self._g = g
p = utils.read_only_property("_p")
q = utils.read_only_property("_q")
g = utils.read_only_property("_g")
def parameters(self, backend):
return backend.load_dsa_parameter_numbers(self)
def __eq__(self, other):
if not isinstance(other, DSAParameterNumbers):
return NotImplemented
return self.p == other.p and self.q == other.q and self.g == other.g
def __ne__(self, other):
return not self == other
class DSAPublicNumbers(object):
def __init__(self, y, parameter_numbers):
if not isinstance(y, six.integer_types):
raise TypeError("DSAPublicNumbers y argument must be an integer.")
if not isinstance(parameter_numbers, DSAParameterNumbers):
raise TypeError(
"parameter_numbers must be a DSAParameterNumbers instance."
)
self._y = y
self._parameter_numbers = parameter_numbers
y = utils.read_only_property("_y")
parameter_numbers = utils.read_only_property("_parameter_numbers")
def public_key(self, backend):
return backend.load_dsa_public_numbers(self)
def __eq__(self, other):
if not isinstance(other, DSAPublicNumbers):
return NotImplemented
return (
self.y == other.y and
self.parameter_numbers == other.parameter_numbers
)
def __ne__(self, other):
return not self == other
class DSAPrivateNumbers(object):
def __init__(self, x, public_numbers):
if not isinstance(x, six.integer_types):
raise TypeError("DSAPrivateNumbers x argument must be an integer.")
if not isinstance(public_numbers, DSAPublicNumbers):
raise TypeError(
"public_numbers must be a DSAPublicNumbers instance."
)
self._public_numbers = public_numbers
self._x = x
x = utils.read_only_property("_x")
public_numbers = utils.read_only_property("_public_numbers")
def private_key(self, backend):
return backend.load_dsa_private_numbers(self)
def __eq__(self, other):
if not isinstance(other, DSAPrivateNumbers):
return NotImplemented
return (
self.x == other.x and self.public_numbers == other.public_numbers
)
def __ne__(self, other):
return not self == other

View file

@ -0,0 +1,346 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
import six
from cryptography import utils
@six.add_metaclass(abc.ABCMeta)
class EllipticCurve(object):
@abc.abstractproperty
def name(self):
"""
The name of the curve. e.g. secp256r1.
"""
@abc.abstractproperty
def key_size(self):
"""
The bit length of the base point of the curve.
"""
@six.add_metaclass(abc.ABCMeta)
class EllipticCurveSignatureAlgorithm(object):
@abc.abstractproperty
def algorithm(self):
"""
The digest algorithm used with this signature.
"""
@six.add_metaclass(abc.ABCMeta)
class EllipticCurvePrivateKey(object):
@abc.abstractmethod
def signer(self, signature_algorithm):
"""
Returns an AsymmetricSignatureContext used for signing data.
"""
@abc.abstractmethod
def exchange(self, algorithm, peer_public_key):
"""
Performs a key exchange operation using the provided algorithm with the
provided peer's public key.
"""
@abc.abstractmethod
def public_key(self):
"""
The EllipticCurvePublicKey for this private key.
"""
@abc.abstractproperty
def curve(self):
"""
The EllipticCurve that this key is on.
"""
@six.add_metaclass(abc.ABCMeta)
class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey):
@abc.abstractmethod
def private_numbers(self):
"""
Returns an EllipticCurvePrivateNumbers.
"""
@abc.abstractmethod
def private_bytes(self, encoding, format, encryption_algorithm):
"""
Returns the key serialized as bytes.
"""
@six.add_metaclass(abc.ABCMeta)
class EllipticCurvePublicKey(object):
@abc.abstractmethod
def verifier(self, signature, signature_algorithm):
"""
Returns an AsymmetricVerificationContext used for signing data.
"""
@abc.abstractproperty
def curve(self):
"""
The EllipticCurve that this key is on.
"""
@abc.abstractmethod
def public_numbers(self):
"""
Returns an EllipticCurvePublicNumbers.
"""
@abc.abstractmethod
def public_bytes(self, encoding, format):
"""
Returns the key serialized as bytes.
"""
EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey
@utils.register_interface(EllipticCurve)
class SECT571R1(object):
name = "sect571r1"
key_size = 571
@utils.register_interface(EllipticCurve)
class SECT409R1(object):
name = "sect409r1"
key_size = 409
@utils.register_interface(EllipticCurve)
class SECT283R1(object):
name = "sect283r1"
key_size = 283
@utils.register_interface(EllipticCurve)
class SECT233R1(object):
name = "sect233r1"
key_size = 233
@utils.register_interface(EllipticCurve)
class SECT163R2(object):
name = "sect163r2"
key_size = 163
@utils.register_interface(EllipticCurve)
class SECT571K1(object):
name = "sect571k1"
key_size = 571
@utils.register_interface(EllipticCurve)
class SECT409K1(object):
name = "sect409k1"
key_size = 409
@utils.register_interface(EllipticCurve)
class SECT283K1(object):
name = "sect283k1"
key_size = 283
@utils.register_interface(EllipticCurve)
class SECT233K1(object):
name = "sect233k1"
key_size = 233
@utils.register_interface(EllipticCurve)
class SECT163K1(object):
name = "sect163k1"
key_size = 163
@utils.register_interface(EllipticCurve)
class SECP521R1(object):
name = "secp521r1"
key_size = 521
@utils.register_interface(EllipticCurve)
class SECP384R1(object):
name = "secp384r1"
key_size = 384
@utils.register_interface(EllipticCurve)
class SECP256R1(object):
name = "secp256r1"
key_size = 256
@utils.register_interface(EllipticCurve)
class SECP256K1(object):
name = "secp256k1"
key_size = 256
@utils.register_interface(EllipticCurve)
class SECP224R1(object):
name = "secp224r1"
key_size = 224
@utils.register_interface(EllipticCurve)
class SECP192R1(object):
name = "secp192r1"
key_size = 192
_CURVE_TYPES = {
"prime192v1": SECP192R1,
"prime256v1": SECP256R1,
"secp192r1": SECP192R1,
"secp224r1": SECP224R1,
"secp256r1": SECP256R1,
"secp384r1": SECP384R1,
"secp521r1": SECP521R1,
"secp256k1": SECP256K1,
"sect163k1": SECT163K1,
"sect233k1": SECT233K1,
"sect283k1": SECT283K1,
"sect409k1": SECT409K1,
"sect571k1": SECT571K1,
"sect163r2": SECT163R2,
"sect233r1": SECT233R1,
"sect283r1": SECT283R1,
"sect409r1": SECT409R1,
"sect571r1": SECT571R1,
}
@utils.register_interface(EllipticCurveSignatureAlgorithm)
class ECDSA(object):
def __init__(self, algorithm):
self._algorithm = algorithm
algorithm = utils.read_only_property("_algorithm")
def generate_private_key(curve, backend):
return backend.generate_elliptic_curve_private_key(curve)
class EllipticCurvePublicNumbers(object):
def __init__(self, x, y, curve):
if (
not isinstance(x, six.integer_types) or
not isinstance(y, six.integer_types)
):
raise TypeError("x and y must be integers.")
if not isinstance(curve, EllipticCurve):
raise TypeError("curve must provide the EllipticCurve interface.")
self._y = y
self._x = x
self._curve = curve
def public_key(self, backend):
return backend.load_elliptic_curve_public_numbers(self)
def encode_point(self):
# key_size is in bits. Convert to bytes and round up
byte_length = (self.curve.key_size + 7) // 8
return (
b'\x04' + utils.int_to_bytes(self.x, byte_length) +
utils.int_to_bytes(self.y, byte_length)
)
@classmethod
def from_encoded_point(cls, curve, data):
if not isinstance(curve, EllipticCurve):
raise TypeError("curve must be an EllipticCurve instance")
if data.startswith(b'\x04'):
# key_size is in bits. Convert to bytes and round up
byte_length = (curve.key_size + 7) // 8
if len(data) == 2 * byte_length + 1:
x = utils.int_from_bytes(data[1:byte_length + 1], 'big')
y = utils.int_from_bytes(data[byte_length + 1:], 'big')
return cls(x, y, curve)
else:
raise ValueError('Invalid elliptic curve point data length')
else:
raise ValueError('Unsupported elliptic curve point type')
curve = utils.read_only_property("_curve")
x = utils.read_only_property("_x")
y = utils.read_only_property("_y")
def __eq__(self, other):
if not isinstance(other, EllipticCurvePublicNumbers):
return NotImplemented
return (
self.x == other.x and
self.y == other.y and
self.curve.name == other.curve.name and
self.curve.key_size == other.curve.key_size
)
def __ne__(self, other):
return not self == other
def __repr__(self):
return (
"<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, "
"y={0.y}>".format(self)
)
class EllipticCurvePrivateNumbers(object):
def __init__(self, private_value, public_numbers):
if not isinstance(private_value, six.integer_types):
raise TypeError("private_value must be an integer.")
if not isinstance(public_numbers, EllipticCurvePublicNumbers):
raise TypeError(
"public_numbers must be an EllipticCurvePublicNumbers "
"instance."
)
self._private_value = private_value
self._public_numbers = public_numbers
def private_key(self, backend):
return backend.load_elliptic_curve_private_numbers(self)
private_value = utils.read_only_property("_private_value")
public_numbers = utils.read_only_property("_public_numbers")
def __eq__(self, other):
if not isinstance(other, EllipticCurvePrivateNumbers):
return NotImplemented
return (
self.private_value == other.private_value and
self.public_numbers == other.public_numbers
)
def __ne__(self, other):
return not self == other
class ECDH(object):
pass

View file

@ -0,0 +1,67 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
import six
from cryptography import utils
from cryptography.hazmat.primitives import hashes
@six.add_metaclass(abc.ABCMeta)
class AsymmetricPadding(object):
@abc.abstractproperty
def name(self):
"""
A string naming this padding (e.g. "PSS", "PKCS1").
"""
@utils.register_interface(AsymmetricPadding)
class PKCS1v15(object):
name = "EMSA-PKCS1-v1_5"
@utils.register_interface(AsymmetricPadding)
class PSS(object):
MAX_LENGTH = object()
name = "EMSA-PSS"
def __init__(self, mgf, salt_length):
self._mgf = mgf
if (not isinstance(salt_length, six.integer_types) and
salt_length is not self.MAX_LENGTH):
raise TypeError("salt_length must be an integer.")
if salt_length is not self.MAX_LENGTH and salt_length < 0:
raise ValueError("salt_length must be zero or greater.")
self._salt_length = salt_length
@utils.register_interface(AsymmetricPadding)
class OAEP(object):
name = "EME-OAEP"
def __init__(self, mgf, algorithm, label):
if not isinstance(algorithm, hashes.HashAlgorithm):
raise TypeError("Expected instance of hashes.HashAlgorithm.")
self._mgf = mgf
self._algorithm = algorithm
self._label = label
class MGF1(object):
MAX_LENGTH = object()
def __init__(self, algorithm):
if not isinstance(algorithm, hashes.HashAlgorithm):
raise TypeError("Expected instance of hashes.HashAlgorithm.")
self._algorithm = algorithm

View file

@ -0,0 +1,352 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import abc
from fractions import gcd
import six
from cryptography import utils
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
from cryptography.hazmat.backends.interfaces import RSABackend
@six.add_metaclass(abc.ABCMeta)
class RSAPrivateKey(object):
@abc.abstractmethod
def signer(self, padding, algorithm):
"""
Returns an AsymmetricSignatureContext used for signing data.
"""
@abc.abstractmethod
def decrypt(self, ciphertext, padding):
"""
Decrypts the provided ciphertext.
"""
@abc.abstractproperty
def key_size(self):
"""
The bit length of the public modulus.
"""
@abc.abstractmethod
def public_key(self):
"""
The RSAPublicKey associated with this private key.
"""
@six.add_metaclass(abc.ABCMeta)
class RSAPrivateKeyWithSerialization(RSAPrivateKey):
@abc.abstractmethod
def private_numbers(self):
"""
Returns an RSAPrivateNumbers.
"""
@abc.abstractmethod
def private_bytes(self, encoding, format, encryption_algorithm):
"""
Returns the key serialized as bytes.
"""
@six.add_metaclass(abc.ABCMeta)
class RSAPublicKey(object):
@abc.abstractmethod
def verifier(self, signature, padding, algorithm):
"""
Returns an AsymmetricVerificationContext used for verifying signatures.
"""
@abc.abstractmethod
def encrypt(self, plaintext, padding):
"""
Encrypts the given plaintext.
"""
@abc.abstractproperty
def key_size(self):
"""
The bit length of the public modulus.
"""
@abc.abstractmethod
def public_numbers(self):
"""
Returns an RSAPublicNumbers
"""
@abc.abstractmethod
def public_bytes(self, encoding, format):
"""
Returns the key serialized as bytes.
"""
RSAPublicKeyWithSerialization = RSAPublicKey
def generate_private_key(public_exponent, key_size, backend):
if not isinstance(backend, RSABackend):
raise UnsupportedAlgorithm(
"Backend object does not implement RSABackend.",
_Reasons.BACKEND_MISSING_INTERFACE
)
_verify_rsa_parameters(public_exponent, key_size)
return backend.generate_rsa_private_key(public_exponent, key_size)
def _verify_rsa_parameters(public_exponent, key_size):
if public_exponent < 3:
raise ValueError("public_exponent must be >= 3.")
if public_exponent & 1 == 0:
raise ValueError("public_exponent must be odd.")
if key_size < 512:
raise ValueError("key_size must be at least 512-bits.")
def _check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp,
public_exponent, modulus):
if modulus < 3:
raise ValueError("modulus must be >= 3.")
if p >= modulus:
raise ValueError("p must be < modulus.")
if q >= modulus:
raise ValueError("q must be < modulus.")
if dmp1 >= modulus:
raise ValueError("dmp1 must be < modulus.")
if dmq1 >= modulus:
raise ValueError("dmq1 must be < modulus.")
if iqmp >= modulus:
raise ValueError("iqmp must be < modulus.")
if private_exponent >= modulus:
raise ValueError("private_exponent must be < modulus.")
if public_exponent < 3 or public_exponent >= modulus:
raise ValueError("public_exponent must be >= 3 and < modulus.")
if public_exponent & 1 == 0:
raise ValueError("public_exponent must be odd.")
if dmp1 & 1 == 0:
raise ValueError("dmp1 must be odd.")
if dmq1 & 1 == 0:
raise ValueError("dmq1 must be odd.")
if p * q != modulus:
raise ValueError("p*q must equal modulus.")
def _check_public_key_components(e, n):
if n < 3:
raise ValueError("n must be >= 3.")
if e < 3 or e >= n:
raise ValueError("e must be >= 3 and < n.")
if e & 1 == 0:
raise ValueError("e must be odd.")
def _modinv(e, m):
"""
Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
"""
x1, y1, x2, y2 = 1, 0, 0, 1
a, b = e, m
while b > 0:
q, r = divmod(a, b)
xn, yn = x1 - q * x2, y1 - q * y2
a, b, x1, y1, x2, y2 = b, r, x2, y2, xn, yn
return x1 % m
def rsa_crt_iqmp(p, q):
"""
Compute the CRT (q ** -1) % p value from RSA primes p and q.
"""
return _modinv(q, p)
def rsa_crt_dmp1(private_exponent, p):
"""
Compute the CRT private_exponent % (p - 1) value from the RSA
private_exponent and p.
"""
return private_exponent % (p - 1)
def rsa_crt_dmq1(private_exponent, q):
"""
Compute the CRT private_exponent % (q - 1) value from the RSA
private_exponent and q.
"""
return private_exponent % (q - 1)
# Controls the number of iterations rsa_recover_prime_factors will perform
# to obtain the prime factors. Each iteration increments by 2 so the actual
# maximum attempts is half this number.
_MAX_RECOVERY_ATTEMPTS = 1000
def rsa_recover_prime_factors(n, e, d):
"""
Compute factors p and q from the private exponent d. We assume that n has
no more than two factors. This function is adapted from code in PyCrypto.
"""
# See 8.2.2(i) in Handbook of Applied Cryptography.
ktot = d * e - 1
# The quantity d*e-1 is a multiple of phi(n), even,
# and can be represented as t*2^s.
t = ktot
while t % 2 == 0:
t = t // 2
# Cycle through all multiplicative inverses in Zn.
# The algorithm is non-deterministic, but there is a 50% chance
# any candidate a leads to successful factoring.
# See "Digitalized Signatures and Public Key Functions as Intractable
# as Factorization", M. Rabin, 1979
spotted = False
a = 2
while not spotted and a < _MAX_RECOVERY_ATTEMPTS:
k = t
# Cycle through all values a^{t*2^i}=a^k
while k < ktot:
cand = pow(a, k, n)
# Check if a^k is a non-trivial root of unity (mod n)
if cand != 1 and cand != (n - 1) and pow(cand, 2, n) == 1:
# We have found a number such that (cand-1)(cand+1)=0 (mod n).
# Either of the terms divides n.
p = gcd(cand + 1, n)
spotted = True
break
k *= 2
# This value was not any good... let's try another!
a += 2
if not spotted:
raise ValueError("Unable to compute factors p and q from exponent d.")
# Found !
q, r = divmod(n, p)
assert r == 0
return (p, q)
class RSAPrivateNumbers(object):
def __init__(self, p, q, d, dmp1, dmq1, iqmp,
public_numbers):
if (
not isinstance(p, six.integer_types) or
not isinstance(q, six.integer_types) or
not isinstance(d, six.integer_types) or
not isinstance(dmp1, six.integer_types) or
not isinstance(dmq1, six.integer_types) or
not isinstance(iqmp, six.integer_types)
):
raise TypeError(
"RSAPrivateNumbers p, q, d, dmp1, dmq1, iqmp arguments must"
" all be an integers."
)
if not isinstance(public_numbers, RSAPublicNumbers):
raise TypeError(
"RSAPrivateNumbers public_numbers must be an RSAPublicNumbers"
" instance."
)
self._p = p
self._q = q
self._d = d
self._dmp1 = dmp1
self._dmq1 = dmq1
self._iqmp = iqmp
self._public_numbers = public_numbers
p = utils.read_only_property("_p")
q = utils.read_only_property("_q")
d = utils.read_only_property("_d")
dmp1 = utils.read_only_property("_dmp1")
dmq1 = utils.read_only_property("_dmq1")
iqmp = utils.read_only_property("_iqmp")
public_numbers = utils.read_only_property("_public_numbers")
def private_key(self, backend):
return backend.load_rsa_private_numbers(self)
def __eq__(self, other):
if not isinstance(other, RSAPrivateNumbers):
return NotImplemented
return (
self.p == other.p and
self.q == other.q and
self.d == other.d and
self.dmp1 == other.dmp1 and
self.dmq1 == other.dmq1 and
self.iqmp == other.iqmp and
self.public_numbers == other.public_numbers
)
def __ne__(self, other):
return not self == other
def __hash__(self):
return hash((
self.p,
self.q,
self.d,
self.dmp1,
self.dmq1,
self.iqmp,
self.public_numbers,
))
class RSAPublicNumbers(object):
def __init__(self, e, n):
if (
not isinstance(e, six.integer_types) or
not isinstance(n, six.integer_types)
):
raise TypeError("RSAPublicNumbers arguments must be integers.")
self._e = e
self._n = n
e = utils.read_only_property("_e")
n = utils.read_only_property("_n")
def public_key(self, backend):
return backend.load_rsa_public_numbers(self)
def __repr__(self):
return "<RSAPublicNumbers(e={0.e}, n={0.n})>".format(self)
def __eq__(self, other):
if not isinstance(other, RSAPublicNumbers):
return NotImplemented
return self.e == other.e and self.n == other.n
def __ne__(self, other):
return not self == other
def __hash__(self):
return hash((self.e, self.n))

View file

@ -0,0 +1,73 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import warnings
from pyasn1.codec.der import decoder, encoder
from pyasn1.error import PyAsn1Error
from pyasn1.type import namedtype, univ
import six
from cryptography import utils
class _DSSSigValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('r', univ.Integer()),
namedtype.NamedType('s', univ.Integer())
)
def decode_rfc6979_signature(signature):
warnings.warn(
"decode_rfc6979_signature is deprecated and will "
"be removed in a future version, use decode_dss_signature instead "
"instead.",
utils.DeprecatedIn10,
stacklevel=2
)
return decode_dss_signature(signature)
def decode_dss_signature(signature):
try:
data, remaining = decoder.decode(signature, asn1Spec=_DSSSigValue())
except PyAsn1Error:
raise ValueError("Invalid signature data. Unable to decode ASN.1")
if remaining:
raise ValueError(
"The signature contains bytes after the end of the ASN.1 sequence."
)
r = int(data.getComponentByName('r'))
s = int(data.getComponentByName('s'))
return (r, s)
def encode_rfc6979_signature(r, s):
warnings.warn(
"encode_rfc6979_signature is deprecated and will "
"be removed in a future version, use encode_dss_signature instead "
"instead.",
utils.DeprecatedIn10,
stacklevel=2
)
return encode_dss_signature(r, s)
def encode_dss_signature(r, s):
if (
not isinstance(r, six.integer_types) or
not isinstance(s, six.integer_types)
):
raise ValueError("Both r and s must be integers")
sig = _DSSSigValue()
sig.setComponentByName('r', r)
sig.setComponentByName('s', s)
return encoder.encode(sig)