Skip to content

Commit

Permalink
Merge branch 'x448'
Browse files Browse the repository at this point in the history
  • Loading branch information
Legrandin committed Sep 8, 2024
2 parents e42fd29 + d60d018 commit ccf67d6
Show file tree
Hide file tree
Showing 55 changed files with 2,074 additions and 280 deletions.
1 change: 1 addition & 0 deletions Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Under development
* GH#814: RSA keys for PSS can be imported.
* GH#810: fixed negation of Ed25519 points
* Add support for Curve25519 / X25519
* Add support for Curve448 / X448
* Add attribute ``curve`` to EccPoint and EccXPoint classes,
with the canonical name of the curve.
* GH#781: the label for the SP800_108_Counter KDF may now
Expand Down
2 changes: 1 addition & 1 deletion Doc/src/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ A list of useful resources in that area can be found on `Matthew Green's blog`_.
* Asymmetric key generation:

- RSA
- ECC (NIST P-curves; Ed25519, Ed448)
- ECC (NIST P-curves; Ed25519, Ed448, Curve25519, Curve448)
- DSA
- ElGamal (legacy)

Expand Down
5 changes: 3 additions & 2 deletions Doc/src/public_key/ecc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ You can also export the public key, which is not sensitive::
"Ed25519", "``'Ed25519'``", "``'ed25519'``"
"Ed448", "``'Ed448'``", "``'ed448'``"
"Curve25519", "``'Curve25519'``", "``'curve25519'``"
"Curve448", "``'Curve448'``", "``'curve448'``"

For more information about each NIST curve see `FIPS 186-4`_, Section D.1.2.

The Ed25519 and the Ed448 curves are defined in RFC8032_.
Curves Ed25519 and Ed448 are defined in RFC8032_.

The Curve25519 curve is defined in RFC7748_.
Curves Curve25519 and Curve448 are defined in RFC7748_.

The ECC keys can be used to perform or verify signatures, using the modules
:mod:`Crypto.Signature.DSS` (ECDSA; NIST curves only)
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ with respect to the last official version of PyCrypto (2.6.1):
* Authenticated encryption modes (GCM, CCM, EAX, SIV, OCB)
* Accelerated AES on Intel platforms via AES-NI
* First class support for PyPy
* Elliptic curves cryptography (NIST P-curves; Ed25519, Ed448, Curve25519)
* Elliptic curves cryptography (NIST P-curves; Ed25519, Ed448, Curve25519, Curve448)
* Better and more compact API (`nonce` and `iv` attributes for ciphers,
automatic generation of random nonces and IVs, simplified CTR cipher mode,
and more)
Expand Down
46 changes: 45 additions & 1 deletion lib/Crypto/Protocol/DH.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from Crypto.Util.number import long_to_bytes
from Crypto.PublicKey.ECC import (EccKey,
construct,
_import_curve25519_public_key)
_import_curve25519_public_key,
_import_curve448_public_key)


def _compute_ecdh(key_priv, key_pub):
Expand All @@ -11,6 +12,8 @@ def _compute_ecdh(key_priv, key_pub):

if key_priv.curve == "Curve25519":
z = bytearray(pointP.x.to_bytes(32, byteorder='little'))
elif key_priv.curve == "Curve448":
z = bytearray(pointP.x.to_bytes(56, byteorder='little'))
else:
# See Section 5.7.1.2 in NIST SP 800-56Ar3
z = long_to_bytes(pointP.x, pointP.size_in_bytes())
Expand Down Expand Up @@ -58,6 +61,47 @@ def import_x25519_private_key(encoded):
return construct(seed=encoded, curve="Curve25519")


def import_x448_public_key(encoded):
"""Create a new X448 public key object,
starting from the key encoded as raw ``bytes``,
in the format described in RFC7748.
Args:
encoded (bytes):
The x448 public key to import.
It must be 56 bytes.
Returns:
:class:`Crypto.PublicKey.EccKey` : a new ECC key object.
Raises:
ValueError: when the given key cannot be parsed.
"""

x = _import_curve448_public_key(encoded)
return construct(curve='Curve448', point_x=x)


def import_x448_private_key(encoded):
"""Create a new X448 private key object,
starting from the key encoded as raw ``bytes``,
in the format described in RFC7748.
Args:
encoded (bytes):
The X448 private key to import.
It must be 56 bytes.
Returns:
:class:`Crypto.PublicKey.EccKey` : a new ECC key object.
Raises:
ValueError: when the given key cannot be parsed.
"""

return construct(seed=encoded, curve="Curve448")


def key_agreement(**kwargs):
"""Perform a Diffie-Hellman key agreement.
Expand Down
2 changes: 2 additions & 0 deletions lib/Crypto/Protocol/DH.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ class RequestParams(TypedDict, Generic[T]):

def import_x25519_public_key(encoded: bytes) -> EccKey: ...
def import_x25519_private_key(encoded: bytes) -> EccKey: ...
def import_x448_public_key(encoded: bytes) -> EccKey: ...
def import_x448_private_key(encoded: bytes) -> EccKey: ...
def key_agreement(**kwargs: Unpack[RequestParams[T]]) -> T: ...
Loading

0 comments on commit ccf67d6

Please sign in to comment.