update Darwin
This commit is contained in:
parent
89ee84c73e
commit
531041e89a
1705 changed files with 6511 additions and 459836 deletions
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import warnings
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
|
|
@ -21,31 +23,54 @@ from cryptography.hazmat.backends.interfaces import DSABackend
|
|||
from cryptography.hazmat.primitives import interfaces
|
||||
|
||||
|
||||
def _check_dsa_parameters(modulus, subgroup_order, generator):
|
||||
if (
|
||||
not isinstance(modulus, six.integer_types) or
|
||||
not isinstance(subgroup_order, six.integer_types) or
|
||||
not isinstance(generator, six.integer_types)
|
||||
):
|
||||
raise TypeError("DSA parameters must be integers")
|
||||
def generate_parameters(key_size, backend):
|
||||
return backend.generate_dsa_parameters(key_size)
|
||||
|
||||
if (utils.bit_length(modulus),
|
||||
utils.bit_length(subgroup_order)) not in (
|
||||
|
||||
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),
|
||||
utils.bit_length(parameters.q)) not in (
|
||||
(1024, 160),
|
||||
(2048, 256),
|
||||
(3072, 256)):
|
||||
raise ValueError("modulus and subgroup_order lengths must be "
|
||||
raise ValueError("p and q lengths must be "
|
||||
"one of these pairs (1024, 160) or (2048, 256) "
|
||||
"or (3072, 256)")
|
||||
"or (3072, 256).")
|
||||
|
||||
if generator <= 1 or generator >= modulus:
|
||||
raise ValueError("generator must be > 1 and < modulus")
|
||||
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).")
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.DSAParameters)
|
||||
class DSAParameters(object):
|
||||
def __init__(self, modulus, subgroup_order, generator):
|
||||
_check_dsa_parameters(modulus, subgroup_order, generator)
|
||||
warnings.warn(
|
||||
"The DSAParameters class is deprecated and will be removed in a "
|
||||
"future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
_check_dsa_parameters(
|
||||
DSAParameterNumbers(
|
||||
p=modulus,
|
||||
q=subgroup_order,
|
||||
g=generator
|
||||
)
|
||||
)
|
||||
|
||||
self._modulus = modulus
|
||||
self._subgroup_order = subgroup_order
|
||||
|
|
@ -53,13 +78,24 @@ class DSAParameters(object):
|
|||
|
||||
@classmethod
|
||||
def generate(cls, key_size, backend):
|
||||
warnings.warn(
|
||||
"generate is deprecated and will be removed in a future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
"Backend object does not implement DSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
return backend.generate_dsa_parameters(key_size)
|
||||
parameters = backend.generate_dsa_parameters(key_size)
|
||||
numbers = parameters.parameter_numbers()
|
||||
return cls(
|
||||
modulus=numbers.p,
|
||||
subgroup_order=numbers.q,
|
||||
generator=numbers.g
|
||||
)
|
||||
|
||||
@property
|
||||
def modulus(self):
|
||||
|
|
@ -89,18 +125,31 @@ class DSAParameters(object):
|
|||
@utils.register_interface(interfaces.DSAPrivateKey)
|
||||
class DSAPrivateKey(object):
|
||||
def __init__(self, modulus, subgroup_order, generator, x, y):
|
||||
_check_dsa_parameters(modulus, subgroup_order, generator)
|
||||
warnings.warn(
|
||||
"The DSAPrivateKey class is deprecated and will be removed in a "
|
||||
"future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if (
|
||||
not isinstance(x, six.integer_types) or
|
||||
not isinstance(y, six.integer_types)
|
||||
):
|
||||
raise TypeError("DSAPrivateKey arguments must be integers")
|
||||
raise TypeError("DSAPrivateKey arguments must be integers.")
|
||||
|
||||
if x <= 0 or x >= subgroup_order:
|
||||
raise ValueError("x must be > 0 and < subgroup_order")
|
||||
|
||||
if y != pow(generator, x, modulus):
|
||||
raise ValueError("y must be equal to (generator ** x % modulus)")
|
||||
_check_dsa_private_numbers(
|
||||
DSAPrivateNumbers(
|
||||
public_numbers=DSAPublicNumbers(
|
||||
parameter_numbers=DSAParameterNumbers(
|
||||
p=modulus,
|
||||
q=subgroup_order,
|
||||
g=generator
|
||||
),
|
||||
y=y
|
||||
),
|
||||
x=x
|
||||
)
|
||||
)
|
||||
|
||||
self._modulus = modulus
|
||||
self._subgroup_order = subgroup_order
|
||||
|
|
@ -110,18 +159,31 @@ class DSAPrivateKey(object):
|
|||
|
||||
@classmethod
|
||||
def generate(cls, parameters, backend):
|
||||
warnings.warn(
|
||||
"generate is deprecated and will be removed in a future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
"Backend object does not implement DSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
return backend.generate_dsa_private_key(parameters)
|
||||
key = backend.generate_dsa_private_key(parameters)
|
||||
private_numbers = key.private_numbers()
|
||||
return cls(
|
||||
modulus=private_numbers.public_numbers.parameter_numbers.p,
|
||||
subgroup_order=private_numbers.public_numbers.parameter_numbers.q,
|
||||
generator=private_numbers.public_numbers.parameter_numbers.g,
|
||||
x=private_numbers.x,
|
||||
y=private_numbers.public_numbers.y
|
||||
)
|
||||
|
||||
def signer(self, algorithm, backend):
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
"Backend object does not implement DSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -151,9 +213,21 @@ class DSAPrivateKey(object):
|
|||
@utils.register_interface(interfaces.DSAPublicKey)
|
||||
class DSAPublicKey(object):
|
||||
def __init__(self, modulus, subgroup_order, generator, y):
|
||||
_check_dsa_parameters(modulus, subgroup_order, generator)
|
||||
warnings.warn(
|
||||
"The DSAPublicKey class is deprecated and will be removed in a "
|
||||
"future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
_check_dsa_parameters(
|
||||
DSAParameterNumbers(
|
||||
p=modulus,
|
||||
q=subgroup_order,
|
||||
g=generator
|
||||
)
|
||||
)
|
||||
if not isinstance(y, six.integer_types):
|
||||
raise TypeError("y must be an integer")
|
||||
raise TypeError("y must be an integer.")
|
||||
|
||||
self._modulus = modulus
|
||||
self._subgroup_order = subgroup_order
|
||||
|
|
@ -163,7 +237,7 @@ class DSAPublicKey(object):
|
|||
def verifier(self, signature, algorithm, backend):
|
||||
if not isinstance(backend, DSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement DSABackend",
|
||||
"Backend object does not implement DSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -181,3 +255,83 @@ class DSAPublicKey(object):
|
|||
def parameters(self):
|
||||
return DSAParameters(self._modulus, self._subgroup_order,
|
||||
self._generator)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def p(self):
|
||||
return self._p
|
||||
|
||||
@property
|
||||
def q(self):
|
||||
return self._q
|
||||
|
||||
@property
|
||||
def g(self):
|
||||
return self._g
|
||||
|
||||
def parameters(self, backend):
|
||||
return backend.load_dsa_parameter_numbers(self)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._y
|
||||
|
||||
@property
|
||||
def parameter_numbers(self):
|
||||
return self._parameter_numbers
|
||||
|
||||
def public_key(self, backend):
|
||||
return backend.load_dsa_public_numbers(self)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._x
|
||||
|
||||
@property
|
||||
def public_numbers(self):
|
||||
return self._public_numbers
|
||||
|
||||
def private_key(self, backend):
|
||||
return backend.load_dsa_private_numbers(self)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,255 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT571R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect571r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 571
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT409R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect409r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 409
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT283R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect283r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 283
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT233R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect233r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 233
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT163R2(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect163r2"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 163
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT571K1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect571k1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 571
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT409K1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect409k1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 409
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT283K1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect283k1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 283
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT233K1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect233k1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 233
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECT163K1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "sect163k1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 163
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECP521R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "secp521r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 521
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECP384R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "secp384r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 384
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECP256R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "secp256r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 256
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECP224R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "secp224r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 224
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurve)
|
||||
class SECP192R1(object):
|
||||
@property
|
||||
def name(self):
|
||||
return "secp192r1"
|
||||
|
||||
@property
|
||||
def key_size(self):
|
||||
return 192
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.EllipticCurveSignatureAlgorithm)
|
||||
class ECDSA(object):
|
||||
def __init__(self, algorithm):
|
||||
self._algorithm = algorithm
|
||||
|
||||
@property
|
||||
def algorithm(self):
|
||||
return self._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, interfaces.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.elliptic_curve_public_key_from_numbers(self)
|
||||
|
||||
@property
|
||||
def curve(self):
|
||||
return self._curve
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._x
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._y
|
||||
|
||||
|
||||
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.elliptic_curve_private_key_from_numbers(self)
|
||||
|
||||
@property
|
||||
def private_value(self):
|
||||
return self._private_value
|
||||
|
||||
@property
|
||||
def public_numbers(self):
|
||||
return self._public_numbers
|
||||
|
|
@ -38,18 +38,19 @@ class PSS(object):
|
|||
warnings.warn(
|
||||
"salt_length is deprecated on MGF1 and should be added via the"
|
||||
" PSS constructor.",
|
||||
utils.DeprecatedIn04
|
||||
utils.DeprecatedIn04,
|
||||
stacklevel=2
|
||||
)
|
||||
else:
|
||||
if (not isinstance(salt_length, six.integer_types) and
|
||||
salt_length is not self.MAX_LENGTH):
|
||||
raise TypeError("salt_length must be an integer")
|
||||
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")
|
||||
raise ValueError("salt_length must be zero or greater.")
|
||||
|
||||
if salt_length is None and self._mgf._salt_length is None:
|
||||
raise ValueError("You must supply salt_length")
|
||||
raise ValueError("You must supply salt_length.")
|
||||
|
||||
self._salt_length = salt_length
|
||||
|
||||
|
|
@ -80,13 +81,14 @@ class MGF1(object):
|
|||
warnings.warn(
|
||||
"salt_length is deprecated on MGF1 and should be passed to "
|
||||
"the PSS constructor instead.",
|
||||
utils.DeprecatedIn04
|
||||
utils.DeprecatedIn04,
|
||||
stacklevel=2
|
||||
)
|
||||
if (not isinstance(salt_length, six.integer_types) and
|
||||
salt_length is not self.MAX_LENGTH):
|
||||
raise TypeError("salt_length must be an integer")
|
||||
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")
|
||||
raise ValueError("salt_length must be zero or greater.")
|
||||
|
||||
self._salt_length = salt_length
|
||||
|
|
|
|||
|
|
@ -13,31 +13,102 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import warnings
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.backends.interfaces import RSABackend
|
||||
from cryptography.hazmat.primitives import interfaces
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.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.")
|
||||
|
||||
|
||||
class RSAPublicKey(object):
|
||||
def __init__(self, public_exponent, modulus):
|
||||
warnings.warn(
|
||||
"The RSAPublicKey class is deprecated and will be removed in a "
|
||||
"future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if (
|
||||
not isinstance(public_exponent, six.integer_types) or
|
||||
not isinstance(modulus, six.integer_types)
|
||||
):
|
||||
raise TypeError("RSAPublicKey arguments must be integers")
|
||||
raise TypeError("RSAPublicKey arguments must be integers.")
|
||||
|
||||
if modulus < 3:
|
||||
raise ValueError("modulus must be >= 3")
|
||||
|
||||
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")
|
||||
_check_public_key_components(public_exponent, modulus)
|
||||
|
||||
self._public_exponent = public_exponent
|
||||
self._modulus = modulus
|
||||
|
|
@ -45,7 +116,7 @@ class RSAPublicKey(object):
|
|||
def verifier(self, signature, padding, algorithm, backend):
|
||||
if not isinstance(backend, RSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement RSABackend",
|
||||
"Backend object does not implement RSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -55,7 +126,7 @@ class RSAPublicKey(object):
|
|||
def encrypt(self, plaintext, padding, backend):
|
||||
if not isinstance(backend, RSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement RSABackend",
|
||||
"Backend object does not implement RSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -118,10 +189,15 @@ def rsa_crt_dmq1(private_exponent, q):
|
|||
return private_exponent % (q - 1)
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.RSAPrivateKey)
|
||||
class RSAPrivateKey(object):
|
||||
def __init__(self, p, q, private_exponent, dmp1, dmq1, iqmp,
|
||||
public_exponent, modulus):
|
||||
warnings.warn(
|
||||
"The RSAPrivateKey class is deprecated and will be removed in a "
|
||||
"future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if (
|
||||
not isinstance(p, six.integer_types) or
|
||||
not isinstance(q, six.integer_types) or
|
||||
|
|
@ -132,43 +208,10 @@ class RSAPrivateKey(object):
|
|||
not isinstance(public_exponent, six.integer_types) or
|
||||
not isinstance(modulus, six.integer_types)
|
||||
):
|
||||
raise TypeError("RSAPrivateKey arguments must be integers")
|
||||
raise TypeError("RSAPrivateKey arguments must be integers.")
|
||||
|
||||
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")
|
||||
_check_private_key_components(p, q, private_exponent, dmp1, dmq1, iqmp,
|
||||
public_exponent, modulus)
|
||||
|
||||
self._p = p
|
||||
self._q = q
|
||||
|
|
@ -181,18 +224,35 @@ class RSAPrivateKey(object):
|
|||
|
||||
@classmethod
|
||||
def generate(cls, public_exponent, key_size, backend):
|
||||
warnings.warn(
|
||||
"generate is deprecated and will be removed in a future version.",
|
||||
utils.DeprecatedIn05,
|
||||
stacklevel=2
|
||||
)
|
||||
if not isinstance(backend, RSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement RSABackend",
|
||||
"Backend object does not implement RSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
return backend.generate_rsa_private_key(public_exponent, key_size)
|
||||
_verify_rsa_parameters(public_exponent, key_size)
|
||||
key = backend.generate_rsa_private_key(public_exponent, key_size)
|
||||
private_numbers = key.private_numbers()
|
||||
return RSAPrivateKey(
|
||||
p=private_numbers.p,
|
||||
q=private_numbers.q,
|
||||
dmp1=private_numbers.dmp1,
|
||||
dmq1=private_numbers.dmq1,
|
||||
iqmp=private_numbers.iqmp,
|
||||
private_exponent=private_numbers.d,
|
||||
public_exponent=private_numbers.public_numbers.e,
|
||||
modulus=private_numbers.public_numbers.n
|
||||
)
|
||||
|
||||
def signer(self, padding, algorithm, backend):
|
||||
if not isinstance(backend, RSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement RSABackend",
|
||||
"Backend object does not implement RSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -201,7 +261,7 @@ class RSAPrivateKey(object):
|
|||
def decrypt(self, ciphertext, padding, backend):
|
||||
if not isinstance(backend, RSABackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement RSABackend",
|
||||
"Backend object does not implement RSABackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -257,3 +317,88 @@ class RSAPrivateKey(object):
|
|||
@property
|
||||
def n(self):
|
||||
return self.modulus
|
||||
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def p(self):
|
||||
return self._p
|
||||
|
||||
@property
|
||||
def q(self):
|
||||
return self._q
|
||||
|
||||
@property
|
||||
def d(self):
|
||||
return self._d
|
||||
|
||||
@property
|
||||
def dmp1(self):
|
||||
return self._dmp1
|
||||
|
||||
@property
|
||||
def dmq1(self):
|
||||
return self._dmq1
|
||||
|
||||
@property
|
||||
def iqmp(self):
|
||||
return self._iqmp
|
||||
|
||||
@property
|
||||
def public_numbers(self):
|
||||
return self._public_numbers
|
||||
|
||||
def private_key(self, backend):
|
||||
return backend.load_rsa_private_numbers(self)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def e(self):
|
||||
return self._e
|
||||
|
||||
@property
|
||||
def n(self):
|
||||
return self._n
|
||||
|
||||
def public_key(self, backend):
|
||||
return backend.load_rsa_public_numbers(self)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from cryptography.hazmat.primitives import interfaces
|
|||
def _verify_key_size(algorithm, key):
|
||||
# Verify that the key size matches the expected key size
|
||||
if len(key) * 8 not in algorithm.key_sizes:
|
||||
raise ValueError("Invalid key size ({0}) for {1}".format(
|
||||
raise ValueError("Invalid key size ({0}) for {1}.".format(
|
||||
len(key) * 8, algorithm.name
|
||||
))
|
||||
return key
|
||||
|
|
|
|||
|
|
@ -26,12 +26,14 @@ class Cipher(object):
|
|||
def __init__(self, algorithm, mode, backend):
|
||||
if not isinstance(backend, CipherBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement CipherBackend",
|
||||
"Backend object does not implement CipherBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
if not isinstance(algorithm, interfaces.CipherAlgorithm):
|
||||
raise TypeError("Expected interface of interfaces.CipherAlgorithm")
|
||||
raise TypeError(
|
||||
"Expected interface of interfaces.CipherAlgorithm."
|
||||
)
|
||||
|
||||
if mode is not None:
|
||||
mode.validate_for_algorithm(algorithm)
|
||||
|
|
@ -44,7 +46,7 @@ class Cipher(object):
|
|||
if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
|
||||
if self.mode.tag is not None:
|
||||
raise ValueError(
|
||||
"Authentication tag must be None when encrypting"
|
||||
"Authentication tag must be None when encrypting."
|
||||
)
|
||||
ctx = self._backend.create_symmetric_encryption_ctx(
|
||||
self.algorithm, self.mode
|
||||
|
|
@ -55,7 +57,7 @@ class Cipher(object):
|
|||
if isinstance(self.mode, interfaces.ModeWithAuthenticationTag):
|
||||
if self.mode.tag is None:
|
||||
raise ValueError(
|
||||
"Authentication tag must be provided when decrypting"
|
||||
"Authentication tag must be provided when decrypting."
|
||||
)
|
||||
ctx = self._backend.create_symmetric_decryption_ctx(
|
||||
self.algorithm, self.mode
|
||||
|
|
@ -79,12 +81,12 @@ class _CipherContext(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
return self._ctx.update(data)
|
||||
|
||||
def finalize(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
data = self._ctx.finalize()
|
||||
self._ctx = None
|
||||
return data
|
||||
|
|
@ -100,13 +102,13 @@ class _AEADCipherContext(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
self._updated = True
|
||||
return self._ctx.update(data)
|
||||
|
||||
def finalize(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
data = self._ctx.finalize()
|
||||
self._tag = self._ctx.tag
|
||||
self._ctx = None
|
||||
|
|
@ -114,9 +116,9 @@ class _AEADCipherContext(object):
|
|||
|
||||
def authenticate_additional_data(self, data):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
if self._updated:
|
||||
raise AlreadyUpdated("Update has been called on this context")
|
||||
raise AlreadyUpdated("Update has been called on this context.")
|
||||
self._ctx.authenticate_additional_data(data)
|
||||
|
||||
|
||||
|
|
@ -126,5 +128,5 @@ class _AEADEncryptionContext(_AEADCipherContext):
|
|||
def tag(self):
|
||||
if self._ctx is not None:
|
||||
raise NotYetFinalized("You must finalize encryption before "
|
||||
"getting the tag")
|
||||
"getting the tag.")
|
||||
return self._tag
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ from cryptography import utils
|
|||
from cryptography.hazmat.primitives import interfaces
|
||||
|
||||
|
||||
def _check_iv_length(mode, algorithm):
|
||||
if len(mode.initialization_vector) * 8 != algorithm.block_size:
|
||||
raise ValueError("Invalid IV size ({0}) for {1}.".format(
|
||||
len(mode.initialization_vector), mode.name
|
||||
))
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
@utils.register_interface(interfaces.ModeWithInitializationVector)
|
||||
class CBC(object):
|
||||
|
|
@ -25,11 +32,7 @@ class CBC(object):
|
|||
def __init__(self, initialization_vector):
|
||||
self.initialization_vector = initialization_vector
|
||||
|
||||
def validate_for_algorithm(self, algorithm):
|
||||
if len(self.initialization_vector) * 8 != algorithm.block_size:
|
||||
raise ValueError("Invalid iv size ({0}) for {1}".format(
|
||||
len(self.initialization_vector), self.name
|
||||
))
|
||||
validate_for_algorithm = _check_iv_length
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
|
|
@ -48,11 +51,7 @@ class OFB(object):
|
|||
def __init__(self, initialization_vector):
|
||||
self.initialization_vector = initialization_vector
|
||||
|
||||
def validate_for_algorithm(self, algorithm):
|
||||
if len(self.initialization_vector) * 8 != algorithm.block_size:
|
||||
raise ValueError("Invalid iv size ({0}) for {1}".format(
|
||||
len(self.initialization_vector), self.name
|
||||
))
|
||||
validate_for_algorithm = _check_iv_length
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
|
|
@ -63,11 +62,18 @@ class CFB(object):
|
|||
def __init__(self, initialization_vector):
|
||||
self.initialization_vector = initialization_vector
|
||||
|
||||
def validate_for_algorithm(self, algorithm):
|
||||
if len(self.initialization_vector) * 8 != algorithm.block_size:
|
||||
raise ValueError("Invalid iv size ({0}) for {1}".format(
|
||||
len(self.initialization_vector), self.name
|
||||
))
|
||||
validate_for_algorithm = _check_iv_length
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
@utils.register_interface(interfaces.ModeWithInitializationVector)
|
||||
class CFB8(object):
|
||||
name = "CFB8"
|
||||
|
||||
def __init__(self, initialization_vector):
|
||||
self.initialization_vector = initialization_vector
|
||||
|
||||
validate_for_algorithm = _check_iv_length
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.Mode)
|
||||
|
|
@ -80,7 +86,7 @@ class CTR(object):
|
|||
|
||||
def validate_for_algorithm(self, algorithm):
|
||||
if len(self.nonce) * 8 != algorithm.block_size:
|
||||
raise ValueError("Invalid nonce size ({0}) for {1}".format(
|
||||
raise ValueError("Invalid nonce size ({0}) for {1}.".format(
|
||||
len(self.nonce), self.name
|
||||
))
|
||||
|
||||
|
|
@ -91,13 +97,16 @@ class CTR(object):
|
|||
class GCM(object):
|
||||
name = "GCM"
|
||||
|
||||
def __init__(self, initialization_vector, tag=None):
|
||||
def __init__(self, initialization_vector, tag=None, min_tag_length=16):
|
||||
# len(initialization_vector) must in [1, 2 ** 64), but it's impossible
|
||||
# to actually construct a bytes object that large, so we don't check
|
||||
# for it
|
||||
if tag is not None and len(tag) < 4:
|
||||
if min_tag_length < 4:
|
||||
raise ValueError("min_tag_length must be >= 4")
|
||||
if tag is not None and len(tag) < min_tag_length:
|
||||
raise ValueError(
|
||||
"Authentication tag must be 4 bytes or longer"
|
||||
"Authentication tag must be {0} bytes or longer.".format(
|
||||
min_tag_length)
|
||||
)
|
||||
|
||||
self.initialization_vector = initialization_vector
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import (
|
||||
AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||
|
|
@ -28,13 +26,13 @@ class CMAC(object):
|
|||
def __init__(self, algorithm, backend, ctx=None):
|
||||
if not isinstance(backend, CMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement CMACBackend",
|
||||
"Backend object does not implement CMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
if not isinstance(algorithm, interfaces.BlockCipherAlgorithm):
|
||||
raise TypeError(
|
||||
"Expected instance of interfaces.BlockCipherAlgorithm"
|
||||
"Expected instance of interfaces.BlockCipherAlgorithm."
|
||||
)
|
||||
self._algorithm = algorithm
|
||||
|
||||
|
|
@ -46,28 +44,28 @@ class CMAC(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
if isinstance(data, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before hashing")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("data must be bytes.")
|
||||
self._ctx.update(data)
|
||||
|
||||
def finalize(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
digest = self._ctx.finalize()
|
||||
self._ctx = None
|
||||
return digest
|
||||
|
||||
def verify(self, signature):
|
||||
if isinstance(signature, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before verifying")
|
||||
if not isinstance(signature, bytes):
|
||||
raise TypeError("signature must be bytes.")
|
||||
digest = self.finalize()
|
||||
if not constant_time.bytes_eq(digest, signature):
|
||||
raise InvalidSignature("Signature did not match digest.")
|
||||
|
||||
def copy(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
return CMAC(
|
||||
self._algorithm,
|
||||
backend=self._backend,
|
||||
|
|
|
|||
|
|
@ -13,12 +13,11 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import hmac
|
||||
import sys
|
||||
|
||||
import cffi
|
||||
|
||||
import six
|
||||
|
||||
from cryptography.hazmat.bindings.utils import _create_modulename
|
||||
|
||||
TYPES = """
|
||||
|
|
@ -55,9 +54,18 @@ _lib = _ffi.verify(
|
|||
ext_package="cryptography",
|
||||
)
|
||||
|
||||
if hasattr(hmac, "compare_digest"):
|
||||
def bytes_eq(a, b):
|
||||
if not isinstance(a, bytes) or not isinstance(b, bytes):
|
||||
raise TypeError("a and b must be bytes.")
|
||||
|
||||
def bytes_eq(a, b):
|
||||
if isinstance(a, six.text_type) or isinstance(b, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before comparing")
|
||||
return hmac.compare_digest(a, b)
|
||||
|
||||
return _lib.Cryptography_constant_time_bytes_eq(a, len(a), b, len(b)) == 1
|
||||
else:
|
||||
def bytes_eq(a, b):
|
||||
if not isinstance(a, bytes) or not isinstance(b, bytes):
|
||||
raise TypeError("a and b must be bytes.")
|
||||
|
||||
return _lib.Cryptography_constant_time_bytes_eq(
|
||||
a, len(a), b, len(b)
|
||||
) == 1
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import (
|
||||
AlreadyFinalized, UnsupportedAlgorithm, _Reasons
|
||||
|
|
@ -28,7 +26,7 @@ class Hash(object):
|
|||
def __init__(self, algorithm, backend, ctx=None):
|
||||
if not isinstance(backend, HashBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HashBackend",
|
||||
"Backend object does not implement HashBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -45,21 +43,21 @@ class Hash(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
if isinstance(data, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before hashing")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("data must be bytes.")
|
||||
self._ctx.update(data)
|
||||
|
||||
def copy(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
return Hash(
|
||||
self.algorithm, backend=self._backend, ctx=self._ctx.copy()
|
||||
)
|
||||
|
||||
def finalize(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
digest = self._ctx.finalize()
|
||||
self._ctx = None
|
||||
return digest
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import (
|
||||
AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
|
||||
|
|
@ -28,7 +26,7 @@ class HMAC(object):
|
|||
def __init__(self, key, algorithm, backend, ctx=None):
|
||||
if not isinstance(backend, HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HMACBackend",
|
||||
"Backend object does not implement HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -45,14 +43,14 @@ class HMAC(object):
|
|||
|
||||
def update(self, msg):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
if isinstance(msg, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before hashing")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
if not isinstance(msg, bytes):
|
||||
raise TypeError("msg must be bytes.")
|
||||
self._ctx.update(msg)
|
||||
|
||||
def copy(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
return HMAC(
|
||||
self._key,
|
||||
self.algorithm,
|
||||
|
|
@ -62,14 +60,14 @@ class HMAC(object):
|
|||
|
||||
def finalize(self):
|
||||
if self._ctx is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
digest = self._ctx.finalize()
|
||||
self._ctx = None
|
||||
return digest
|
||||
|
||||
def verify(self, signature):
|
||||
if isinstance(signature, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before verifying")
|
||||
if not isinstance(signature, bytes):
|
||||
raise TypeError("signature must be bytes.")
|
||||
digest = self.finalize()
|
||||
if not constant_time.bytes_eq(digest, signature):
|
||||
raise InvalidSignature("Signature did not match digest.")
|
||||
|
|
|
|||
|
|
@ -186,27 +186,15 @@ class HashContext(object):
|
|||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RSAPrivateKey(object):
|
||||
@abc.abstractmethod
|
||||
def signer(self, padding, algorithm, backend):
|
||||
def signer(self, padding, algorithm):
|
||||
"""
|
||||
Returns an AsymmetricSignatureContext used for signing data.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def modulus(self):
|
||||
@abc.abstractmethod
|
||||
def decrypt(self, ciphertext, padding):
|
||||
"""
|
||||
The public modulus of the RSA key.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def public_exponent(self):
|
||||
"""
|
||||
The public exponent of the RSA key.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def private_exponent(self):
|
||||
"""
|
||||
The private exponent of the RSA key.
|
||||
Decrypts the provided ciphertext.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
|
|
@ -221,77 +209,28 @@ class RSAPrivateKey(object):
|
|||
The RSAPublicKey associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def n(self):
|
||||
"""
|
||||
The public modulus of the RSA key. Alias for modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def p(self):
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RSAPrivateKeyWithNumbers(RSAPrivateKey):
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self):
|
||||
"""
|
||||
One of the two primes used to generate d.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def q(self):
|
||||
"""
|
||||
One of the two primes used to generate d.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def d(self):
|
||||
"""
|
||||
The private exponent. This can be calculated using p and q. Alias for
|
||||
private_exponent.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def dmp1(self):
|
||||
"""
|
||||
A Chinese remainder theorem coefficient used to speed up RSA
|
||||
calculations. Calculated as: d mod (p-1)
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def dmq1(self):
|
||||
"""
|
||||
A Chinese remainder theorem coefficient used to speed up RSA
|
||||
calculations. Calculated as: d mod (q-1)
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def iqmp(self):
|
||||
"""
|
||||
A Chinese remainder theorem coefficient used to speed up RSA
|
||||
calculations. The modular inverse of q modulo p
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def e(self):
|
||||
"""
|
||||
The public exponent of the RSA key. Alias for public_exponent.
|
||||
Returns an RSAPrivateNumbers.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RSAPublicKey(object):
|
||||
@abc.abstractmethod
|
||||
def verifier(self, signature, padding, algorithm, backend):
|
||||
def verifier(self, signature, padding, algorithm):
|
||||
"""
|
||||
Returns an AsymmetricVerificationContext used for verifying signatures.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def modulus(self):
|
||||
@abc.abstractmethod
|
||||
def encrypt(self, plaintext, padding):
|
||||
"""
|
||||
The public modulus of the RSA key.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def public_exponent(self):
|
||||
"""
|
||||
The public exponent of the RSA key.
|
||||
Encrypts the given plaintext.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
|
|
@ -300,63 +239,31 @@ class RSAPublicKey(object):
|
|||
The bit length of the public modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def n(self):
|
||||
"""
|
||||
The public modulus of the RSA key. Alias for modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def e(self):
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RSAPublicKeyWithNumbers(RSAPublicKey):
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self):
|
||||
"""
|
||||
The public exponent of the RSA key. Alias for public_exponent.
|
||||
Returns an RSAPublicNumbers
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DSAParameters(object):
|
||||
@abc.abstractproperty
|
||||
def modulus(self):
|
||||
@abc.abstractmethod
|
||||
def generate_private_key(self):
|
||||
"""
|
||||
The prime modulus that's used in generating the DSA keypair and used
|
||||
in the DSA signing and verification processes.
|
||||
Generates and returns a DSAPrivateKey.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def subgroup_order(self):
|
||||
"""
|
||||
The subgroup order that's used in generating the DSA keypair
|
||||
by the generator and used in the DSA signing and verification
|
||||
processes.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def generator(self):
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DSAParametersWithNumbers(DSAParameters):
|
||||
@abc.abstractmethod
|
||||
def parameter_numbers(self):
|
||||
"""
|
||||
The generator that is used in generating the DSA keypair and used
|
||||
in the DSA signing and verification processes.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def p(self):
|
||||
"""
|
||||
The prime modulus that's used in generating the DSA keypair and used
|
||||
in the DSA signing and verification processes. Alias for modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def q(self):
|
||||
"""
|
||||
The subgroup order that's used in generating the DSA keypair
|
||||
by the generator and used in the DSA signing and verification
|
||||
processes. Alias for subgroup_order.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def g(self):
|
||||
"""
|
||||
The generator that is used in generating the DSA keypair and used
|
||||
in the DSA signing and verification processes. Alias for generator.
|
||||
Returns a DSAParameterNumbers.
|
||||
"""
|
||||
|
||||
|
||||
|
|
@ -374,18 +281,6 @@ class DSAPrivateKey(object):
|
|||
The DSAPublicKey associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def x(self):
|
||||
"""
|
||||
The private key "x" in the DSA structure.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def y(self):
|
||||
"""
|
||||
The public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self):
|
||||
"""
|
||||
|
|
@ -393,6 +288,15 @@ class DSAPrivateKey(object):
|
|||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DSAPrivateKeyWithNumbers(DSAPrivateKey):
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self):
|
||||
"""
|
||||
Returns a DSAPrivateNumbers.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DSAPublicKey(object):
|
||||
@abc.abstractproperty
|
||||
|
|
@ -401,12 +305,6 @@ class DSAPublicKey(object):
|
|||
The bit length of the prime modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def y(self):
|
||||
"""
|
||||
The public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self):
|
||||
"""
|
||||
|
|
@ -414,6 +312,15 @@ class DSAPublicKey(object):
|
|||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DSAPublicKeyWithNumbers(DSAPublicKey):
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self):
|
||||
"""
|
||||
Returns a DSAPublicNumbers.
|
||||
"""
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class AsymmetricSignatureContext(object):
|
||||
@abc.abstractmethod
|
||||
|
|
@ -489,3 +396,63 @@ class CMACContext(object):
|
|||
"""
|
||||
Return a CMACContext that is a copy of the current context.
|
||||
"""
|
||||
|
||||
|
||||
@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 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 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.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -28,12 +28,53 @@ class HKDF(object):
|
|||
def __init__(self, algorithm, length, salt, info, backend):
|
||||
if not isinstance(backend, HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HMACBackend",
|
||||
"Backend object does not implement HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
self._algorithm = algorithm
|
||||
|
||||
if not isinstance(salt, bytes) and salt is not None:
|
||||
raise TypeError("salt must be bytes.")
|
||||
|
||||
if salt is None:
|
||||
salt = b"\x00" * (self._algorithm.digest_size // 8)
|
||||
|
||||
self._salt = salt
|
||||
|
||||
self._backend = backend
|
||||
|
||||
self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend)
|
||||
|
||||
def _extract(self, key_material):
|
||||
h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend)
|
||||
h.update(key_material)
|
||||
return h.finalize()
|
||||
|
||||
def derive(self, key_material):
|
||||
if not isinstance(key_material, bytes):
|
||||
raise TypeError("key_material must be bytes.")
|
||||
|
||||
return self._hkdf_expand.derive(self._extract(key_material))
|
||||
|
||||
def verify(self, key_material, expected_key):
|
||||
if not constant_time.bytes_eq(self.derive(key_material), expected_key):
|
||||
raise InvalidKey
|
||||
|
||||
|
||||
@utils.register_interface(interfaces.KeyDerivationFunction)
|
||||
class HKDFExpand(object):
|
||||
def __init__(self, algorithm, length, info, backend):
|
||||
if not isinstance(backend, HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
self._algorithm = algorithm
|
||||
|
||||
self._backend = backend
|
||||
|
||||
max_length = 255 * (algorithm.digest_size // 8)
|
||||
|
||||
if length > max_length:
|
||||
|
|
@ -44,32 +85,16 @@ class HKDF(object):
|
|||
|
||||
self._length = length
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
raise TypeError(
|
||||
"Unicode-objects must be encoded before using them as a salt.")
|
||||
|
||||
if salt is None:
|
||||
salt = b"\x00" * (self._algorithm.digest_size // 8)
|
||||
|
||||
self._salt = salt
|
||||
|
||||
if isinstance(info, six.text_type):
|
||||
raise TypeError(
|
||||
"Unicode-objects must be encoded before using them as info.")
|
||||
if not isinstance(info, bytes) and info is not None:
|
||||
raise TypeError("info must be bytes.")
|
||||
|
||||
if info is None:
|
||||
info = b""
|
||||
|
||||
self._info = info
|
||||
self._backend = backend
|
||||
|
||||
self._used = False
|
||||
|
||||
def _extract(self, key_material):
|
||||
h = hmac.HMAC(self._salt, self._algorithm, backend=self._backend)
|
||||
h.update(key_material)
|
||||
return h.finalize()
|
||||
|
||||
def _expand(self, key_material):
|
||||
output = [b""]
|
||||
counter = 1
|
||||
|
|
@ -85,17 +110,14 @@ class HKDF(object):
|
|||
return b"".join(output)[:self._length]
|
||||
|
||||
def derive(self, key_material):
|
||||
if isinstance(key_material, six.text_type):
|
||||
raise TypeError(
|
||||
"Unicode-objects must be encoded before using them as key "
|
||||
"material."
|
||||
)
|
||||
if not isinstance(key_material, bytes):
|
||||
raise TypeError("key_material must be bytes.")
|
||||
|
||||
if self._used:
|
||||
raise AlreadyFinalized
|
||||
|
||||
self._used = True
|
||||
return self._expand(self._extract(key_material))
|
||||
return self._expand(key_material)
|
||||
|
||||
def verify(self, key_material, expected_key):
|
||||
if not constant_time.bytes_eq(self.derive(key_material), expected_key):
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import six
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import (
|
||||
AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
|
||||
|
|
@ -28,38 +26,32 @@ class PBKDF2HMAC(object):
|
|||
def __init__(self, algorithm, length, salt, iterations, backend):
|
||||
if not isinstance(backend, PBKDF2HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement PBKDF2HMACBackend",
|
||||
"Backend object does not implement PBKDF2HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
if not backend.pbkdf2_hmac_supported(algorithm):
|
||||
raise UnsupportedAlgorithm(
|
||||
"{0} is not supported for PBKDF2 by this backend".format(
|
||||
"{0} is not supported for PBKDF2 by this backend.".format(
|
||||
algorithm.name),
|
||||
_Reasons.UNSUPPORTED_HASH
|
||||
)
|
||||
self._used = False
|
||||
self._algorithm = algorithm
|
||||
self._length = length
|
||||
if isinstance(salt, six.text_type):
|
||||
raise TypeError(
|
||||
"Unicode-objects must be encoded before using them as key "
|
||||
"material."
|
||||
)
|
||||
if not isinstance(salt, bytes):
|
||||
raise TypeError("salt must be bytes.")
|
||||
self._salt = salt
|
||||
self._iterations = iterations
|
||||
self._backend = backend
|
||||
|
||||
def derive(self, key_material):
|
||||
if self._used:
|
||||
raise AlreadyFinalized("PBKDF2 instances can only be used once")
|
||||
raise AlreadyFinalized("PBKDF2 instances can only be used once.")
|
||||
self._used = True
|
||||
|
||||
if isinstance(key_material, six.text_type):
|
||||
raise TypeError(
|
||||
"Unicode-objects must be encoded before using them as key "
|
||||
"material."
|
||||
)
|
||||
if not isinstance(key_material, bytes):
|
||||
raise TypeError("key_material must be bytes.")
|
||||
return self._backend.derive_pbkdf2_hmac(
|
||||
self._algorithm,
|
||||
self._length,
|
||||
|
|
|
|||
|
|
@ -79,10 +79,10 @@ _lib = _ffi.verify(
|
|||
class PKCS7(object):
|
||||
def __init__(self, block_size):
|
||||
if not (0 <= block_size < 256):
|
||||
raise ValueError("block_size must be in range(0, 256)")
|
||||
raise ValueError("block_size must be in range(0, 256).")
|
||||
|
||||
if block_size % 8 != 0:
|
||||
raise ValueError("block_size must be a multiple of 8")
|
||||
raise ValueError("block_size must be a multiple of 8.")
|
||||
|
||||
self.block_size = block_size
|
||||
|
||||
|
|
@ -102,10 +102,10 @@ class _PKCS7PaddingContext(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._buffer is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
|
||||
if isinstance(data, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before padding")
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("data must be bytes.")
|
||||
|
||||
self._buffer += data
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ class _PKCS7PaddingContext(object):
|
|||
|
||||
def finalize(self):
|
||||
if self._buffer is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
|
||||
pad_size = self.block_size // 8 - len(self._buffer)
|
||||
result = self._buffer + six.int2byte(pad_size) * pad_size
|
||||
|
|
@ -135,10 +135,10 @@ class _PKCS7UnpaddingContext(object):
|
|||
|
||||
def update(self, data):
|
||||
if self._buffer is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
|
||||
if isinstance(data, six.text_type):
|
||||
raise TypeError("Unicode-objects must be encoded before unpadding")
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("data must be bytes.")
|
||||
|
||||
self._buffer += data
|
||||
|
||||
|
|
@ -154,17 +154,17 @@ class _PKCS7UnpaddingContext(object):
|
|||
|
||||
def finalize(self):
|
||||
if self._buffer is None:
|
||||
raise AlreadyFinalized("Context was already finalized")
|
||||
raise AlreadyFinalized("Context was already finalized.")
|
||||
|
||||
if len(self._buffer) != self.block_size // 8:
|
||||
raise ValueError("Invalid padding bytes")
|
||||
raise ValueError("Invalid padding bytes.")
|
||||
|
||||
valid = _lib.Cryptography_check_pkcs7_padding(
|
||||
self._buffer, self.block_size // 8
|
||||
)
|
||||
|
||||
if not valid:
|
||||
raise ValueError("Invalid padding bytes")
|
||||
raise ValueError("Invalid padding bytes.")
|
||||
|
||||
pad_size = six.indexbytes(self._buffer, -1)
|
||||
res = self._buffer[:-pad_size]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
|
||||
def load_pem_traditional_openssl_private_key(data, password, backend):
|
||||
return backend.load_traditional_openssl_pem_private_key(
|
||||
data, password
|
||||
)
|
||||
|
||||
|
||||
def load_pem_pkcs8_private_key(data, password, backend):
|
||||
return backend.load_pkcs8_pem_private_key(
|
||||
data, password
|
||||
)
|
||||
|
|
@ -29,7 +29,7 @@ class HOTP(object):
|
|||
def __init__(self, key, length, algorithm, backend):
|
||||
if not isinstance(backend, HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HMACBackend",
|
||||
"Backend object does not implement HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -37,13 +37,13 @@ class HOTP(object):
|
|||
raise ValueError("Key length has to be at least 128 bits.")
|
||||
|
||||
if not isinstance(length, six.integer_types):
|
||||
raise TypeError("Length parameter must be an integer type")
|
||||
raise TypeError("Length parameter must be an integer type.")
|
||||
|
||||
if length < 6 or length > 8:
|
||||
raise ValueError("Length of HOTP has to be between 6 to 8.")
|
||||
|
||||
if not isinstance(algorithm, (SHA1, SHA256, SHA512)):
|
||||
raise TypeError("Algorithm must be SHA1, SHA256 or SHA512")
|
||||
raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.")
|
||||
|
||||
self._key = key
|
||||
self._length = length
|
||||
|
|
@ -57,15 +57,13 @@ class HOTP(object):
|
|||
|
||||
def verify(self, hotp, counter):
|
||||
if not constant_time.bytes_eq(self.generate(counter), hotp):
|
||||
raise InvalidToken("Supplied HOTP value does not match")
|
||||
raise InvalidToken("Supplied HOTP value does not match.")
|
||||
|
||||
def _dynamic_truncate(self, counter):
|
||||
ctx = hmac.HMAC(self._key, self._algorithm, self._backend)
|
||||
ctx.update(struct.pack(">Q", counter))
|
||||
hmac_value = ctx.finalize()
|
||||
|
||||
offset_bits = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111
|
||||
|
||||
offset = int(offset_bits)
|
||||
offset = six.indexbytes(hmac_value, len(hmac_value) - 1) & 0b1111
|
||||
p = hmac_value[offset:offset + 4]
|
||||
return struct.unpack(">I", p)[0] & 0x7fffffff
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class TOTP(object):
|
|||
def __init__(self, key, length, algorithm, time_step, backend):
|
||||
if not isinstance(backend, HMACBackend):
|
||||
raise UnsupportedAlgorithm(
|
||||
"Backend object does not implement HMACBackend",
|
||||
"Backend object does not implement HMACBackend.",
|
||||
_Reasons.BACKEND_MISSING_INTERFACE
|
||||
)
|
||||
|
||||
|
|
@ -38,4 +38,4 @@ class TOTP(object):
|
|||
|
||||
def verify(self, totp, time):
|
||||
if not constant_time.bytes_eq(self.generate(time), totp):
|
||||
raise InvalidToken("Supplied TOTP value does not match")
|
||||
raise InvalidToken("Supplied TOTP value does not match.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue