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.name == "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.name == "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 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.name == "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.name == "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 update(self, data): """Authenticate the next byte string in the tuple. Args: data (bytes/bytearray/memoryview): The next byte string. """ if self._digest is not None: raise TypeError( "You cannot call 'update' after 'digest' or 'hexdigest'") if not is_bytes(data): raise TypeError("You can only call 'update' on bytes") self._cshake.update(_encode_str(tobytes(data))) return self
def new(**kwargs): """Create a new KMAC256 object. Args: key (bytes/bytearray/memoryview): The key to use to compute the MAC. It must be at least 256 bits long (32 bytes). data (bytes/bytearray/memoryview): Optional. The very first chunk of the message to authenticate. It is equivalent to an early call to :meth:`KMAC_Hash.update`. mac_len (integer): Optional. The size of the authentication tag, in bytes. Default is 64. Minimum is 8. custom (bytes/bytearray/memoryview): Optional. A customization byte string (``S`` in SP 800-185). Returns: A :class:`KMAC_Hash` hash object """ key = kwargs.pop("key", None) if not is_bytes(key): raise TypeError("You must pass a key to KMAC256") if len(key) < 32: raise ValueError("The key must be at least 256 bits long (32 bytes)") data = kwargs.pop("data", None) mac_len = kwargs.pop("mac_len", 64) if mac_len < 8: raise ValueError("'mac_len' must be 8 bytes or more") custom = kwargs.pop("custom", b"") if kwargs: raise TypeError("Unknown parameters: " + str(kwargs)) return KMAC_Hash(data, key, mac_len, custom, "20", cSHAKE256, 136)
def decrypt(self, ciphertext, sentinel, expected_pt_len=0): r"""Decrypt a PKCS#1 v1.5 ciphertext. This is the function ``RSAES-PKCS1-V1_5-DECRYPT`` specified in `section 7.2.2 of RFC8017 <https://tools.ietf.org/html/rfc8017#page-29>`_. Args: ciphertext (bytes/bytearray/memoryview): The ciphertext that contains the message to recover. sentinel (any type): The object to return whenever an error is detected. expected_pt_len (integer): The length the plaintext is known to have, or 0 if unknown. Returns (byte string): It is either the original message or the ``sentinel`` (in case of an error). .. warning:: PKCS#1 v1.5 decryption is intrinsically vulnerable to timing attacks (see `Bleichenbacher's`__ attack). **Use PKCS#1 OAEP instead**. This implementation attempts to mitigate the risk with some constant-time constructs. However, they are not sufficient by themselves: the type of protocol you implement and the way you handle errors make a big difference. Specifically, you should make it very hard for the (malicious) party that submitted the ciphertext to quickly understand if decryption succeeded or not. To this end, it is recommended that your protocol only encrypts plaintexts of fixed length (``expected_pt_len``), that ``sentinel`` is a random byte string of the same length, and that processing continues for as long as possible even if ``sentinel`` is returned (i.e. in case of incorrect decryption). .. __: http://www.bell-labs.com/user/bleichen/papers/pkcs.ps """ # See 7.2.2 in RFC8017 k = self._key.size_in_bytes() # Step 1 if len(ciphertext) != k: raise ValueError( "Ciphertext with incorrect length (not %d bytes)" % k) # Step 2a (O2SIP) ct_int = bytes_to_long(ciphertext) # Step 2b (RSADP) m_int = self._key._decrypt(ct_int) # Complete step 2c (I2OSP) em = long_to_bytes(m_int, k) # Step 3 (not constant time when the sentinel is not a byte string) output = bytearray(k) if not is_bytes(sentinel) or len(sentinel) > k: size = _pkcs1_decode(em, b'', expected_pt_len, output) if size < 0: return sentinel else: return output[size:] # Step 3 (somewhat constant time) size = _pkcs1_decode(em, sentinel, expected_pt_len, output) return output[size:]