Skip to content

Commit

Permalink
Update the PKCS#8 documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Legrandin committed Jan 8, 2024
1 parent 8677775 commit a14a222
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 47 deletions.
98 changes: 82 additions & 16 deletions Doc/src/io/pkcs8.rst
Original file line number Diff line number Diff line change
@@ -1,28 +1,94 @@
PKCS#8
======

`PKCS#8`_ is a standard for storing and transferring private key information.
The wrapped key can either be clear or encrypted.
`PKCS#8`_ is a standard for encoding asymmetric private keys,
such as RSA or ECC, so that they can be stored or exchanged.
The private key can either be encrypted with a passphrase or
left in the clear.

All encryption algorithms are based on passphrase-based key derivation.
The following mechanisms are fully supported:
Example of how to encrypt an ECC private key (even though
normally you would use the ``export_key`` method of the key itself)::

* *PBKDF2WithHMAC-SHA1AndAES128-CBC*
* *PBKDF2WithHMAC-SHA1AndAES192-CBC*
* *PBKDF2WithHMAC-SHA1AndAES256-CBC*
* *PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC*
* *scryptAndAES128-CBC*
* *scryptAndAES192-CBC*
* *scryptAndAES256-CBC*
from Crypto.PublicKey import ECC
from Crypto.IO import PKCS8

The following mechanisms are only supported for importing keys.
key = ECC.generate(curve='p256')
pkey = key.export_key(format='DER'),
passphrase = b'secret santa'
encrypted_key = PKCS8.wrap(
pkey,
"1.2.840.10045.2.1", # unrestricted ECC
passphrase=passphrase,
protection='PBKDF2WithHMAC-SHA512AndAES256-CBC',
prot_params={'iteration_count': 210000}
)

.. _enc_params:

Encryption parameters
-----------------------

When creating an encrypted PKCS#8 container, the two parameters
``protection`` and ``prot_params`` drive the encryption algorithm:

* ``protection`` (mandatory), a string that defines how the encryption
key is derived from the passphrase, and which cipher to use.
The string must follow one of the two patterns:

#. ``'PBKDF2WithHMAC-'`` + **hash** + ``'And'`` + **cipher**
#. ``'scryptAnd'`` + **cipher**

where **hash** is the name of the cryptographic hash
(recommended: ``'SHA512'``) and **cipher** is the name
of the cipher mode to use (recommended: ``'AES256-CBC'``).

Other values for **hash** are ``'SHA1'``, ``'SHA224'``, ``'SHA256'``,
``'SHA384'``, ``'SHA512-224'``, ``'SHA512-256'``, ``'SHA3-224'``,
``'SHA3-256'``, ``'SHA3-384'``, ``'SHA3-512'``.

Other values for **cipher** are
``'AES128-GCM'``, ``'AES192-GCM'``, ``'AES256-GCM'``,
``'AES128-CBC'``, ``'AES192-CBC'`` or ``'DES-EDE3-CBC'``.

* ``prot_params`` (optional), a dictionary to override the parameters of the
key derivation function:

+------------------+-----------------------------------------------+
| Key | Description |
+==================+===============================================+
| iteration_count | The KDF algorithm is repeated several times to|
| | slow down brute force attacks on passwords |
| | (called *N* or CPU/memory cost in scrypt). |
| | |
| | **For PBKDF2 with SHA512 the recommended |
| | value is 210 000** (default is 1 000). |
| | |
| | **For scrypt the recommended value is |
| | 131 072** (default value is 16 384). |
+------------------+-----------------------------------------------+
| salt_size | Salt is used to thwart dictionary and rainbow |
| | attacks on passwords. The default value is 8 |
| | bytes. |
+------------------+-----------------------------------------------+
| block_size | *(scrypt only)* Memory-cost (r). The default |
| | value is 8. |
+------------------+-----------------------------------------------+
| parallelization | *(scrypt only)* CPU-cost (p). The default |
| | value is 1. |
+------------------+-----------------------------------------------+


Legacy algorithms
-----------------

