slight update
This commit is contained in:
403
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/DSS.py
vendored
Normal file
403
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/DSS.py
vendored
Normal file
@ -0,0 +1,403 @@
|
||||
#
|
||||
# Signature/DSS.py : DSS.py
|
||||
#
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Crypto.Util.asn1 import DerSequence
|
||||
from Crypto.Util.number import long_to_bytes
|
||||
from Crypto.Math.Numbers import Integer
|
||||
|
||||
from Crypto.Hash import HMAC
|
||||
from Crypto.PublicKey.ECC import EccKey
|
||||
from Crypto.PublicKey.DSA import DsaKey
|
||||
|
||||
__all__ = ['DssSigScheme', 'new']
|
||||
|
||||
|
||||
class DssSigScheme(object):
|
||||
"""A (EC)DSA signature object.
|
||||
Do not instantiate directly.
|
||||
Use :func:`Crypto.Signature.DSS.new`.
|
||||
"""
|
||||
|
||||
def __init__(self, key, encoding, order):
|
||||
"""Create a new Digital Signature Standard (DSS) object.
|
||||
|
||||
Do not instantiate this object directly,
|
||||
use `Crypto.Signature.DSS.new` instead.
|
||||
"""
|
||||
|
||||
self._key = key
|
||||
self._encoding = encoding
|
||||
self._order = order
|
||||
|
||||
self._order_bits = self._order.size_in_bits()
|
||||
self._order_bytes = (self._order_bits - 1) // 8 + 1
|
||||
|
||||
def can_sign(self):
|
||||
"""Return ``True`` if this signature object can be used
|
||||
for signing messages."""
|
||||
|
||||
return self._key.has_private()
|
||||
|
||||
def _compute_nonce(self, msg_hash):
|
||||
raise NotImplementedError("To be provided by subclasses")
|
||||
|
||||
def _valid_hash(self, msg_hash):
|
||||
raise NotImplementedError("To be provided by subclasses")
|
||||
|
||||
def sign(self, msg_hash):
|
||||
"""Compute the DSA/ECDSA signature of a message.
|
||||
|
||||
Args:
|
||||
msg_hash (hash object):
|
||||
The hash that was carried out over the message.
|
||||
The object belongs to the :mod:`Crypto.Hash` package.
|
||||
Under mode ``'fips-186-3'``, the hash must be a FIPS
|
||||
approved secure hash (SHA-2 or SHA-3).
|
||||
|
||||
:return: The signature as ``bytes``
|
||||
:raise ValueError: if the hash algorithm is incompatible to the (EC)DSA key
|
||||
:raise TypeError: if the (EC)DSA key has no private half
|
||||
"""
|
||||
|
||||
if not self._key.has_private():
|
||||
raise TypeError("Private key is needed to sign")
|
||||
|
||||
if not self._valid_hash(msg_hash):
|
||||
raise ValueError("Hash is not sufficiently strong")
|
||||
|
||||
# Generate the nonce k (critical!)
|
||||
nonce = self._compute_nonce(msg_hash)
|
||||
|
||||
# Perform signature using the raw API
|
||||
z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
|
||||
sig_pair = self._key._sign(z, nonce)
|
||||
|
||||
# Encode the signature into a single byte string
|
||||
if self._encoding == 'binary':
|
||||
output = b"".join([long_to_bytes(x, self._order_bytes)
|
||||
for x in sig_pair])
|
||||
else:
|
||||
# Dss-sig ::= SEQUENCE {
|
||||
# r INTEGER,
|
||||
# s INTEGER
|
||||
# }
|
||||
# Ecdsa-Sig-Value ::= SEQUENCE {
|
||||
# r INTEGER,
|
||||
# s INTEGER
|
||||
# }
|
||||
output = DerSequence(sig_pair).encode()
|
||||
|
||||
return output
|
||||
|
||||
def verify(self, msg_hash, signature):
|
||||
"""Check if a certain (EC)DSA signature is authentic.
|
||||
|
||||
Args:
|
||||
msg_hash (hash object):
|
||||
The hash that was carried out over the message.
|
||||
This is an object belonging to the :mod:`Crypto.Hash` module.
|
||||
Under mode ``'fips-186-3'``, the hash must be a FIPS
|
||||
approved secure hash (SHA-2 or SHA-3).
|
||||
|
||||
signature (``bytes``):
|
||||
The signature that needs to be validated.
|
||||
|
||||
:raise ValueError: if the signature is not authentic
|
||||
"""
|
||||
|
||||
if not self._valid_hash(msg_hash):
|
||||
raise ValueError("Hash is not sufficiently strong")
|
||||
|
||||
if self._encoding == 'binary':
|
||||
if len(signature) != (2 * self._order_bytes):
|
||||
raise ValueError("The signature is not authentic (length)")
|
||||
r_prime, s_prime = [Integer.from_bytes(x)
|
||||
for x in (signature[:self._order_bytes],
|
||||
signature[self._order_bytes:])]
|
||||
else:
|
||||
try:
|
||||
der_seq = DerSequence().decode(signature, strict=True)
|
||||
except (ValueError, IndexError):
|
||||
raise ValueError("The signature is not authentic (DER)")
|
||||
if len(der_seq) != 2 or not der_seq.hasOnlyInts():
|
||||
raise ValueError("The signature is not authentic (DER content)")
|
||||
r_prime, s_prime = Integer(der_seq[0]), Integer(der_seq[1])
|
||||
|
||||
if not (0 < r_prime < self._order) or not (0 < s_prime < self._order):
|
||||
raise ValueError("The signature is not authentic (d)")
|
||||
|
||||
z = Integer.from_bytes(msg_hash.digest()[:self._order_bytes])
|
||||
result = self._key._verify(z, (r_prime, s_prime))
|
||||
if not result:
|
||||
raise ValueError("The signature is not authentic")
|
||||
# Make PyCrypto code to fail
|
||||
return False
|
||||
|
||||
|
||||
class DeterministicDsaSigScheme(DssSigScheme):
|
||||
# Also applicable to ECDSA
|
||||
|
||||
def __init__(self, key, encoding, order, private_key):
|
||||
super(DeterministicDsaSigScheme, self).__init__(key, encoding, order)
|
||||
self._private_key = private_key
|
||||
|
||||
def _bits2int(self, bstr):
|
||||
"""See 2.3.2 in RFC6979"""
|
||||
|
||||
result = Integer.from_bytes(bstr)
|
||||
q_len = self._order.size_in_bits()
|
||||
b_len = len(bstr) * 8
|
||||
if b_len > q_len:
|
||||
# Only keep leftmost q_len bits
|
||||
result >>= (b_len - q_len)
|
||||
return result
|
||||
|
||||
def _int2octets(self, int_mod_q):
|
||||
"""See 2.3.3 in RFC6979"""
|
||||
|
||||
assert 0 < int_mod_q < self._order
|
||||
return long_to_bytes(int_mod_q, self._order_bytes)
|
||||
|
||||
def _bits2octets(self, bstr):
|
||||
"""See 2.3.4 in RFC6979"""
|
||||
|
||||
z1 = self._bits2int(bstr)
|
||||
if z1 < self._order:
|
||||
z2 = z1
|
||||
else:
|
||||
z2 = z1 - self._order
|
||||
return self._int2octets(z2)
|
||||
|
||||
def _compute_nonce(self, mhash):
|
||||
"""Generate k in a deterministic way"""
|
||||
|
||||
# See section 3.2 in RFC6979.txt
|
||||
# Step a
|
||||
h1 = mhash.digest()
|
||||
# Step b
|
||||
mask_v = b'\x01' * mhash.digest_size
|
||||
# Step c
|
||||
nonce_k = b'\x00' * mhash.digest_size
|
||||
|
||||
for int_oct in (b'\x00', b'\x01'):
|
||||
# Step d/f
|
||||
nonce_k = HMAC.new(nonce_k,
|
||||
mask_v + int_oct +
|
||||
self._int2octets(self._private_key) +
|
||||
self._bits2octets(h1), mhash).digest()
|
||||
# Step e/g
|
||||
mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
|
||||
|
||||
nonce = -1
|
||||
while not (0 < nonce < self._order):
|
||||
# Step h.C (second part)
|
||||
if nonce != -1:
|
||||
nonce_k = HMAC.new(nonce_k, mask_v + b'\x00',
|
||||
mhash).digest()
|
||||
mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
|
||||
|
||||
# Step h.A
|
||||
mask_t = b""
|
||||
|
||||
# Step h.B
|
||||
while len(mask_t) < self._order_bytes:
|
||||
mask_v = HMAC.new(nonce_k, mask_v, mhash).digest()
|
||||
mask_t += mask_v
|
||||
|
||||
# Step h.C (first part)
|
||||
nonce = self._bits2int(mask_t)
|
||||
return nonce
|
||||
|
||||
def _valid_hash(self, msg_hash):
|
||||
return True
|
||||
|
||||
|
||||
class FipsDsaSigScheme(DssSigScheme):
|
||||
|
||||
#: List of L (bit length of p) and N (bit length of q) combinations
|
||||
#: that are allowed by FIPS 186-3. The security level is provided in
|
||||
#: Table 2 of FIPS 800-57 (rev3).
|
||||
_fips_186_3_L_N = (
|
||||
(1024, 160), # 80 bits (SHA-1 or stronger)
|
||||
(2048, 224), # 112 bits (SHA-224 or stronger)
|
||||
(2048, 256), # 128 bits (SHA-256 or stronger)
|
||||
(3072, 256) # 256 bits (SHA-512)
|
||||
)
|
||||
|
||||
def __init__(self, key, encoding, order, randfunc):
|
||||
super(FipsDsaSigScheme, self).__init__(key, encoding, order)
|
||||
self._randfunc = randfunc
|
||||
|
||||
L = Integer(key.p).size_in_bits()
|
||||
if (L, self._order_bits) not in self._fips_186_3_L_N:
|
||||
error = ("L/N (%d, %d) is not compliant to FIPS 186-3"
|
||||
% (L, self._order_bits))
|
||||
raise ValueError(error)
|
||||
|
||||
def _compute_nonce(self, msg_hash):
|
||||
# hash is not used
|
||||
return Integer.random_range(min_inclusive=1,
|
||||
max_exclusive=self._order,
|
||||
randfunc=self._randfunc)
|
||||
|
||||
def _valid_hash(self, msg_hash):
|
||||
"""Verify that SHA-1, SHA-2 or SHA-3 are used"""
|
||||
return (msg_hash.oid == "1.3.14.3.2.26" or
|
||||
msg_hash.oid.startswith("2.16.840.1.101.3.4.2."))
|
||||
|
||||
|
||||
class FipsEcDsaSigScheme(DssSigScheme):
|
||||
|
||||
def __init__(self, key, encoding, order, randfunc):
|
||||
super(FipsEcDsaSigScheme, self).__init__(key, encoding, order)
|
||||
self._randfunc = randfunc
|
||||
|
||||
def _compute_nonce(self, msg_hash):
|
||||
return Integer.random_range(min_inclusive=1,
|
||||
max_exclusive=self._key._curve.order,
|
||||
randfunc=self._randfunc)
|
||||
|
||||
def _valid_hash(self, msg_hash):
|
||||
"""Verify that the strength of the hash matches or exceeds
|
||||
the strength of the EC. We fail if the hash is too weak."""
|
||||
|
||||
modulus_bits = self._key.pointQ.size_in_bits()
|
||||
|
||||
# SHS: SHA-2, SHA-3, truncated SHA-512
|
||||
sha224 = ("2.16.840.1.101.3.4.2.4", "2.16.840.1.101.3.4.2.7", "2.16.840.1.101.3.4.2.5")
|
||||
sha256 = ("2.16.840.1.101.3.4.2.1", "2.16.840.1.101.3.4.2.8", "2.16.840.1.101.3.4.2.6")
|
||||
sha384 = ("2.16.840.1.101.3.4.2.2", "2.16.840.1.101.3.4.2.9")
|
||||
sha512 = ("2.16.840.1.101.3.4.2.3", "2.16.840.1.101.3.4.2.10")
|
||||
shs = sha224 + sha256 + sha384 + sha512
|
||||
|
||||
try:
|
||||
result = msg_hash.oid in shs
|
||||
except AttributeError:
|
||||
result = False
|
||||
return result
|
||||
|
||||
|
||||
def new(key, mode, encoding='binary', randfunc=None):
|
||||
"""Create a signature object :class:`DssSigScheme` that
|
||||
can perform (EC)DSA signature or verification.
|
||||
|
||||
.. note::
|
||||
Refer to `NIST SP 800 Part 1 Rev 4`_ (or newer release) for an
|
||||
overview of the recommended key lengths.
|
||||
|
||||
Args:
|
||||
key (:class:`Crypto.PublicKey.DSA` or :class:`Crypto.PublicKey.ECC`):
|
||||
The key to use for computing the signature (*private* keys only)
|
||||
or for verifying one.
|
||||
For DSA keys, let ``L`` and ``N`` be the bit lengths of the modulus ``p``
|
||||
and of ``q``: the pair ``(L,N)`` must appear in the following list,
|
||||
in compliance to section 4.2 of `FIPS 186-4`_:
|
||||
|
||||
- (1024, 160) *legacy only; do not create new signatures with this*
|
||||
- (2048, 224) *deprecated; do not create new signatures with this*
|
||||
- (2048, 256)
|
||||
- (3072, 256)
|
||||
|
||||
For ECC, only keys over P-224, P-256, P-384, and P-521 are accepted.
|
||||
|
||||
mode (string):
|
||||
The parameter can take these values:
|
||||
|
||||
- ``'fips-186-3'``. The signature generation is randomized and carried out
|
||||
according to `FIPS 186-3`_: the nonce ``k`` is taken from the RNG.
|
||||
- ``'deterministic-rfc6979'``. The signature generation is not
|
||||
randomized. See RFC6979_.
|
||||
|
||||
encoding (string):
|
||||
How the signature is encoded. This value determines the output of
|
||||
:meth:`sign` and the input to :meth:`verify`.
|
||||
|
||||
The following values are accepted:
|
||||
|
||||
- ``'binary'`` (default), the signature is the raw concatenation
|
||||
of ``r`` and ``s``. It is defined in the IEEE P.1363 standard.
|
||||
For DSA, the size in bytes of the signature is ``N/4`` bytes
|
||||
(e.g. 64 for ``N=256``).
|
||||
For ECDSA, the signature is always twice the length of a point
|
||||
coordinate (e.g. 64 bytes for P-256).
|
||||
|
||||
- ``'der'``, the signature is a ASN.1 DER SEQUENCE
|
||||
with two INTEGERs (``r`` and ``s``). It is defined in RFC3279_.
|
||||
The size of the signature is variable.
|
||||
|
||||
randfunc (callable):
|
||||
A function that returns random ``bytes``, of a given length.
|
||||
If omitted, the internal RNG is used.
|
||||
Only applicable for the *'fips-186-3'* mode.
|
||||
|
||||
.. _FIPS 186-3: http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
|
||||
.. _FIPS 186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
||||
.. _NIST SP 800 Part 1 Rev 4: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf
|
||||
.. _RFC6979: http://tools.ietf.org/html/rfc6979
|
||||
.. _RFC3279: https://tools.ietf.org/html/rfc3279#section-2.2.2
|
||||
"""
|
||||
|
||||
# The goal of the 'mode' parameter is to avoid to
|
||||
# have the current version of the standard as default.
|
||||
#
|
||||
# Over time, such version will be superseded by (for instance)
|
||||
# FIPS 186-4 and it will be odd to have -3 as default.
|
||||
|
||||
if encoding not in ('binary', 'der'):
|
||||
raise ValueError("Unknown encoding '%s'" % encoding)
|
||||
|
||||
if isinstance(key, EccKey):
|
||||
order = key._curve.order
|
||||
private_key_attr = 'd'
|
||||
if not key.curve.startswith("NIST"):
|
||||
raise ValueError("ECC key is not on a NIST P curve")
|
||||
elif isinstance(key, DsaKey):
|
||||
order = Integer(key.q)
|
||||
private_key_attr = 'x'
|
||||
else:
|
||||
raise ValueError("Unsupported key type " + str(type(key)))
|
||||
|
||||
if key.has_private():
|
||||
private_key = getattr(key, private_key_attr)
|
||||
else:
|
||||
private_key = None
|
||||
|
||||
if mode == 'deterministic-rfc6979':
|
||||
return DeterministicDsaSigScheme(key, encoding, order, private_key)
|
||||
elif mode == 'fips-186-3':
|
||||
if isinstance(key, EccKey):
|
||||
return FipsEcDsaSigScheme(key, encoding, order, randfunc)
|
||||
else:
|
||||
return FipsDsaSigScheme(key, encoding, order, randfunc)
|
||||
else:
|
||||
raise ValueError("Unknown DSS mode '%s'" % mode)
|
27
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/DSS.pyi
vendored
Normal file
27
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/DSS.pyi
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
from typing import Union, Optional, Callable
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Crypto.PublicKey.DSA import DsaKey
|
||||
from Crypto.PublicKey.ECC import EccKey
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
|
||||
__all__ = ['new']
|
||||
|
||||
class DssSigScheme:
|
||||
def __init__(self, key: Union[DsaKey, EccKey], encoding: str, order: int) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_hash: Hash) -> bytes: ...
|
||||
def verify(self, msg_hash: Hash, signature: bytes) -> bool: ...
|
||||
|
||||
class DeterministicDsaSigScheme(DssSigScheme):
|
||||
def __init__(self, key, encoding, order, private_key) -> None: ...
|
||||
|
||||
class FipsDsaSigScheme(DssSigScheme):
|
||||
def __init__(self, key: DsaKey, encoding: str, order: int, randfunc: Callable) -> None: ...
|
||||
|
||||
class FipsEcDsaSigScheme(DssSigScheme):
|
||||
def __init__(self, key: EccKey, encoding: str, order: int, randfunc: Callable) -> None: ...
|
||||
|
||||
def new(key: Union[DsaKey, EccKey], mode: str, encoding: Optional[str]='binary', randfunc: Optional[Callable]=None) -> Union[DeterministicDsaSigScheme, FipsDsaSigScheme, FipsEcDsaSigScheme]: ...
|
55
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_PSS.py
vendored
Normal file
55
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_PSS.py
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Legacy module for PKCS#1 PSS signatures.
|
||||
|
||||
:undocumented: __package__
|
||||
"""
|
||||
|
||||
import types
|
||||
|
||||
from Crypto.Signature import pss
|
||||
|
||||
|
||||
def _pycrypto_verify(self, hash_object, signature):
|
||||
try:
|
||||
self._verify(hash_object, signature)
|
||||
except (ValueError, TypeError):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def new(rsa_key, mgfunc=None, saltLen=None, randfunc=None):
|
||||
pkcs1 = pss.new(rsa_key, mask_func=mgfunc,
|
||||
salt_bytes=saltLen, rand_func=randfunc)
|
||||
pkcs1._verify = pkcs1.verify
|
||||
pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1)
|
||||
return pkcs1
|
28
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_PSS.pyi
vendored
Normal file
28
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_PSS.pyi
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
from typing import Union, Callable, Optional
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
def update(self, bytes) -> None: ...
|
||||
|
||||
|
||||
class HashModule(Protocol):
|
||||
@staticmethod
|
||||
def new(data: Optional[bytes]) -> Hash: ...
|
||||
|
||||
|
||||
MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes]
|
||||
RndFunction = Callable[[int], bytes]
|
||||
|
||||
class PSS_SigScheme:
|
||||
def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_hash: Hash) -> bytes: ...
|
||||
def verify(self, msg_hash: Hash, signature: bytes) -> bool: ...
|
||||
|
||||
|
||||
|
||||
def new(rsa_key: RsaKey, mgfunc: Optional[MaskFunction]=None, saltLen: Optional[int]=None, randfunc: Optional[RndFunction]=None) -> PSS_SigScheme: ...
|
53
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_v1_5.py
vendored
Normal file
53
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_v1_5.py
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""
|
||||
Legacy module for PKCS#1 v1.5 signatures.
|
||||
|
||||
:undocumented: __package__
|
||||
"""
|
||||
|
||||
import types
|
||||
|
||||
from Crypto.Signature import pkcs1_15
|
||||
|
||||
def _pycrypto_verify(self, hash_object, signature):
|
||||
try:
|
||||
self._verify(hash_object, signature)
|
||||
except (ValueError, TypeError):
|
||||
return False
|
||||
return True
|
||||
|
||||
def new(rsa_key):
|
||||
pkcs1 = pkcs1_15.new(rsa_key)
|
||||
pkcs1._verify = pkcs1.verify
|
||||
pkcs1.verify = types.MethodType(_pycrypto_verify, pkcs1)
|
||||
return pkcs1
|
||||
|
16
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_v1_5.pyi
vendored
Normal file
16
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/PKCS1_v1_5.pyi
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
from typing import Optional
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
|
||||
class PKCS115_SigScheme:
|
||||
def __init__(self, rsa_key: RsaKey) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_hash: Hash) -> bytes: ...
|
||||
def verify(self, msg_hash: Hash, signature: bytes) -> bool: ...
|
||||
|
||||
|
||||
def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ...
|
36
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__init__.py
vendored
Normal file
36
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__init__.py
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""Digital signature protocols
|
||||
|
||||
A collection of standardized protocols to carry out digital signatures.
|
||||
"""
|
||||
|
||||
__all__ = ['PKCS1_v1_5', 'PKCS1_PSS', 'DSS', 'pkcs1_15', 'pss', 'eddsa']
|
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/DSS.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/DSS.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/PKCS1_PSS.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/PKCS1_PSS.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/PKCS1_v1_5.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/PKCS1_v1_5.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/eddsa.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/eddsa.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/pkcs1_15.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/pkcs1_15.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/pss.cpython-312.pyc
vendored
Normal file
BIN
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/__pycache__/pss.cpython-312.pyc
vendored
Normal file
Binary file not shown.
343
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/eddsa.py
vendored
Normal file
343
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/eddsa.py
vendored
Normal file
@ -0,0 +1,343 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2022, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Crypto.Math.Numbers import Integer
|
||||
|
||||
from Crypto.Hash import SHA512, SHAKE256
|
||||
from Crypto.Util.py3compat import bchr, is_bytes
|
||||
from Crypto.PublicKey.ECC import (EccKey,
|
||||
construct,
|
||||
_import_ed25519_public_key,
|
||||
_import_ed448_public_key)
|
||||
|
||||
|
||||
def import_public_key(encoded):
|
||||
"""Create a new Ed25519 or Ed448 public key object,
|
||||
starting from the key encoded as raw ``bytes``,
|
||||
in the format described in RFC8032.
|
||||
|
||||
Args:
|
||||
encoded (bytes):
|
||||
The EdDSA public key to import.
|
||||
It must be 32 bytes for Ed25519, and 57 bytes for Ed448.
|
||||
|
||||
Returns:
|
||||
:class:`Crypto.PublicKey.EccKey` : a new ECC key object.
|
||||
|
||||
Raises:
|
||||
ValueError: when the given key cannot be parsed.
|
||||
"""
|
||||
|
||||
if len(encoded) == 32:
|
||||
x, y = _import_ed25519_public_key(encoded)
|
||||
curve_name = "Ed25519"
|
||||
elif len(encoded) == 57:
|
||||
x, y = _import_ed448_public_key(encoded)
|
||||
curve_name = "Ed448"
|
||||
else:
|
||||
raise ValueError("Not an EdDSA key (%d bytes)" % len(encoded))
|
||||
return construct(curve=curve_name, point_x=x, point_y=y)
|
||||
|
||||
|
||||
def import_private_key(encoded):
|
||||
"""Create a new Ed25519 or Ed448 private key object,
|
||||
starting from the key encoded as raw ``bytes``,
|
||||
in the format described in RFC8032.
|
||||
|
||||
Args:
|
||||
encoded (bytes):
|
||||
The EdDSA private key to import.
|
||||
It must be 32 bytes for Ed25519, and 57 bytes for Ed448.
|
||||
|
||||
Returns:
|
||||
:class:`Crypto.PublicKey.EccKey` : a new ECC key object.
|
||||
|
||||
Raises:
|
||||
ValueError: when the given key cannot be parsed.
|
||||
"""
|
||||
|
||||
if len(encoded) == 32:
|
||||
curve_name = "ed25519"
|
||||
elif len(encoded) == 57:
|
||||
curve_name = "ed448"
|
||||
else:
|
||||
raise ValueError("Incorrect length. Only EdDSA private keys are supported.")
|
||||
|
||||
# Note that the private key is truly a sequence of random bytes,
|
||||
# so we cannot check its correctness in any way.
|
||||
|
||||
return construct(seed=encoded, curve=curve_name)
|
||||
|
||||
|
||||
class EdDSASigScheme(object):
|
||||
"""An EdDSA signature object.
|
||||
Do not instantiate directly.
|
||||
Use :func:`Crypto.Signature.eddsa.new`.
|
||||
"""
|
||||
|
||||
def __init__(self, key, context):
|
||||
"""Create a new EdDSA object.
|
||||
|
||||
Do not instantiate this object directly,
|
||||
use `Crypto.Signature.DSS.new` instead.
|
||||
"""
|
||||
|
||||
self._key = key
|
||||
self._context = context
|
||||
self._A = key._export_eddsa_public()
|
||||
self._order = key._curve.order
|
||||
|
||||
def can_sign(self):
|
||||
"""Return ``True`` if this signature object can be used
|
||||
for signing messages."""
|
||||
|
||||
return self._key.has_private()
|
||||
|
||||
def sign(self, msg_or_hash):
|
||||
"""Compute the EdDSA signature of a message.
|
||||
|
||||
Args:
|
||||
msg_or_hash (bytes or a hash object):
|
||||
The message to sign (``bytes``, in case of *PureEdDSA*) or
|
||||
the hash that was carried out over the message (hash object, for *HashEdDSA*).
|
||||
|
||||
The hash object must be :class:`Crypto.Hash.SHA512` for Ed25519,
|
||||
and :class:`Crypto.Hash.SHAKE256` object for Ed448.
|
||||
|
||||
:return: The signature as ``bytes``. It is always 64 bytes for Ed25519, and 114 bytes for Ed448.
|
||||
:raise TypeError: if the EdDSA key has no private half
|
||||
"""
|
||||
|
||||
if not self._key.has_private():
|
||||
raise TypeError("Private key is needed to sign")
|
||||
|
||||
if self._key.curve == "Ed25519":
|
||||
ph = isinstance(msg_or_hash, SHA512.SHA512Hash)
|
||||
if not (ph or is_bytes(msg_or_hash)):
|
||||
raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash")
|
||||
eddsa_sign_method = self._sign_ed25519
|
||||
|
||||
elif self._key.curve == "Ed448":
|
||||
ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF)
|
||||
if not (ph or is_bytes(msg_or_hash)):
|
||||
raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash")
|
||||
eddsa_sign_method = self._sign_ed448
|
||||
|
||||
else:
|
||||
raise ValueError("Incorrect curve for EdDSA")
|
||||
|
||||
return eddsa_sign_method(msg_or_hash, ph)
|
||||
|
||||
def _sign_ed25519(self, msg_or_hash, ph):
|
||||
|
||||
if self._context or ph:
|
||||
flag = int(ph)
|
||||
# dom2(flag, self._context)
|
||||
dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \
|
||||
bchr(len(self._context)) + self._context
|
||||
else:
|
||||
dom2 = b''
|
||||
|
||||
PHM = msg_or_hash.digest() if ph else msg_or_hash
|
||||
|
||||
# See RFC 8032, section 5.1.6
|
||||
|
||||
# Step 2
|
||||
r_hash = SHA512.new(dom2 + self._key._prefix + PHM).digest()
|
||||
r = Integer.from_bytes(r_hash, 'little') % self._order
|
||||
# Step 3
|
||||
R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public()
|
||||
# Step 4
|
||||
k_hash = SHA512.new(dom2 + R_pk + self._A + PHM).digest()
|
||||
k = Integer.from_bytes(k_hash, 'little') % self._order
|
||||
# Step 5
|
||||
s = (r + k * self._key.d) % self._order
|
||||
|
||||
return R_pk + s.to_bytes(32, 'little')
|
||||
|
||||
def _sign_ed448(self, msg_or_hash, ph):
|
||||
|
||||
flag = int(ph)
|
||||
# dom4(flag, self._context)
|
||||
dom4 = b'SigEd448' + bchr(flag) + \
|
||||
bchr(len(self._context)) + self._context
|
||||
|
||||
PHM = msg_or_hash.read(64) if ph else msg_or_hash
|
||||
|
||||
# See RFC 8032, section 5.2.6
|
||||
|
||||
# Step 2
|
||||
r_hash = SHAKE256.new(dom4 + self._key._prefix + PHM).read(114)
|
||||
r = Integer.from_bytes(r_hash, 'little') % self._order
|
||||
# Step 3
|
||||
R_pk = EccKey(point=r * self._key._curve.G)._export_eddsa_public()
|
||||
# Step 4
|
||||
k_hash = SHAKE256.new(dom4 + R_pk + self._A + PHM).read(114)
|
||||
k = Integer.from_bytes(k_hash, 'little') % self._order
|
||||
# Step 5
|
||||
s = (r + k * self._key.d) % self._order
|
||||
|
||||
return R_pk + s.to_bytes(57, 'little')
|
||||
|
||||
def verify(self, msg_or_hash, signature):
|
||||
"""Check if an EdDSA signature is authentic.
|
||||
|
||||
Args:
|
||||
msg_or_hash (bytes or a hash object):
|
||||
The message to verify (``bytes``, in case of *PureEdDSA*) or
|
||||
the hash that was carried out over the message (hash object, for *HashEdDSA*).
|
||||
|
||||
The hash object must be :class:`Crypto.Hash.SHA512` object for Ed25519,
|
||||
and :class:`Crypto.Hash.SHAKE256` for Ed448.
|
||||
|
||||
signature (``bytes``):
|
||||
The signature that needs to be validated.
|
||||
It must be 64 bytes for Ed25519, and 114 bytes for Ed448.
|
||||
|
||||
:raise ValueError: if the signature is not authentic
|
||||
"""
|
||||
|
||||
if self._key.curve == "Ed25519":
|
||||
ph = isinstance(msg_or_hash, SHA512.SHA512Hash)
|
||||
if not (ph or is_bytes(msg_or_hash)):
|
||||
raise TypeError("'msg_or_hash' must be bytes of a SHA-512 hash")
|
||||
eddsa_verify_method = self._verify_ed25519
|
||||
|
||||
elif self._key.curve == "Ed448":
|
||||
ph = isinstance(msg_or_hash, SHAKE256.SHAKE256_XOF)
|
||||
if not (ph or is_bytes(msg_or_hash)):
|
||||
raise TypeError("'msg_or_hash' must be bytes of a SHAKE256 hash")
|
||||
eddsa_verify_method = self._verify_ed448
|
||||
|
||||
else:
|
||||
raise ValueError("Incorrect curve for EdDSA")
|
||||
|
||||
return eddsa_verify_method(msg_or_hash, signature, ph)
|
||||
|
||||
def _verify_ed25519(self, msg_or_hash, signature, ph):
|
||||
|
||||
if len(signature) != 64:
|
||||
raise ValueError("The signature is not authentic (length)")
|
||||
|
||||
if self._context or ph:
|
||||
flag = int(ph)
|
||||
dom2 = b'SigEd25519 no Ed25519 collisions' + bchr(flag) + \
|
||||
bchr(len(self._context)) + self._context
|
||||
else:
|
||||
dom2 = b''
|
||||
|
||||
PHM = msg_or_hash.digest() if ph else msg_or_hash
|
||||
|
||||
# Section 5.1.7
|
||||
|
||||
# Step 1
|
||||
try:
|
||||
R = import_public_key(signature[:32]).pointQ
|
||||
except ValueError:
|
||||
raise ValueError("The signature is not authentic (R)")
|
||||
s = Integer.from_bytes(signature[32:], 'little')
|
||||
if s > self._order:
|
||||
raise ValueError("The signature is not authentic (S)")
|
||||
# Step 2
|
||||
k_hash = SHA512.new(dom2 + signature[:32] + self._A + PHM).digest()
|
||||
k = Integer.from_bytes(k_hash, 'little') % self._order
|
||||
# Step 3
|
||||
point1 = s * 8 * self._key._curve.G
|
||||
# OPTIMIZE: with double-scalar multiplication, with no SCA
|
||||
# countermeasures because it is public values
|
||||
point2 = 8 * R + k * 8 * self._key.pointQ
|
||||
if point1 != point2:
|
||||
raise ValueError("The signature is not authentic")
|
||||
|
||||
def _verify_ed448(self, msg_or_hash, signature, ph):
|
||||
|
||||
if len(signature) != 114:
|
||||
raise ValueError("The signature is not authentic (length)")
|
||||
|
||||
flag = int(ph)
|
||||
# dom4(flag, self._context)
|
||||
dom4 = b'SigEd448' + bchr(flag) + \
|
||||
bchr(len(self._context)) + self._context
|
||||
|
||||
PHM = msg_or_hash.read(64) if ph else msg_or_hash
|
||||
|
||||
# Section 5.2.7
|
||||
|
||||
# Step 1
|
||||
try:
|
||||
R = import_public_key(signature[:57]).pointQ
|
||||
except ValueError:
|
||||
raise ValueError("The signature is not authentic (R)")
|
||||
s = Integer.from_bytes(signature[57:], 'little')
|
||||
if s > self._order:
|
||||
raise ValueError("The signature is not authentic (S)")
|
||||
# Step 2
|
||||
k_hash = SHAKE256.new(dom4 + signature[:57] + self._A + PHM).read(114)
|
||||
k = Integer.from_bytes(k_hash, 'little') % self._order
|
||||
# Step 3
|
||||
point1 = s * 8 * self._key._curve.G
|
||||
# OPTIMIZE: with double-scalar multiplication, with no SCA
|
||||
# countermeasures because it is public values
|
||||
point2 = 8 * R + k * 8 * self._key.pointQ
|
||||
if point1 != point2:
|
||||
raise ValueError("The signature is not authentic")
|
||||
|
||||
|
||||
def new(key, mode, context=None):
|
||||
"""Create a signature object :class:`EdDSASigScheme` that
|
||||
can perform or verify an EdDSA signature.
|
||||
|
||||
Args:
|
||||
key (:class:`Crypto.PublicKey.ECC` object):
|
||||
The key to use for computing the signature (*private* keys only)
|
||||
or for verifying one.
|
||||
The key must be on the curve ``Ed25519`` or ``Ed448``.
|
||||
|
||||
mode (string):
|
||||
This parameter must be ``'rfc8032'``.
|
||||
|
||||
context (bytes):
|
||||
Up to 255 bytes of `context <https://datatracker.ietf.org/doc/html/rfc8032#page-41>`_,
|
||||
which is a constant byte string to segregate different protocols or
|
||||
different applications of the same key.
|
||||
"""
|
||||
|
||||
if not isinstance(key, EccKey) or key.curve not in ("Ed25519", "Ed448"):
|
||||
raise ValueError("EdDSA can only be used with EdDSA keys")
|
||||
|
||||
if mode != 'rfc8032':
|
||||
raise ValueError("Mode must be 'rfc8032'")
|
||||
|
||||
if context is None:
|
||||
context = b''
|
||||
elif len(context) > 255:
|
||||
raise ValueError("Context for EdDSA must not be longer than 255 bytes")
|
||||
|
||||
return EdDSASigScheme(key, context)
|
21
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/eddsa.pyi
vendored
Normal file
21
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/eddsa.pyi
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
from typing import Union, Optional
|
||||
from typing_extensions import Protocol
|
||||
from Crypto.PublicKey.ECC import EccKey
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
|
||||
class XOF(Protocol):
|
||||
def read(self, len: int) -> bytes: ...
|
||||
|
||||
def import_public_key(encoded: bytes) -> EccKey: ...
|
||||
def import_private_key(encoded: bytes) -> EccKey: ...
|
||||
|
||||
class EdDSASigScheme(object):
|
||||
|
||||
def __init__(self, key: EccKey, context: bytes) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_or_hash: Union[bytes, Hash, XOF]) -> bytes: ...
|
||||
def verify(self, msg_or_hash: Union[bytes, Hash, XOF], signature: bytes) -> None: ...
|
||||
|
||||
def new(key: EccKey, mode: str, context: Optional[bytes]=None) -> EdDSASigScheme: ...
|
223
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pkcs1_15.py
vendored
Normal file
223
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pkcs1_15.py
vendored
Normal file
@ -0,0 +1,223 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
import Crypto.Util.number
|
||||
from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
|
||||
from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId
|
||||
|
||||
class PKCS115_SigScheme:
|
||||
"""A signature object for ``RSASSA-PKCS1-v1_5``.
|
||||
Do not instantiate directly.
|
||||
Use :func:`Crypto.Signature.pkcs1_15.new`.
|
||||
"""
|
||||
|
||||
def __init__(self, rsa_key):
|
||||
"""Initialize this PKCS#1 v1.5 signature scheme object.
|
||||
|
||||
:Parameters:
|
||||
rsa_key : an RSA key object
|
||||
Creation of signatures is only possible if this is a *private*
|
||||
RSA key. Verification of signatures is always possible.
|
||||
"""
|
||||
self._key = rsa_key
|
||||
|
||||
def can_sign(self):
|
||||
"""Return ``True`` if this object can be used to sign messages."""
|
||||
return self._key.has_private()
|
||||
|
||||
def sign(self, msg_hash):
|
||||
"""Create the PKCS#1 v1.5 signature of a message.
|
||||
|
||||
This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and
|
||||
it is specified in
|
||||
`section 8.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#page-36>`_.
|
||||
|
||||
:parameter msg_hash:
|
||||
This is an object from the :mod:`Crypto.Hash` package.
|
||||
It has been used to digest the message to sign.
|
||||
:type msg_hash: hash object
|
||||
|
||||
:return: the signature encoded as a *byte string*.
|
||||
:raise ValueError: if the RSA key is not long enough for the given hash algorithm.
|
||||
:raise TypeError: if the RSA key has no private half.
|
||||
"""
|
||||
|
||||
# See 8.2.1 in RFC3447
|
||||
modBits = Crypto.Util.number.size(self._key.n)
|
||||
k = ceil_div(modBits,8) # Convert from bits to bytes
|
||||
|
||||
# Step 1
|
||||
em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
|
||||
# Step 2a (OS2IP)
|
||||
em_int = bytes_to_long(em)
|
||||
# Step 2b (RSASP1) and Step 2c (I2OSP)
|
||||
signature = self._key._decrypt_to_bytes(em_int)
|
||||
# Verify no faults occurred
|
||||
if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n):
|
||||
raise ValueError("Fault detected in RSA private key operation")
|
||||
return signature
|
||||
|
||||
def verify(self, msg_hash, signature):
|
||||
"""Check if the PKCS#1 v1.5 signature over a message is valid.
|
||||
|
||||
This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and
|
||||
it is specified in
|
||||
`section 8.2.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#page-37>`_.
|
||||
|
||||
:parameter msg_hash:
|
||||
The hash that was carried out over the message. This is an object
|
||||
belonging to the :mod:`Crypto.Hash` module.
|
||||
:type parameter: hash object
|
||||
|
||||
:parameter signature:
|
||||
The signature that needs to be validated.
|
||||
:type signature: byte string
|
||||
|
||||
:raise ValueError: if the signature is not valid.
|
||||
"""
|
||||
|
||||
# See 8.2.2 in RFC3447
|
||||
modBits = Crypto.Util.number.size(self._key.n)
|
||||
k = ceil_div(modBits, 8) # Convert from bits to bytes
|
||||
|
||||
# Step 1
|
||||
if len(signature) != k:
|
||||
raise ValueError("Invalid signature")
|
||||
# Step 2a (O2SIP)
|
||||
signature_int = bytes_to_long(signature)
|
||||
# Step 2b (RSAVP1)
|
||||
em_int = self._key._encrypt(signature_int)
|
||||
# Step 2c (I2OSP)
|
||||
em1 = long_to_bytes(em_int, k)
|
||||
# Step 3
|
||||
try:
|
||||
possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ]
|
||||
# MD2/4/5 hashes always require NULL params in AlgorithmIdentifier.
|
||||
# For all others, it is optional.
|
||||
try:
|
||||
algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.')
|
||||
except AttributeError:
|
||||
algorithm_is_md = False
|
||||
if not algorithm_is_md: # MD2/MD4/MD5
|
||||
possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False))
|
||||
except ValueError:
|
||||
raise ValueError("Invalid signature")
|
||||
# Step 4
|
||||
# By comparing the full encodings (as opposed to checking each
|
||||
# of its components one at a time) we avoid attacks to the padding
|
||||
# scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537).
|
||||
#
|
||||
if em1 not in possible_em1:
|
||||
raise ValueError("Invalid signature")
|
||||
pass
|
||||
|
||||
|
||||
def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True):
|
||||
"""
|
||||
Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
|
||||
in PKCS#1 v2.1 (RFC3447, 9.2).
|
||||
|
||||
``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
|
||||
and hash it internally. Here, we expect that the message has already
|
||||
been hashed instead.
|
||||
|
||||
:Parameters:
|
||||
msg_hash : hash object
|
||||
The hash object that holds the digest of the message being signed.
|
||||
emLen : int
|
||||
The length the final encoding must have, in bytes.
|
||||
with_hash_parameters : bool
|
||||
If True (default), include NULL parameters for the hash
|
||||
algorithm in the ``digestAlgorithm`` SEQUENCE.
|
||||
|
||||
:attention: the early standard (RFC2313) stated that ``DigestInfo``
|
||||
had to be BER-encoded. This means that old signatures
|
||||
might have length tags in indefinite form, which
|
||||
is not supported in DER. Such encoding cannot be
|
||||
reproduced by this function.
|
||||
|
||||
:Return: An ``emLen`` byte long string that encodes the hash.
|
||||
"""
|
||||
|
||||
# First, build the ASN.1 DER object DigestInfo:
|
||||
#
|
||||
# DigestInfo ::= SEQUENCE {
|
||||
# digestAlgorithm AlgorithmIdentifier,
|
||||
# digest OCTET STRING
|
||||
# }
|
||||
#
|
||||
# where digestAlgorithm identifies the hash function and shall be an
|
||||
# algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
|
||||
#
|
||||
# PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
|
||||
# { OID id-md2 PARAMETERS NULL }|
|
||||
# { OID id-md5 PARAMETERS NULL }|
|
||||
# { OID id-sha1 PARAMETERS NULL }|
|
||||
# { OID id-sha256 PARAMETERS NULL }|
|
||||
# { OID id-sha384 PARAMETERS NULL }|
|
||||
# { OID id-sha512 PARAMETERS NULL }
|
||||
# }
|
||||
#
|
||||
# Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters
|
||||
# should be omitted. They may be present, but when they are, they shall
|
||||
# have NULL value.
|
||||
|
||||
digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ])
|
||||
|
||||
if with_hash_parameters:
|
||||
digestAlgo.append(DerNull().encode())
|
||||
|
||||
digest = DerOctetString(msg_hash.digest())
|
||||
digestInfo = DerSequence([
|
||||
digestAlgo.encode(),
|
||||
digest.encode()
|
||||
]).encode()
|
||||
|
||||
# We need at least 11 bytes for the remaining data: 3 fixed bytes and
|
||||
# at least 8 bytes of padding).
|
||||
if emLen<len(digestInfo)+11:
|
||||
raise TypeError("DigestInfo is too long for this RSA key (%d bytes)." % len(digestInfo))
|
||||
PS = b'\xFF' * (emLen - len(digestInfo) - 3)
|
||||
return b'\x00\x01' + PS + b'\x00' + digestInfo
|
||||
|
||||
def new(rsa_key):
|
||||
"""Create a signature object for creating
|
||||
or verifying PKCS#1 v1.5 signatures.
|
||||
|
||||
:parameter rsa_key:
|
||||
The RSA key to use for signing or verifying the message.
|
||||
This is a :class:`Crypto.PublicKey.RSA` object.
|
||||
Signing is only possible when ``rsa_key`` is a **private** RSA key.
|
||||
:type rsa_key: RSA object
|
||||
|
||||
:return: a :class:`PKCS115_SigScheme` signature object
|
||||
"""
|
||||
return PKCS115_SigScheme(rsa_key)
|
||||
|
17
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pkcs1_15.pyi
vendored
Normal file
17
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pkcs1_15.pyi
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
from typing import Optional
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
|
||||
class PKCS115_SigScheme:
|
||||
def __init__(self, rsa_key: RsaKey) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_hash: Hash) -> bytes: ...
|
||||
def verify(self, msg_hash: Hash, signature: bytes) -> None: ...
|
||||
|
||||
def _EMSA_PKCS1_V1_5_ENCODE(msg_hash: Hash, emLen: int, with_hash_parameters: Optional[bool]=True) -> bytes: ...
|
||||
|
||||
def new(rsa_key: RsaKey) -> PKCS115_SigScheme: ...
|
387
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pss.py
vendored
Normal file
387
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pss.py
vendored
Normal file
@ -0,0 +1,387 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from Crypto.Util.py3compat import bchr, bord, iter_range
|
||||
import Crypto.Util.number
|
||||
from Crypto.Util.number import (ceil_div,
|
||||
long_to_bytes,
|
||||
bytes_to_long
|
||||
)
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto import Random
|
||||
|
||||
|
||||
class PSS_SigScheme:
|
||||
"""A signature object for ``RSASSA-PSS``.
|
||||
Do not instantiate directly.
|
||||
Use :func:`Crypto.Signature.pss.new`.
|
||||
"""
|
||||
|
||||
def __init__(self, key, mgfunc, saltLen, randfunc):
|
||||
"""Initialize this PKCS#1 PSS signature scheme object.
|
||||
|
||||
:Parameters:
|
||||
key : an RSA key object
|
||||
If a private half is given, both signature and
|
||||
verification are possible.
|
||||
If a public half is given, only verification is possible.
|
||||
mgfunc : callable
|
||||
A mask generation function that accepts two parameters:
|
||||
a string to use as seed, and the lenth of the mask to
|
||||
generate, in bytes.
|
||||
saltLen : integer
|
||||
Length of the salt, in bytes.
|
||||
randfunc : callable
|
||||
A function that returns random bytes.
|
||||
"""
|
||||
|
||||
self._key = key
|
||||
self._saltLen = saltLen
|
||||
self._mgfunc = mgfunc
|
||||
self._randfunc = randfunc
|
||||
|
||||
def can_sign(self):
|
||||
"""Return ``True`` if this object can be used to sign messages."""
|
||||
return self._key.has_private()
|
||||
|
||||
def sign(self, msg_hash):
|
||||
"""Create the PKCS#1 PSS signature of a message.
|
||||
|
||||
This function is also called ``RSASSA-PSS-SIGN`` and
|
||||
it is specified in
|
||||
`section 8.1.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#section-8.1.1>`_.
|
||||
|
||||
:parameter msg_hash:
|
||||
This is an object from the :mod:`Crypto.Hash` package.
|
||||
It has been used to digest the message to sign.
|
||||
:type msg_hash: hash object
|
||||
|
||||
:return: the signature encoded as a *byte string*.
|
||||
:raise ValueError: if the RSA key is not long enough for the given hash algorithm.
|
||||
:raise TypeError: if the RSA key has no private half.
|
||||
"""
|
||||
|
||||
# Set defaults for salt length and mask generation function
|
||||
if self._saltLen is None:
|
||||
sLen = msg_hash.digest_size
|
||||
else:
|
||||
sLen = self._saltLen
|
||||
|
||||
if self._mgfunc is None:
|
||||
mgf = lambda x, y: MGF1(x, y, msg_hash)
|
||||
else:
|
||||
mgf = self._mgfunc
|
||||
|
||||
modBits = Crypto.Util.number.size(self._key.n)
|
||||
|
||||
# See 8.1.1 in RFC3447
|
||||
k = ceil_div(modBits, 8) # k is length in bytes of the modulus
|
||||
# Step 1
|
||||
em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen)
|
||||
# Step 2a (OS2IP)
|
||||
em_int = bytes_to_long(em)
|
||||
# Step 2b (RSASP1) and Step 2c (I2OSP)
|
||||
signature = self._key._decrypt_to_bytes(em_int)
|
||||
# Verify no faults occurred
|
||||
if em_int != pow(bytes_to_long(signature), self._key.e, self._key.n):
|
||||
raise ValueError("Fault detected in RSA private key operation")
|
||||
return signature
|
||||
|
||||
def verify(self, msg_hash, signature):
|
||||
"""Check if the PKCS#1 PSS signature over a message is valid.
|
||||
|
||||
This function is also called ``RSASSA-PSS-VERIFY`` and
|
||||
it is specified in
|
||||
`section 8.1.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#section-8.1.2>`_.
|
||||
|
||||
:parameter msg_hash:
|
||||
The hash that was carried out over the message. This is an object
|
||||
belonging to the :mod:`Crypto.Hash` module.
|
||||
:type parameter: hash object
|
||||
|
||||
:parameter signature:
|
||||
The signature that needs to be validated.
|
||||
:type signature: bytes
|
||||
|
||||
:raise ValueError: if the signature is not valid.
|
||||
"""
|
||||
|
||||
# Set defaults for salt length and mask generation function
|
||||
if self._saltLen is None:
|
||||
sLen = msg_hash.digest_size
|
||||
else:
|
||||
sLen = self._saltLen
|
||||
if self._mgfunc:
|
||||
mgf = self._mgfunc
|
||||
else:
|
||||
mgf = lambda x, y: MGF1(x, y, msg_hash)
|
||||
|
||||
modBits = Crypto.Util.number.size(self._key.n)
|
||||
|
||||
# See 8.1.2 in RFC3447
|
||||
k = ceil_div(modBits, 8) # Convert from bits to bytes
|
||||
# Step 1
|
||||
if len(signature) != k:
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 2a (O2SIP)
|
||||
signature_int = bytes_to_long(signature)
|
||||
# Step 2b (RSAVP1)
|
||||
em_int = self._key._encrypt(signature_int)
|
||||
# Step 2c (I2OSP)
|
||||
emLen = ceil_div(modBits - 1, 8)
|
||||
em = long_to_bytes(em_int, emLen)
|
||||
# Step 3/4
|
||||
_EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
|
||||
|
||||
|
||||
def MGF1(mgfSeed, maskLen, hash_gen):
|
||||
"""Mask Generation Function, described in `B.2.1 of RFC8017
|
||||
<https://tools.ietf.org/html/rfc8017>`_.
|
||||
|
||||
:param mfgSeed:
|
||||
seed from which the mask is generated
|
||||
:type mfgSeed: byte string
|
||||
|
||||
:param maskLen:
|
||||
intended length in bytes of the mask
|
||||
:type maskLen: integer
|
||||
|
||||
:param hash_gen:
|
||||
A module or a hash object from :mod:`Crypto.Hash`
|
||||
:type hash_object:
|
||||
|
||||
:return: the mask, as a *byte string*
|
||||
"""
|
||||
|
||||
T = b""
|
||||
for counter in iter_range(ceil_div(maskLen, hash_gen.digest_size)):
|
||||
c = long_to_bytes(counter, 4)
|
||||
hobj = hash_gen.new()
|
||||
hobj.update(mgfSeed + c)
|
||||
T = T + hobj.digest()
|
||||
assert(len(T) >= maskLen)
|
||||
return T[:maskLen]
|
||||
|
||||
|
||||
def _EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
|
||||
r"""
|
||||
Implement the ``EMSA-PSS-ENCODE`` function, as defined
|
||||
in PKCS#1 v2.1 (RFC3447, 9.1.1).
|
||||
|
||||
The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M``
|
||||
as input, and hash it internally. Here, we expect that the message
|
||||
has already been hashed instead.
|
||||
|
||||
:Parameters:
|
||||
mhash : hash object
|
||||
The hash object that holds the digest of the message being signed.
|
||||
emBits : int
|
||||
Maximum length of the final encoding, in bits.
|
||||
randFunc : callable
|
||||
An RNG function that accepts as only parameter an int, and returns
|
||||
a string of random bytes, to be used as salt.
|
||||
mgf : callable
|
||||
A mask generation function that accepts two parameters: a string to
|
||||
use as seed, and the lenth of the mask to generate, in bytes.
|
||||
sLen : int
|
||||
Length of the salt, in bytes.
|
||||
|
||||
:Return: An ``emLen`` byte long string that encodes the hash
|
||||
(with ``emLen = \ceil(emBits/8)``).
|
||||
|
||||
:Raise ValueError:
|
||||
When digest or salt length are too big.
|
||||
"""
|
||||
|
||||
emLen = ceil_div(emBits, 8)
|
||||
|
||||
# Bitmask of digits that fill up
|
||||
lmask = 0
|
||||
for i in iter_range(8*emLen-emBits):
|
||||
lmask = lmask >> 1 | 0x80
|
||||
|
||||
# Step 1 and 2 have been already done
|
||||
# Step 3
|
||||
if emLen < mhash.digest_size+sLen+2:
|
||||
raise ValueError("Digest or salt length are too long"
|
||||
" for given key size.")
|
||||
# Step 4
|
||||
salt = randFunc(sLen)
|
||||
# Step 5
|
||||
m_prime = bchr(0)*8 + mhash.digest() + salt
|
||||
# Step 6
|
||||
h = mhash.new()
|
||||
h.update(m_prime)
|
||||
# Step 7
|
||||
ps = bchr(0)*(emLen-sLen-mhash.digest_size-2)
|
||||
# Step 8
|
||||
db = ps + bchr(1) + salt
|
||||
# Step 9
|
||||
dbMask = mgf(h.digest(), emLen-mhash.digest_size-1)
|
||||
# Step 10
|
||||
maskedDB = strxor(db, dbMask)
|
||||
# Step 11
|
||||
maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:]
|
||||
# Step 12
|
||||
em = maskedDB + h.digest() + bchr(0xBC)
|
||||
return em
|
||||
|
||||
|
||||
def _EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
|
||||
"""
|
||||
Implement the ``EMSA-PSS-VERIFY`` function, as defined
|
||||
in PKCS#1 v2.1 (RFC3447, 9.1.2).
|
||||
|
||||
``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input,
|
||||
and hash it internally. Here, we expect that the message has already
|
||||
been hashed instead.
|
||||
|
||||
:Parameters:
|
||||
mhash : hash object
|
||||
The hash object that holds the digest of the message to be verified.
|
||||
em : string
|
||||
The signature to verify, therefore proving that the sender really
|
||||
signed the message that was received.
|
||||
emBits : int
|
||||
Length of the final encoding (em), in bits.
|
||||
mgf : callable
|
||||
A mask generation function that accepts two parameters: a string to
|
||||
use as seed, and the lenth of the mask to generate, in bytes.
|
||||
sLen : int
|
||||
Length of the salt, in bytes.
|
||||
|
||||
:Raise ValueError:
|
||||
When the encoding is inconsistent, or the digest or salt lengths
|
||||
are too big.
|
||||
"""
|
||||
|
||||
emLen = ceil_div(emBits, 8)
|
||||
|
||||
# Bitmask of digits that fill up
|
||||
lmask = 0
|
||||
for i in iter_range(8*emLen-emBits):
|
||||
lmask = lmask >> 1 | 0x80
|
||||
|
||||
# Step 1 and 2 have been already done
|
||||
# Step 3
|
||||
if emLen < mhash.digest_size+sLen+2:
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 4
|
||||
if ord(em[-1:]) != 0xBC:
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 5
|
||||
maskedDB = em[:emLen-mhash.digest_size-1]
|
||||
h = em[emLen-mhash.digest_size-1:-1]
|
||||
# Step 6
|
||||
if lmask & bord(em[0]):
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 7
|
||||
dbMask = mgf(h, emLen-mhash.digest_size-1)
|
||||
# Step 8
|
||||
db = strxor(maskedDB, dbMask)
|
||||
# Step 9
|
||||
db = bchr(bord(db[0]) & ~lmask) + db[1:]
|
||||
# Step 10
|
||||
if not db.startswith(bchr(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)):
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 11
|
||||
if sLen > 0:
|
||||
salt = db[-sLen:]
|
||||
else:
|
||||
salt = b""
|
||||
# Step 12
|
||||
m_prime = bchr(0)*8 + mhash.digest() + salt
|
||||
# Step 13
|
||||
hobj = mhash.new()
|
||||
hobj.update(m_prime)
|
||||
hp = hobj.digest()
|
||||
# Step 14
|
||||
if h != hp:
|
||||
raise ValueError("Incorrect signature")
|
||||
|
||||
|
||||
def new(rsa_key, **kwargs):
|
||||
"""Create an object for making or verifying PKCS#1 PSS signatures.
|
||||
|
||||
:parameter rsa_key:
|
||||
The RSA key to use for signing or verifying the message.
|
||||
This is a :class:`Crypto.PublicKey.RSA` object.
|
||||
Signing is only possible when ``rsa_key`` is a **private** RSA key.
|
||||
:type rsa_key: RSA object
|
||||
|
||||
:Keyword Arguments:
|
||||
|
||||
* *mask_func* (``callable``) --
|
||||
A function that returns the mask (as `bytes`).
|
||||
It must accept two parameters: a seed (as `bytes`)
|
||||
and the length of the data to return.
|
||||
|
||||
If not specified, it will be the function :func:`MGF1` defined in
|
||||
`RFC8017 <https://tools.ietf.org/html/rfc8017#page-67>`_ and
|
||||
combined with the same hash algorithm applied to the
|
||||
message to sign or verify.
|
||||
|
||||
If you want to use a different function, for instance still :func:`MGF1`
|
||||
but together with another hash, you can do::
|
||||
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Signature.pss import MGF1
|
||||
mgf = lambda x, y: MGF1(x, y, SHA256)
|
||||
|
||||
* *salt_bytes* (``integer``) --
|
||||
Length of the salt, in bytes.
|
||||
It is a value between 0 and ``emLen - hLen - 2``, where ``emLen``
|
||||
is the size of the RSA modulus and ``hLen`` is the size of the digest
|
||||
applied to the message to sign or verify.
|
||||
|
||||
The salt is generated internally, you don't need to provide it.
|
||||
|
||||
If not specified, the salt length will be ``hLen``.
|
||||
If it is zero, the signature scheme becomes deterministic.
|
||||
|
||||
Note that in some implementations such as OpenSSL the default
|
||||
salt length is ``emLen - hLen - 2`` (even though it is not more
|
||||
secure than ``hLen``).
|
||||
|
||||
* *rand_func* (``callable``) --
|
||||
A function that returns random ``bytes``, of the desired length.
|
||||
The default is :func:`Crypto.Random.get_random_bytes`.
|
||||
|
||||
:return: a :class:`PSS_SigScheme` signature object
|
||||
"""
|
||||
|
||||
mask_func = kwargs.pop("mask_func", None)
|
||||
salt_len = kwargs.pop("salt_bytes", None)
|
||||
rand_func = kwargs.pop("rand_func", None)
|
||||
if rand_func is None:
|
||||
rand_func = Random.get_random_bytes
|
||||
if kwargs:
|
||||
raise ValueError("Unknown keywords: " + str(kwargs.keys()))
|
||||
return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func)
|
30
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pss.pyi
vendored
Normal file
30
week05/easy/env/lib/python3.12/site-packages/Crypto/Signature/pss.pyi
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
from typing import Union, Callable, Optional
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
|
||||
|
||||
class Hash(Protocol):
|
||||
def digest(self) -> bytes: ...
|
||||
def update(self, bytes) -> None: ...
|
||||
|
||||
|
||||
class HashModule(Protocol):
|
||||
@staticmethod
|
||||
def new(data: Optional[bytes]) -> Hash: ...
|
||||
|
||||
|
||||
MaskFunction = Callable[[bytes, int, Union[Hash, HashModule]], bytes]
|
||||
RndFunction = Callable[[int], bytes]
|
||||
|
||||
class PSS_SigScheme:
|
||||
def __init__(self, key: RsaKey, mgfunc: MaskFunction, saltLen: int, randfunc: RndFunction) -> None: ...
|
||||
def can_sign(self) -> bool: ...
|
||||
def sign(self, msg_hash: Hash) -> bytes: ...
|
||||
def verify(self, msg_hash: Hash, signature: bytes) -> None: ...
|
||||
|
||||
|
||||
MGF1 : MaskFunction
|
||||
def _EMSA_PSS_ENCODE(mhash: Hash, emBits: int, randFunc: RndFunction, mgf:MaskFunction, sLen: int) -> str: ...
|
||||
def _EMSA_PSS_VERIFY(mhash: Hash, em: str, emBits: int, mgf: MaskFunction, sLen: int) -> None: ...
|
||||
def new(rsa_key: RsaKey, **kwargs: Union[MaskFunction, RndFunction, int]) -> PSS_SigScheme: ...
|
Reference in New Issue
Block a user