Skip to content

Commit

Permalink
Update ECC docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Legrandin committed Jan 7, 2024
1 parent be2262e commit e83ef22
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 29 deletions.
44 changes: 28 additions & 16 deletions Doc/src/public_key/ecc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,34 @@ is significantly smaller at the same security level.
For instance, a 3072-bit RSA key takes 768 bytes whereas the equally strong NIST P-256
private key only takes 32 bytes (that is, 256 bits).

This module provides mechanisms for generating new ECC keys, exporting and importing them
using widely supported formats like PEM or DER.
With this module you can generate new ECC keys::

>>> from Crypto.PublicKey import ECC
>>>
>>> mykey = ECC.generate(curve='p256')

export an ECC private key and protect it with a password, so that it is
resistant to brute force attacks::

>>> pwd = b'secret'
>>> with open("myprivatekey.pem", "wt") as f:
>>> data = mykey.export_key(format='PEM'
passphrase=pwd,
protection='PBKDF2WithHMAC-SHA512AndAES256-CBC',
prot_params={'iteration_count':131072})
>>> f.write(data)

and reimport it later::

>>> pwd = b'secret'
>>> with open("myprivatekey.pem", "rt") as f:
>>> data = f.read()
>>> mykey = ECC.import_key(data, pwd)

You can also export the public key, which is not sensitive::

>>> with open("mypublickey.pem", "wbt) as f:
>>> data = mykey.public_key().export_key()

.. _ECC table:
.. csv-table::
Expand All @@ -32,20 +58,6 @@ 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_.

The following example demonstrates how to generate a new ECC key, export it,
and subsequently reload it back into the application::

>>> from Crypto.PublicKey import ECC
>>>
>>> key = ECC.generate(curve='P-256')
>>>
>>> f = open('myprivatekey.pem','wt')
>>> f.write(key.export_key(format='PEM'))
>>> f.close()
...
>>> f = open('myprivatekey.pem','rt')
>>> key = ECC.import_key(f.read())

The ECC key can be used to perform or verify signatures, using the modules
:mod:`Crypto.Signature.DSS` (ECDSA; NIST curves only)
or :mod:`Crypto.Signature.eddsa` (EdDSA; Ed25519 and Ed448 curve only).
Expand Down
4 changes: 2 additions & 2 deletions Doc/src/public_key/public_key.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ Available key types
:hidden:

rsa
dsa
ecc
dsa

* :doc:`RSA keys <rsa>`
* :doc:`DSA keys <dsa>`
* :doc:`Elliptic Curve keys <ecc>`
* :doc:`DSA keys (obsolete) <dsa>`

Obsolete key type
-----------------
Expand Down
2 changes: 1 addition & 1 deletion Doc/src/public_key/rsa.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ and reimport it later::
You can also export the public key, which is not sensitive::

>>> with open("mypublickey.pem", "wb") as f:
>>> data = mykey.public_key().export()
>>> data = mykey.public_key().export_key()

For signing data with RSA, use a higher level module such as :ref:`rsa_pss`.

Expand Down
38 changes: 28 additions & 10 deletions lib/Crypto/PublicKey/ECC.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ def _export_pkcs8(self, **kwargs):
from Crypto.IO import PKCS8

if kwargs.get('passphrase', None) is not None and 'protection' not in kwargs:
raise ValueError("At least the 'protection' parameter should be present")
raise ValueError("At least the 'protection' parameter must be present")

if self._is_eddsa():
oid = self._curve.oid
Expand Down Expand Up @@ -1041,7 +1041,7 @@ def export_key(self, **kwargs):
Args:
format (string):
The format to use for encoding the key:
The output format:
- ``'DER'``. The key will be encoded in ASN.1 DER format (binary).
For a public key, the ASN.1 ``subjectPublicKeyInfo`` structure
Expand All @@ -1062,20 +1062,25 @@ def export_key(self, **kwargs):
* For NIST P-curves: equivalent to ``'SEC1'``.
* For EdDSA curves: ``bytes`` in the format defined in `RFC8032`_.
passphrase (byte string or string):
The passphrase to use for protecting the private key.
passphrase (bytes or string):
(*Private keys only*) The passphrase to protect the
private key.
use_pkcs8 (boolean):
Only relevant for private keys.
(*Private keys only*)
If ``True`` (default and recommended), the `PKCS#8`_ representation
will be used. It must be ``True`` for EdDSA curves.
If ``False`` and a passphrase is present, the obsolete PEM
encryption will be used.
protection (string):
When a private key is exported with password-protection
and PKCS#8 (both ``DER`` and ``PEM`` formats), this parameter MUST be
present and be a valid algorithm supported by :mod:`Crypto.IO.PKCS8`.
It is recommended to use ``PBKDF2WithHMAC-SHA1AndAES128-CBC``.
present,
For all possible protection schemes,
refer to :ref:`the encryption parameters of PKCS#8<enc_params>`.
It is recommended to use ``'PBKDF2WithHMAC-SHA5126AndAES128-CBC'``.
compress (boolean):
If ``True``, the method returns a more compact representation
Expand All @@ -1086,6 +1091,16 @@ def export_key(self, **kwargs):
This parameter is ignored for EdDSA curves, as compression is
mandatory.
prot_params (dict):
When a private key is exported with password-protection
and PKCS#8 (both ``DER`` and ``PEM`` formats), this dictionary
contains the parameters to use to derive the encryption key
from the passphrase.
For all possible values,
refer to :ref:`the encryption parameters of PKCS#8<enc_params>`.
The recommendation is to use ``{'iteration_count':21000}`` for PBKDF2,
and ``{'iteration_count':131072}`` for scrypt.
.. warning::
If you don't provide a passphrase, the private key will be
exported in the clear!
Expand Down Expand Up @@ -1121,8 +1136,11 @@ def export_key(self, **kwargs):
raise ValueError("Empty passphrase")
use_pkcs8 = args.pop("use_pkcs8", True)

if not use_pkcs8 and self._is_eddsa():
raise ValueError("'pkcs8' must be True for EdDSA curves")
if not use_pkcs8:
if self._is_eddsa():
raise ValueError("'pkcs8' must be True for EdDSA curves")
if 'protection' in args:
raise ValueError("'protection' is only supported for PKCS#8")

if ext_format == "PEM":
if use_pkcs8:
Expand Down

0 comments on commit e83ef22

Please sign in to comment.