The following ``protection`` mechanisms are only supported for importing keys.
They are much weaker than the ones listed above, and they are provided
for backward compatibility only:

* *pbeWithMD5AndRC2-CBC*
* *pbeWithMD5AndDES-CBC*
* *pbeWithSHA1AndRC2-CBC*
* *pbeWithSHA1AndDES-CBC*
* ``pbeWithMD5AndRC2-CBC``
* ``pbeWithMD5AndDES-CBC``
* ``pbeWithSHA1AndRC2-CBC``
* ``pbeWithSHA1AndDES-CBC``

.. _`PKCS#8`: http://www.ietf.org/rfc/rfc5208.txt

Expand Down
49 changes: 18 additions & 31 deletions lib/Crypto/IO/PKCS8.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,44 +53,29 @@ def wrap(private_key, key_oid, passphrase=None, protection=None,
Args:
private_key (byte string):
private_key (bytes):
The private key encoded in binary form. The actual encoding is
algorithm specific. In most cases, it is DER.
key_oid (string):
The object identifier (OID) of the private key to wrap.
It is a dotted string, like ``1.2.840.113549.1.1.1`` (for RSA keys).
It is a dotted string, like ``'1.2.840.113549.1.1.1'`` (for RSA keys)
or ``'1.2.840.10045.2.1'`` (for ECC keys).
passphrase (bytes string or string):
Keyword Args:
passphrase (bytes or string):
The secret passphrase from which the wrapping key is derived.
Set it only if encryption is required.
protection (string):
The identifier of the algorithm to use for securely wrapping the key.
The default value is ``PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC``.
Refer to :ref:`the encryption parameters<enc_params>` .
The default value is ``'PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC'``.
prot_params (dictionary):
Parameters for the protection algorithm.
+------------------+-----------------------------------------------+
| Key | Description |
+==================+===============================================+
| iteration_count | The KDF algorithm is repeated several times to|
| | slow down brute force attacks on passwords |
| | (called *N* or CPU/memory cost in scrypt). |
| | The default value for PBKDF2 is 1000. |
| | The default value for scrypt is 16384. |
+------------------+-----------------------------------------------+
| salt_size | Salt is used to thwart dictionary and rainbow |
| | attacks on passwords. The default value is 8 |
| | bytes. |
+------------------+-----------------------------------------------+
| block_size | *(scrypt only)* Memory-cost (r). The default |
| | value is 8. |
+------------------+-----------------------------------------------+
| parallelization | *(scrypt only)* CPU-cost (p). The default |
| | value is 1. |
+------------------+-----------------------------------------------+
Parameters for the key derivation function (KDF).
Refer to :ref:`the encryption parameters<enc_params>` .
key_params (DER object or None):
The ``parameters`` field to use in the ``AlgorithmIdentifier``
Expand All @@ -103,8 +88,8 @@ def wrap(private_key, key_oid, passphrase=None, protection=None,
If not specified, a new RNG will be instantiated
from :mod:`Crypto.Random`.
Return:
The PKCS#8-wrapped private key (possibly encrypted), as a byte string.
Returns:
bytes: The PKCS#8-wrapped private key (possibly encrypted).
"""

#
Expand Down Expand Up @@ -145,17 +130,19 @@ def unwrap(p8_private_key, passphrase=None):
"""Unwrap a private key from a PKCS#8 blob (clear or encrypted).
Args:
p8_private_key (byte string):
The private key wrapped into a PKCS#8 blob, DER encoded.
p8_private_key (bytes):
The private key wrapped into a PKCS#8 container, DER encoded.
Keyword Args:
passphrase (byte string or string):
The passphrase to use to decrypt the blob (if it is encrypted).
Return:
A tuple containing
#. the algorithm identifier of the wrapped key (OID, dotted string)
#. the private key (byte string, DER encoded)
#. the associated parameters (byte string, DER encoded) or ``None``
#. the private key (bytes, DER encoded)
#. the associated parameters (bytes, DER encoded) or ``None``
Raises:
ValueError : if decoding fails
Expand Down

0 comments on commit a14a222

Please sign in to comment.