mirror of
https://gitlab.sectorq.eu/jaydee/omv_backup.git
synced 2025-07-04 00:45:50 +02:00
added v3
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
# 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.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,135 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization
|
||||
|
||||
generate_parameters = rust_openssl.dh.generate_parameters
|
||||
|
||||
|
||||
DHPrivateNumbers = rust_openssl.dh.DHPrivateNumbers
|
||||
DHPublicNumbers = rust_openssl.dh.DHPublicNumbers
|
||||
DHParameterNumbers = rust_openssl.dh.DHParameterNumbers
|
||||
|
||||
|
||||
class DHParameters(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def generate_private_key(self) -> DHPrivateKey:
|
||||
"""
|
||||
Generates and returns a DHPrivateKey.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameter_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.ParameterFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the parameters serialized as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameter_numbers(self) -> DHParameterNumbers:
|
||||
"""
|
||||
Returns a DHParameterNumbers.
|
||||
"""
|
||||
|
||||
|
||||
DHParametersWithSerialization = DHParameters
|
||||
DHParameters.register(rust_openssl.dh.DHParameters)
|
||||
|
||||
|
||||
class DHPublicKey(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the prime modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self) -> DHParameters:
|
||||
"""
|
||||
The DHParameters object associated with this public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self) -> DHPublicNumbers:
|
||||
"""
|
||||
Returns a DHPublicNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
DHPublicKeyWithSerialization = DHPublicKey
|
||||
DHPublicKey.register(rust_openssl.dh.DHPublicKey)
|
||||
|
||||
|
||||
class DHPrivateKey(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the prime modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> DHPublicKey:
|
||||
"""
|
||||
The DHPublicKey associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self) -> DHParameters:
|
||||
"""
|
||||
The DHParameters object associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def exchange(self, peer_public_key: DHPublicKey) -> bytes:
|
||||
"""
|
||||
Given peer's DHPublicKey, carry out the key exchange and
|
||||
return shared key as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self) -> DHPrivateNumbers:
|
||||
"""
|
||||
Returns a DHPrivateNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
|
||||
DHPrivateKeyWithSerialization = DHPrivateKey
|
||||
DHPrivateKey.register(rust_openssl.dh.DHPrivateKey)
|
@ -0,0 +1,154 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
import typing
|
||||
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization, hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import utils as asym_utils
|
||||
|
||||
|
||||
class DSAParameters(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def generate_private_key(self) -> DSAPrivateKey:
|
||||
"""
|
||||
Generates and returns a DSAPrivateKey.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameter_numbers(self) -> DSAParameterNumbers:
|
||||
"""
|
||||
Returns a DSAParameterNumbers.
|
||||
"""
|
||||
|
||||
|
||||
DSAParametersWithNumbers = DSAParameters
|
||||
DSAParameters.register(rust_openssl.dsa.DSAParameters)
|
||||
|
||||
|
||||
class DSAPrivateKey(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the prime modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> DSAPublicKey:
|
||||
"""
|
||||
The DSAPublicKey associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self) -> DSAParameters:
|
||||
"""
|
||||
The DSAParameters object associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign(
|
||||
self,
|
||||
data: bytes,
|
||||
algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
|
||||
) -> bytes:
|
||||
"""
|
||||
Signs the data
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self) -> DSAPrivateNumbers:
|
||||
"""
|
||||
Returns a DSAPrivateNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
|
||||
DSAPrivateKeyWithSerialization = DSAPrivateKey
|
||||
DSAPrivateKey.register(rust_openssl.dsa.DSAPrivateKey)
|
||||
|
||||
|
||||
class DSAPublicKey(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the prime modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def parameters(self) -> DSAParameters:
|
||||
"""
|
||||
The DSAParameters object associated with this public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self) -> DSAPublicNumbers:
|
||||
"""
|
||||
Returns a DSAPublicNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify(
|
||||
self,
|
||||
signature: bytes,
|
||||
data: bytes,
|
||||
algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
|
||||
) -> None:
|
||||
"""
|
||||
Verifies the signature of the data.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
DSAPublicKeyWithSerialization = DSAPublicKey
|
||||
DSAPublicKey.register(rust_openssl.dsa.DSAPublicKey)
|
||||
|
||||
DSAPrivateNumbers = rust_openssl.dsa.DSAPrivateNumbers
|
||||
DSAPublicNumbers = rust_openssl.dsa.DSAPublicNumbers
|
||||
DSAParameterNumbers = rust_openssl.dsa.DSAParameterNumbers
|
||||
|
||||
|
||||
def generate_parameters(
|
||||
key_size: int, backend: typing.Any = None
|
||||
) -> DSAParameters:
|
||||
if key_size not in (1024, 2048, 3072, 4096):
|
||||
raise ValueError("Key size must be 1024, 2048, 3072, or 4096 bits.")
|
||||
|
||||
return rust_openssl.dsa.generate_parameters(key_size)
|
||||
|
||||
|
||||
def generate_private_key(
|
||||
key_size: int, backend: typing.Any = None
|
||||
) -> DSAPrivateKey:
|
||||
parameters = generate_parameters(key_size)
|
||||
return parameters.generate_private_key()
|
@ -0,0 +1,403 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
import typing
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat._oid import ObjectIdentifier
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization, hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import utils as asym_utils
|
||||
|
||||
|
||||
class EllipticCurveOID:
|
||||
SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1")
|
||||
SECP224R1 = ObjectIdentifier("1.3.132.0.33")
|
||||
SECP256K1 = ObjectIdentifier("1.3.132.0.10")
|
||||
SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7")
|
||||
SECP384R1 = ObjectIdentifier("1.3.132.0.34")
|
||||
SECP521R1 = ObjectIdentifier("1.3.132.0.35")
|
||||
BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7")
|
||||
BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11")
|
||||
BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13")
|
||||
SECT163K1 = ObjectIdentifier("1.3.132.0.1")
|
||||
SECT163R2 = ObjectIdentifier("1.3.132.0.15")
|
||||
SECT233K1 = ObjectIdentifier("1.3.132.0.26")
|
||||
SECT233R1 = ObjectIdentifier("1.3.132.0.27")
|
||||
SECT283K1 = ObjectIdentifier("1.3.132.0.16")
|
||||
SECT283R1 = ObjectIdentifier("1.3.132.0.17")
|
||||
SECT409K1 = ObjectIdentifier("1.3.132.0.36")
|
||||
SECT409R1 = ObjectIdentifier("1.3.132.0.37")
|
||||
SECT571K1 = ObjectIdentifier("1.3.132.0.38")
|
||||
SECT571R1 = ObjectIdentifier("1.3.132.0.39")
|
||||
|
||||
|
||||
class EllipticCurve(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def name(self) -> str:
|
||||
"""
|
||||
The name of the curve. e.g. secp256r1.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
Bit size of a secret scalar for the curve.
|
||||
"""
|
||||
|
||||
|
||||
class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def algorithm(
|
||||
self,
|
||||
) -> asym_utils.Prehashed | hashes.HashAlgorithm:
|
||||
"""
|
||||
The digest algorithm used with this signature.
|
||||
"""
|
||||
|
||||
|
||||
class EllipticCurvePrivateKey(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def exchange(
|
||||
self, algorithm: ECDH, peer_public_key: EllipticCurvePublicKey
|
||||
) -> bytes:
|
||||
"""
|
||||
Performs a key exchange operation using the provided algorithm with the
|
||||
provided peer's public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> EllipticCurvePublicKey:
|
||||
"""
|
||||
The EllipticCurvePublicKey for this private key.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def curve(self) -> EllipticCurve:
|
||||
"""
|
||||
The EllipticCurve that this key is on.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
Bit size of a secret scalar for the curve.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign(
|
||||
self,
|
||||
data: bytes,
|
||||
signature_algorithm: EllipticCurveSignatureAlgorithm,
|
||||
) -> bytes:
|
||||
"""
|
||||
Signs the data
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self) -> EllipticCurvePrivateNumbers:
|
||||
"""
|
||||
Returns an EllipticCurvePrivateNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
|
||||
EllipticCurvePrivateKeyWithSerialization = EllipticCurvePrivateKey
|
||||
EllipticCurvePrivateKey.register(rust_openssl.ec.ECPrivateKey)
|
||||
|
||||
|
||||
class EllipticCurvePublicKey(metaclass=abc.ABCMeta):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def curve(self) -> EllipticCurve:
|
||||
"""
|
||||
The EllipticCurve that this key is on.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
Bit size of a secret scalar for the curve.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self) -> EllipticCurvePublicNumbers:
|
||||
"""
|
||||
Returns an EllipticCurvePublicNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify(
|
||||
self,
|
||||
signature: bytes,
|
||||
data: bytes,
|
||||
signature_algorithm: EllipticCurveSignatureAlgorithm,
|
||||
) -> None:
|
||||
"""
|
||||
Verifies the signature of the data.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_encoded_point(
|
||||
cls, curve: EllipticCurve, data: bytes
|
||||
) -> EllipticCurvePublicKey:
|
||||
utils._check_bytes("data", data)
|
||||
|
||||
if len(data) == 0:
|
||||
raise ValueError("data must not be an empty byte string")
|
||||
|
||||
if data[0] not in [0x02, 0x03, 0x04]:
|
||||
raise ValueError("Unsupported elliptic curve point type")
|
||||
|
||||
return rust_openssl.ec.from_public_bytes(curve, data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey
|
||||
EllipticCurvePublicKey.register(rust_openssl.ec.ECPublicKey)
|
||||
|
||||
EllipticCurvePrivateNumbers = rust_openssl.ec.EllipticCurvePrivateNumbers
|
||||
EllipticCurvePublicNumbers = rust_openssl.ec.EllipticCurvePublicNumbers
|
||||
|
||||
|
||||
class SECT571R1(EllipticCurve):
|
||||
name = "sect571r1"
|
||||
key_size = 570
|
||||
|
||||
|
||||
class SECT409R1(EllipticCurve):
|
||||
name = "sect409r1"
|
||||
key_size = 409
|
||||
|
||||
|
||||
class SECT283R1(EllipticCurve):
|
||||
name = "sect283r1"
|
||||
key_size = 283
|
||||
|
||||
|
||||
class SECT233R1(EllipticCurve):
|
||||
name = "sect233r1"
|
||||
key_size = 233
|
||||
|
||||
|
||||
class SECT163R2(EllipticCurve):
|
||||
name = "sect163r2"
|
||||
key_size = 163
|
||||
|
||||
|
||||
class SECT571K1(EllipticCurve):
|
||||
name = "sect571k1"
|
||||
key_size = 571
|
||||
|
||||
|
||||
class SECT409K1(EllipticCurve):
|
||||
name = "sect409k1"
|
||||
key_size = 409
|
||||
|
||||
|
||||
class SECT283K1(EllipticCurve):
|
||||
name = "sect283k1"
|
||||
key_size = 283
|
||||
|
||||
|
||||
class SECT233K1(EllipticCurve):
|
||||
name = "sect233k1"
|
||||
key_size = 233
|
||||
|
||||
|
||||
class SECT163K1(EllipticCurve):
|
||||
name = "sect163k1"
|
||||
key_size = 163
|
||||
|
||||
|
||||
class SECP521R1(EllipticCurve):
|
||||
name = "secp521r1"
|
||||
key_size = 521
|
||||
|
||||
|
||||
class SECP384R1(EllipticCurve):
|
||||
name = "secp384r1"
|
||||
key_size = 384
|
||||
|
||||
|
||||
class SECP256R1(EllipticCurve):
|
||||
name = "secp256r1"
|
||||
key_size = 256
|
||||
|
||||
|
||||
class SECP256K1(EllipticCurve):
|
||||
name = "secp256k1"
|
||||
key_size = 256
|
||||
|
||||
|
||||
class SECP224R1(EllipticCurve):
|
||||
name = "secp224r1"
|
||||
key_size = 224
|
||||
|
||||
|
||||
class SECP192R1(EllipticCurve):
|
||||
name = "secp192r1"
|
||||
key_size = 192
|
||||
|
||||
|
||||
class BrainpoolP256R1(EllipticCurve):
|
||||
name = "brainpoolP256r1"
|
||||
key_size = 256
|
||||
|
||||
|
||||
class BrainpoolP384R1(EllipticCurve):
|
||||
name = "brainpoolP384r1"
|
||||
key_size = 384
|
||||
|
||||
|
||||
class BrainpoolP512R1(EllipticCurve):
|
||||
name = "brainpoolP512r1"
|
||||
key_size = 512
|
||||
|
||||
|
||||
_CURVE_TYPES: dict[str, EllipticCurve] = {
|
||||
"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(),
|
||||
"brainpoolP256r1": BrainpoolP256R1(),
|
||||
"brainpoolP384r1": BrainpoolP384R1(),
|
||||
"brainpoolP512r1": BrainpoolP512R1(),
|
||||
}
|
||||
|
||||
|
||||
class ECDSA(EllipticCurveSignatureAlgorithm):
|
||||
def __init__(
|
||||
self,
|
||||
algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
|
||||
deterministic_signing: bool = False,
|
||||
):
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if (
|
||||
deterministic_signing
|
||||
and not backend.ecdsa_deterministic_supported()
|
||||
):
|
||||
raise UnsupportedAlgorithm(
|
||||
"ECDSA with deterministic signature (RFC 6979) is not "
|
||||
"supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
self._algorithm = algorithm
|
||||
self._deterministic_signing = deterministic_signing
|
||||
|
||||
@property
|
||||
def algorithm(
|
||||
self,
|
||||
) -> asym_utils.Prehashed | hashes.HashAlgorithm:
|
||||
return self._algorithm
|
||||
|
||||
@property
|
||||
def deterministic_signing(
|
||||
self,
|
||||
) -> bool:
|
||||
return self._deterministic_signing
|
||||
|
||||
|
||||
generate_private_key = rust_openssl.ec.generate_private_key
|
||||
|
||||
|
||||
def derive_private_key(
|
||||
private_value: int,
|
||||
curve: EllipticCurve,
|
||||
backend: typing.Any = None,
|
||||
) -> EllipticCurvePrivateKey:
|
||||
if not isinstance(private_value, int):
|
||||
raise TypeError("private_value must be an integer type.")
|
||||
|
||||
if private_value <= 0:
|
||||
raise ValueError("private_value must be a positive integer.")
|
||||
|
||||
return rust_openssl.ec.derive_private_key(private_value, curve)
|
||||
|
||||
|
||||
class ECDH:
|
||||
pass
|
||||
|
||||
|
||||
_OID_TO_CURVE = {
|
||||
EllipticCurveOID.SECP192R1: SECP192R1,
|
||||
EllipticCurveOID.SECP224R1: SECP224R1,
|
||||
EllipticCurveOID.SECP256K1: SECP256K1,
|
||||
EllipticCurveOID.SECP256R1: SECP256R1,
|
||||
EllipticCurveOID.SECP384R1: SECP384R1,
|
||||
EllipticCurveOID.SECP521R1: SECP521R1,
|
||||
EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1,
|
||||
EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1,
|
||||
EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1,
|
||||
EllipticCurveOID.SECT163K1: SECT163K1,
|
||||
EllipticCurveOID.SECT163R2: SECT163R2,
|
||||
EllipticCurveOID.SECT233K1: SECT233K1,
|
||||
EllipticCurveOID.SECT233R1: SECT233R1,
|
||||
EllipticCurveOID.SECT283K1: SECT283K1,
|
||||
EllipticCurveOID.SECT283R1: SECT283R1,
|
||||
EllipticCurveOID.SECT409K1: SECT409K1,
|
||||
EllipticCurveOID.SECT409R1: SECT409R1,
|
||||
EllipticCurveOID.SECT571K1: SECT571K1,
|
||||
EllipticCurveOID.SECT571R1: SECT571R1,
|
||||
}
|
||||
|
||||
|
||||
def get_curve_for_oid(oid: ObjectIdentifier) -> type[EllipticCurve]:
|
||||
try:
|
||||
return _OID_TO_CURVE[oid]
|
||||
except KeyError:
|
||||
raise LookupError(
|
||||
"The provided object identifier has no matching elliptic "
|
||||
"curve class"
|
||||
)
|
@ -0,0 +1,116 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization
|
||||
|
||||
|
||||
class Ed25519PublicKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def from_public_bytes(cls, data: bytes) -> Ed25519PublicKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed25519.from_public_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the public key.
|
||||
Equivalent to public_bytes(Raw, Raw).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify(self, signature: bytes, data: bytes) -> None:
|
||||
"""
|
||||
Verify the signature.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
Ed25519PublicKey.register(rust_openssl.ed25519.Ed25519PublicKey)
|
||||
|
||||
|
||||
class Ed25519PrivateKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def generate(cls) -> Ed25519PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed25519.generate_key()
|
||||
|
||||
@classmethod
|
||||
def from_private_bytes(cls, data: bytes) -> Ed25519PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed25519.from_private_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> Ed25519PublicKey:
|
||||
"""
|
||||
The Ed25519PublicKey derived from the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the private key.
|
||||
Equivalent to private_bytes(Raw, Raw, NoEncryption()).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign(self, data: bytes) -> bytes:
|
||||
"""
|
||||
Signs the data.
|
||||
"""
|
||||
|
||||
|
||||
Ed25519PrivateKey.register(rust_openssl.ed25519.Ed25519PrivateKey)
|
@ -0,0 +1,118 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization
|
||||
|
||||
|
||||
class Ed448PublicKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def from_public_bytes(cls, data: bytes) -> Ed448PublicKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed448.from_public_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the public key.
|
||||
Equivalent to public_bytes(Raw, Raw).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify(self, signature: bytes, data: bytes) -> None:
|
||||
"""
|
||||
Verify the signature.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
if hasattr(rust_openssl, "ed448"):
|
||||
Ed448PublicKey.register(rust_openssl.ed448.Ed448PublicKey)
|
||||
|
||||
|
||||
class Ed448PrivateKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def generate(cls) -> Ed448PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed448.generate_key()
|
||||
|
||||
@classmethod
|
||||
def from_private_bytes(cls, data: bytes) -> Ed448PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.ed448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"ed448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.ed448.from_private_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> Ed448PublicKey:
|
||||
"""
|
||||
The Ed448PublicKey derived from the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign(self, data: bytes) -> bytes:
|
||||
"""
|
||||
Signs the data.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the private key.
|
||||
Equivalent to private_bytes(Raw, Raw, NoEncryption()).
|
||||
"""
|
||||
|
||||
|
||||
if hasattr(rust_openssl, "x448"):
|
||||
Ed448PrivateKey.register(rust_openssl.ed448.Ed448PrivateKey)
|
@ -0,0 +1,113 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives._asymmetric import (
|
||||
AsymmetricPadding as AsymmetricPadding,
|
||||
)
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
|
||||
|
||||
class PKCS1v15(AsymmetricPadding):
|
||||
name = "EMSA-PKCS1-v1_5"
|
||||
|
||||
|
||||
class _MaxLength:
|
||||
"Sentinel value for `MAX_LENGTH`."
|
||||
|
||||
|
||||
class _Auto:
|
||||
"Sentinel value for `AUTO`."
|
||||
|
||||
|
||||
class _DigestLength:
|
||||
"Sentinel value for `DIGEST_LENGTH`."
|
||||
|
||||
|
||||
class PSS(AsymmetricPadding):
|
||||
MAX_LENGTH = _MaxLength()
|
||||
AUTO = _Auto()
|
||||
DIGEST_LENGTH = _DigestLength()
|
||||
name = "EMSA-PSS"
|
||||
_salt_length: int | _MaxLength | _Auto | _DigestLength
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mgf: MGF,
|
||||
salt_length: int | _MaxLength | _Auto | _DigestLength,
|
||||
) -> None:
|
||||
self._mgf = mgf
|
||||
|
||||
if not isinstance(
|
||||
salt_length, (int, _MaxLength, _Auto, _DigestLength)
|
||||
):
|
||||
raise TypeError(
|
||||
"salt_length must be an integer, MAX_LENGTH, "
|
||||
"DIGEST_LENGTH, or AUTO"
|
||||
)
|
||||
|
||||
if isinstance(salt_length, int) and salt_length < 0:
|
||||
raise ValueError("salt_length must be zero or greater.")
|
||||
|
||||
self._salt_length = salt_length
|
||||
|
||||
@property
|
||||
def mgf(self) -> MGF:
|
||||
return self._mgf
|
||||
|
||||
|
||||
class OAEP(AsymmetricPadding):
|
||||
name = "EME-OAEP"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
mgf: MGF,
|
||||
algorithm: hashes.HashAlgorithm,
|
||||
label: bytes | None,
|
||||
):
|
||||
if not isinstance(algorithm, hashes.HashAlgorithm):
|
||||
raise TypeError("Expected instance of hashes.HashAlgorithm.")
|
||||
|
||||
self._mgf = mgf
|
||||
self._algorithm = algorithm
|
||||
self._label = label
|
||||
|
||||
@property
|
||||
def algorithm(self) -> hashes.HashAlgorithm:
|
||||
return self._algorithm
|
||||
|
||||
@property
|
||||
def mgf(self) -> MGF:
|
||||
return self._mgf
|
||||
|
||||
|
||||
class MGF(metaclass=abc.ABCMeta):
|
||||
_algorithm: hashes.HashAlgorithm
|
||||
|
||||
|
||||
class MGF1(MGF):
|
||||
MAX_LENGTH = _MaxLength()
|
||||
|
||||
def __init__(self, algorithm: hashes.HashAlgorithm):
|
||||
if not isinstance(algorithm, hashes.HashAlgorithm):
|
||||
raise TypeError("Expected instance of hashes.HashAlgorithm.")
|
||||
|
||||
self._algorithm = algorithm
|
||||
|
||||
|
||||
def calculate_max_pss_salt_length(
|
||||
key: rsa.RSAPrivateKey | rsa.RSAPublicKey,
|
||||
hash_algorithm: hashes.HashAlgorithm,
|
||||
) -> int:
|
||||
if not isinstance(key, (rsa.RSAPrivateKey, rsa.RSAPublicKey)):
|
||||
raise TypeError("key must be an RSA public or private key")
|
||||
# bit length - 1 per RFC 3447
|
||||
emlen = (key.key_size + 6) // 8
|
||||
salt_length = emlen - hash_algorithm.digest_size - 2
|
||||
assert salt_length >= 0
|
||||
return salt_length
|
@ -0,0 +1,263 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
import random
|
||||
import typing
|
||||
from math import gcd
|
||||
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization, hashes
|
||||
from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding
|
||||
from cryptography.hazmat.primitives.asymmetric import utils as asym_utils
|
||||
|
||||
|
||||
class RSAPrivateKey(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes:
|
||||
"""
|
||||
Decrypts the provided ciphertext.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the public modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> RSAPublicKey:
|
||||
"""
|
||||
The RSAPublicKey associated with this private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign(
|
||||
self,
|
||||
data: bytes,
|
||||
padding: AsymmetricPadding,
|
||||
algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
|
||||
) -> bytes:
|
||||
"""
|
||||
Signs the data.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_numbers(self) -> RSAPrivateNumbers:
|
||||
"""
|
||||
Returns an RSAPrivateNumbers.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
|
||||
RSAPrivateKeyWithSerialization = RSAPrivateKey
|
||||
RSAPrivateKey.register(rust_openssl.rsa.RSAPrivateKey)
|
||||
|
||||
|
||||
class RSAPublicKey(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes:
|
||||
"""
|
||||
Encrypts the given plaintext.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def key_size(self) -> int:
|
||||
"""
|
||||
The bit length of the public modulus.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_numbers(self) -> RSAPublicNumbers:
|
||||
"""
|
||||
Returns an RSAPublicNumbers
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
Returns the key serialized as bytes.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def verify(
|
||||
self,
|
||||
signature: bytes,
|
||||
data: bytes,
|
||||
padding: AsymmetricPadding,
|
||||
algorithm: asym_utils.Prehashed | hashes.HashAlgorithm,
|
||||
) -> None:
|
||||
"""
|
||||
Verifies the signature of the data.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def recover_data_from_signature(
|
||||
self,
|
||||
signature: bytes,
|
||||
padding: AsymmetricPadding,
|
||||
algorithm: hashes.HashAlgorithm | None,
|
||||
) -> bytes:
|
||||
"""
|
||||
Recovers the original data from the signature.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
RSAPublicKeyWithSerialization = RSAPublicKey
|
||||
RSAPublicKey.register(rust_openssl.rsa.RSAPublicKey)
|
||||
|
||||
RSAPrivateNumbers = rust_openssl.rsa.RSAPrivateNumbers
|
||||
RSAPublicNumbers = rust_openssl.rsa.RSAPublicNumbers
|
||||
|
||||
|
||||
def generate_private_key(
|
||||
public_exponent: int,
|
||||
key_size: int,
|
||||
backend: typing.Any = None,
|
||||
) -> RSAPrivateKey:
|
||||
_verify_rsa_parameters(public_exponent, key_size)
|
||||
return rust_openssl.rsa.generate_private_key(public_exponent, key_size)
|
||||
|
||||
|
||||
def _verify_rsa_parameters(public_exponent: int, key_size: int) -> None:
|
||||
if public_exponent not in (3, 65537):
|
||||
raise ValueError(
|
||||
"public_exponent must be either 3 (for legacy compatibility) or "
|
||||
"65537. Almost everyone should choose 65537 here!"
|
||||
)
|
||||
|
||||
if key_size < 1024:
|
||||
raise ValueError("key_size must be at least 1024-bits.")
|
||||
|
||||
|
||||
def _modinv(e: int, m: int) -> int:
|
||||
"""
|
||||
Modular Multiplicative Inverse. Returns x such that: (x*e) mod m == 1
|
||||
"""
|
||||
x1, x2 = 1, 0
|
||||
a, b = e, m
|
||||
while b > 0:
|
||||
q, r = divmod(a, b)
|
||||
xn = x1 - q * x2
|
||||
a, b, x1, x2 = b, r, x2, xn
|
||||
return x1 % m
|
||||
|
||||
|
||||
def rsa_crt_iqmp(p: int, q: int) -> int:
|
||||
"""
|
||||
Compute the CRT (q ** -1) % p value from RSA primes p and q.
|
||||
"""
|
||||
return _modinv(q, p)
|
||||
|
||||
|
||||
def rsa_crt_dmp1(private_exponent: int, p: int) -> int:
|
||||
"""
|
||||
Compute the CRT private_exponent % (p - 1) value from the RSA
|
||||
private_exponent (d) and p.
|
||||
"""
|
||||
return private_exponent % (p - 1)
|
||||
|
||||
|
||||
def rsa_crt_dmq1(private_exponent: int, q: int) -> int:
|
||||
"""
|
||||
Compute the CRT private_exponent % (q - 1) value from the RSA
|
||||
private_exponent (d) and q.
|
||||
"""
|
||||
return private_exponent % (q - 1)
|
||||
|
||||
|
||||
def rsa_recover_private_exponent(e: int, p: int, q: int) -> int:
|
||||
"""
|
||||
Compute the RSA private_exponent (d) given the public exponent (e)
|
||||
and the RSA primes p and q.
|
||||
|
||||
This uses the Carmichael totient function to generate the
|
||||
smallest possible working value of the private exponent.
|
||||
"""
|
||||
# This lambda_n is the Carmichael totient function.
|
||||
# The original RSA paper uses the Euler totient function
|
||||
# here: phi_n = (p - 1) * (q - 1)
|
||||
# Either version of the private exponent will work, but the
|
||||
# one generated by the older formulation may be larger
|
||||
# than necessary. (lambda_n always divides phi_n)
|
||||
#
|
||||
# TODO: Replace with lcm(p - 1, q - 1) once the minimum
|
||||
# supported Python version is >= 3.9.
|
||||
lambda_n = (p - 1) * (q - 1) // gcd(p - 1, q - 1)
|
||||
return _modinv(e, lambda_n)
|
||||
|
||||
|
||||
# Controls the number of iterations rsa_recover_prime_factors will perform
|
||||
# to obtain the prime factors.
|
||||
_MAX_RECOVERY_ATTEMPTS = 500
|
||||
|
||||
|
||||
def rsa_recover_prime_factors(n: int, e: int, d: int) -> tuple[int, int]:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
# reject invalid values early
|
||||
if 17 != pow(17, e * d, n):
|
||||
raise ValueError("n, d, e don't match")
|
||||
# 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
|
||||
tries = 0
|
||||
while not spotted and tries < _MAX_RECOVERY_ATTEMPTS:
|
||||
a = random.randint(2, n - 1)
|
||||
tries += 1
|
||||
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
|
||||
if not spotted:
|
||||
raise ValueError("Unable to compute factors p and q from exponent d.")
|
||||
# Found !
|
||||
q, r = divmod(n, p)
|
||||
assert r == 0
|
||||
p, q = sorted((p, q), reverse=True)
|
||||
return (p, q)
|
@ -0,0 +1,111 @@
|
||||
# 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 annotations
|
||||
|
||||
import typing
|
||||
|
||||
from cryptography import utils
|
||||
from cryptography.hazmat.primitives.asymmetric import (
|
||||
dh,
|
||||
dsa,
|
||||
ec,
|
||||
ed448,
|
||||
ed25519,
|
||||
rsa,
|
||||
x448,
|
||||
x25519,
|
||||
)
|
||||
|
||||
# Every asymmetric key type
|
||||
PublicKeyTypes = typing.Union[
|
||||
dh.DHPublicKey,
|
||||
dsa.DSAPublicKey,
|
||||
rsa.RSAPublicKey,
|
||||
ec.EllipticCurvePublicKey,
|
||||
ed25519.Ed25519PublicKey,
|
||||
ed448.Ed448PublicKey,
|
||||
x25519.X25519PublicKey,
|
||||
x448.X448PublicKey,
|
||||
]
|
||||
PUBLIC_KEY_TYPES = PublicKeyTypes
|
||||
utils.deprecated(
|
||||
PUBLIC_KEY_TYPES,
|
||||
__name__,
|
||||
"Use PublicKeyTypes instead",
|
||||
utils.DeprecatedIn40,
|
||||
name="PUBLIC_KEY_TYPES",
|
||||
)
|
||||
# Every asymmetric key type
|
||||
PrivateKeyTypes = typing.Union[
|
||||
dh.DHPrivateKey,
|
||||
ed25519.Ed25519PrivateKey,
|
||||
ed448.Ed448PrivateKey,
|
||||
rsa.RSAPrivateKey,
|
||||
dsa.DSAPrivateKey,
|
||||
ec.EllipticCurvePrivateKey,
|
||||
x25519.X25519PrivateKey,
|
||||
x448.X448PrivateKey,
|
||||
]
|
||||
PRIVATE_KEY_TYPES = PrivateKeyTypes
|
||||
utils.deprecated(
|
||||
PRIVATE_KEY_TYPES,
|
||||
__name__,
|
||||
"Use PrivateKeyTypes instead",
|
||||
utils.DeprecatedIn40,
|
||||
name="PRIVATE_KEY_TYPES",
|
||||
)
|
||||
# Just the key types we allow to be used for x509 signing. This mirrors
|
||||
# the certificate public key types
|
||||
CertificateIssuerPrivateKeyTypes = typing.Union[
|
||||
ed25519.Ed25519PrivateKey,
|
||||
ed448.Ed448PrivateKey,
|
||||
rsa.RSAPrivateKey,
|
||||
dsa.DSAPrivateKey,
|
||||
ec.EllipticCurvePrivateKey,
|
||||
]
|
||||
CERTIFICATE_PRIVATE_KEY_TYPES = CertificateIssuerPrivateKeyTypes
|
||||
utils.deprecated(
|
||||
CERTIFICATE_PRIVATE_KEY_TYPES,
|
||||
__name__,
|
||||
"Use CertificateIssuerPrivateKeyTypes instead",
|
||||
utils.DeprecatedIn40,
|
||||
name="CERTIFICATE_PRIVATE_KEY_TYPES",
|
||||
)
|
||||
# Just the key types we allow to be used for x509 signing. This mirrors
|
||||
# the certificate private key types
|
||||
CertificateIssuerPublicKeyTypes = typing.Union[
|
||||
dsa.DSAPublicKey,
|
||||
rsa.RSAPublicKey,
|
||||
ec.EllipticCurvePublicKey,
|
||||
ed25519.Ed25519PublicKey,
|
||||
ed448.Ed448PublicKey,
|
||||
]
|
||||
CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES = CertificateIssuerPublicKeyTypes
|
||||
utils.deprecated(
|
||||
CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES,
|
||||
__name__,
|
||||
"Use CertificateIssuerPublicKeyTypes instead",
|
||||
utils.DeprecatedIn40,
|
||||
name="CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES",
|
||||
)
|
||||
# This type removes DHPublicKey. x448/x25519 can be a public key
|
||||
# but cannot be used in signing so they are allowed here.
|
||||
CertificatePublicKeyTypes = typing.Union[
|
||||
dsa.DSAPublicKey,
|
||||
rsa.RSAPublicKey,
|
||||
ec.EllipticCurvePublicKey,
|
||||
ed25519.Ed25519PublicKey,
|
||||
ed448.Ed448PublicKey,
|
||||
x25519.X25519PublicKey,
|
||||
x448.X448PublicKey,
|
||||
]
|
||||
CERTIFICATE_PUBLIC_KEY_TYPES = CertificatePublicKeyTypes
|
||||
utils.deprecated(
|
||||
CERTIFICATE_PUBLIC_KEY_TYPES,
|
||||
__name__,
|
||||
"Use CertificatePublicKeyTypes instead",
|
||||
utils.DeprecatedIn40,
|
||||
name="CERTIFICATE_PUBLIC_KEY_TYPES",
|
||||
)
|
@ -0,0 +1,24 @@
|
||||
# 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 annotations
|
||||
|
||||
from cryptography.hazmat.bindings._rust import asn1
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
|
||||
decode_dss_signature = asn1.decode_dss_signature
|
||||
encode_dss_signature = asn1.encode_dss_signature
|
||||
|
||||
|
||||
class Prehashed:
|
||||
def __init__(self, algorithm: hashes.HashAlgorithm):
|
||||
if not isinstance(algorithm, hashes.HashAlgorithm):
|
||||
raise TypeError("Expected instance of HashAlgorithm.")
|
||||
|
||||
self._algorithm = algorithm
|
||||
self._digest_size = algorithm.digest_size
|
||||
|
||||
@property
|
||||
def digest_size(self) -> int:
|
||||
return self._digest_size
|
@ -0,0 +1,109 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization
|
||||
|
||||
|
||||
class X25519PublicKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def from_public_bytes(cls, data: bytes) -> X25519PublicKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.x25519.from_public_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the public key.
|
||||
Equivalent to public_bytes(Raw, Raw).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
X25519PublicKey.register(rust_openssl.x25519.X25519PublicKey)
|
||||
|
||||
|
||||
class X25519PrivateKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def generate(cls) -> X25519PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
return rust_openssl.x25519.generate_key()
|
||||
|
||||
@classmethod
|
||||
def from_private_bytes(cls, data: bytes) -> X25519PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x25519_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X25519 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.x25519.from_private_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> X25519PublicKey:
|
||||
"""
|
||||
Returns the public key associated with this private key
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the private key.
|
||||
Equivalent to private_bytes(Raw, Raw, NoEncryption()).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def exchange(self, peer_public_key: X25519PublicKey) -> bytes:
|
||||
"""
|
||||
Performs a key exchange operation using the provided peer's public key.
|
||||
"""
|
||||
|
||||
|
||||
X25519PrivateKey.register(rust_openssl.x25519.X25519PrivateKey)
|
@ -0,0 +1,112 @@
|
||||
# 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 annotations
|
||||
|
||||
import abc
|
||||
|
||||
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
|
||||
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
|
||||
from cryptography.hazmat.primitives import _serialization
|
||||
|
||||
|
||||
class X448PublicKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def from_public_bytes(cls, data: bytes) -> X448PublicKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.x448.from_public_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PublicFormat,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the public key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the public key.
|
||||
Equivalent to public_bytes(Raw, Raw).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""
|
||||
Checks equality.
|
||||
"""
|
||||
|
||||
|
||||
if hasattr(rust_openssl, "x448"):
|
||||
X448PublicKey.register(rust_openssl.x448.X448PublicKey)
|
||||
|
||||
|
||||
class X448PrivateKey(metaclass=abc.ABCMeta):
|
||||
@classmethod
|
||||
def generate(cls) -> X448PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.x448.generate_key()
|
||||
|
||||
@classmethod
|
||||
def from_private_bytes(cls, data: bytes) -> X448PrivateKey:
|
||||
from cryptography.hazmat.backends.openssl.backend import backend
|
||||
|
||||
if not backend.x448_supported():
|
||||
raise UnsupportedAlgorithm(
|
||||
"X448 is not supported by this version of OpenSSL.",
|
||||
_Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM,
|
||||
)
|
||||
|
||||
return rust_openssl.x448.from_private_bytes(data)
|
||||
|
||||
@abc.abstractmethod
|
||||
def public_key(self) -> X448PublicKey:
|
||||
"""
|
||||
Returns the public key associated with this private key
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes(
|
||||
self,
|
||||
encoding: _serialization.Encoding,
|
||||
format: _serialization.PrivateFormat,
|
||||
encryption_algorithm: _serialization.KeySerializationEncryption,
|
||||
) -> bytes:
|
||||
"""
|
||||
The serialized bytes of the private key.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def private_bytes_raw(self) -> bytes:
|
||||
"""
|
||||
The raw bytes of the private key.
|
||||
Equivalent to private_bytes(Raw, Raw, NoEncryption()).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def exchange(self, peer_public_key: X448PublicKey) -> bytes:
|
||||
"""
|
||||
Performs a key exchange operation using the provided peer's public key.
|
||||
"""
|
||||
|
||||
|
||||
if hasattr(rust_openssl, "x448"):
|
||||
X448PrivateKey.register(rust_openssl.x448.X448PrivateKey)
|
Reference in New Issue
Block a user