Internet-Draft | PQC in OpenPGP | July 2023 |
Kousidis, et al. | Expires 11 January 2024 | [Page] |
This document defines a post-quantum public-key algorithm extension for the OpenPGP protocol. Given the generally assumed threat of a cryptographically relevant quantum computer, this extension provides a basis for long-term secure OpenPGP signatures and ciphertexts. Specifically, it defines composite public-key encryption based on CRYSTALS-Kyber, composite public-key signatures based on CRYSTALS-Dilithium, both in combination with elliptic curve cryptography, and SPHINCS+ as a standalone public key signature scheme.¶
This note is to be removed before publishing as an RFC.¶
Status information for this document may be found at https://datatracker.ietf.org/doc/draft-wussler-openpgp-pqc/.¶
Discussion of this document takes place on the WG Working Group mailing list (mailto:openpgp@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/openpgp/. Subscribe at https://www.ietf.org/mailman/listinfo/openpgp/.¶
Source for this draft and an issue tracker can be found at https://github.com/openpgp-pqc/draft-openpgp-pqc.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 11 January 2024.¶
Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The OpenPGP protocol supports various traditional public-key algorithms based on the factoring or discrete logarithm problem. As the security of algorithms based on these mathematical problems is endangered by the advent of quantum computers, there is a need to extend OpenPGP by algorithms that remain secure in the presence of quantum computers.¶
Such cryptographic algorithms are referred to as post-quantum cryptography. The algorithms defined in this extension were chosen for standardization by the National Institute of Standards and Technology (NIST) in mid 2022 [NISTIR-8413] as the result of the NIST Post-Quantum Cryptography Standardization process initiated in 2016 [NIST-PQC]. Namely, these are CRYSTALS-Kyber as a Key Encapsulation Mechanism (KEM), a KEM being a modern building block for public-key encryption, and CRYSTALS-Dilithium as well as SPHINCS+ as signature schemes.¶
For the two CRYSTALS-* schemes, this document follows the conservative strategy to deploy post-quantum in combination with traditional schemes such that the security is retained even if all schemes but one in the combination are broken. In contrast, the hashed-based signature scheme SPHINCS+ is considered to be sufficiently well understood with respect to its security assumptions in order to be used standalone. To this end, this document specifies the following new set: SPHINCS+ standalone and CRYSTALS-* as composite with ECC-based KEM and digital signature schemes. Here, the term "composite" indicates that any data structure or algorithm pertaining to the combination of the two components appears as single data structure or algorithm from the protocol perspective.¶
The document specifies the conventions for interoperability between compliant OpenPGP implementations that make use of this extension and the newly defined algorithms or algorithm combinations.¶
The terminology in this document is oriented towards the definitions in [draft-driscoll-pqt-hybrid-terminology]. Specifically, the terms "multi-algorithm", "composite" and "non-composite" are used in correspondence with the definitions therein. The abbreviation "PQ" is used for post-quantum schemes. To denote the combination of post-quantum and traditional schemes, the abbreviation "PQ/T" is used. The short form "PQ(/T)" stands for PQ or PQ/T.¶
This section describes the individual post-quantum cryptographic schemes. All schemes listed here are believed to provide security in the presence of a cryptographically relevant quantum computer. However, the mathematical problems on which the two CRYSTALS-* schemes and SPHINCS+ are based, are fundamentally different, and accordingly the level of trust commonly placed in them as well as their performance characteristics vary.¶
[Note to the reader: This specification refers to the latest NIST submission papers of each scheme as if it were a specification. This is a temporary solution that is owed to the fact that currently no other specification is available. The goal is to provide a sufficiently precise specification of the algorithms already at the draft stage of this specification, so that it is possible for implementers to create interoperable implementations. As soon as standards by NIST or the IETF for the PQC schemes employed in this specification are available, these will replace the references to the NIST submission papers. Furthermore, we want to point out that, depending on possible changes to the schemes standardized by NIST, this specification may be updated substantially as soon as corresponding information becomes available.]¶
CRYSTALS-Kyber [KYBER-Subm] is based on the hardness of solving the learning-with-errors problem in module lattices (MLWE). The scheme is believed to provide security against cryptanalytic attacks by classical as well as quantum computers. This specification defines CRYSTALS-Kyber only in composite combination with ECC-based encryption schemes in order to provide a pre-quantum security fallback.¶
CRYSTALS-Dilithium, defined in [DILITHIUM-Subm], is a signature scheme that, like CRYSTALS-Kyber, is based on the hardness of solving lattice problems in module lattices. Accordingly, this specification only defines CRYSTALS-Dilithium in composite combination with ECC-based signature schemes.¶
SPHINCS+ [SPHINCS-Subm] is a stateless hash-based signature scheme. Its security relies on the hardness of finding preimages for cryptographic hash functions. This feature is generally considered to be a high security guarantee. Therefore, this specification defines SPHINCS+ as a standalone signature scheme.¶
In deployments the performance characteristics of SPHINCS+ should be taken into account. We refer to Section 10.1 for a discussion of the performance characteristics of this scheme.¶
The ECC-based encryption is defined here as a KEM. This is in contrast to [I-D.ietf-openpgp-crypto-refresh] where the ECC-based encryption is defined as a public-key encryption scheme.¶
All elliptic curves for the use in the composite combinations are taken from [I-D.ietf-openpgp-crypto-refresh]. However, as explained in the following, in the case of Curve25519 encoding changes are applied to the new composite schemes.¶
Curve25519 and Curve448 are defined in [RFC7748] for use in a Diffie-Hellman key agreement scheme and defined in [RFC8032] for use in a digital signature scheme. For Curve25519 this specification adapts the encoding of objects as defined in [RFC7748] in contrast to [I-D.ietf-openpgp-crypto-refresh].¶
For interoperability this extension offers CRYSTALS-* in composite combinations with the NIST curves P-256, P-384 defined in [SP800-186] and the Brainpool curves brainpoolP256r1, brainpoolP384r1 defined in [RFC5639].¶
This section provides a categorization of the new algorithms and their combinations.¶
This specification introduces new cryptographic schemes, which can be categorized as follows:¶
For each of the composite schemes, this specification mandates that the recipient has to successfully perform the cryptographic algorithms for each of the component schemes used in a cryptrographic message, in order for the message to be deciphered and considered as valid. This means that all component signatures must be verified successfully in order to achieve a successful verification of the composite signature. In the case of the composite public-key decryption, each of the component KEM decapsulation operations must succeed.¶
As the OpenPGP protocol [I-D.ietf-openpgp-crypto-refresh] allows for multiple signatures to be applied to a single message, it is also possible to realize non-composite combinations of signatures. Furthermore, multiple OpenPGP signatures may be combined on the application layer. These latter two cases realize non-composite combinations of signatures. Section 4.4 specifies how implementations should handle the verification of such combinations of signatures.¶
Furthermore, the OpenPGP protocol also allows for parallel encryption to different keys held by the same recipient. Accordingly, if the sender makes use of this feature and sends an encrypted message with multiple PKESK packages for different encryption keys held by the same recipient, a non-composite multi-algorithm public-key encryption is realized where the recipient has to decrypt only one of the PKESK packages in order to decrypt the message. See Section 4.2 for restrictions on parallel encryption mandated by this specification.¶
This section provides some preliminaries for the definitions in the subsequent sections.¶
Elliptic curve points of the generic prime curves are encoded using the SEC1 (uncompressed) format as the following octet string:¶
B = 04 || X || Y¶
where X
and Y
are coordinates of the elliptic curve point P = (X, Y)
, and
each coordinate is encoded in the big-endian format and zero-padded to the
adjusted underlying field size. The adjusted underlying field size is the
underlying field size rounded up to the nearest 8-bit boundary, as noted in the
"Field size" column in Table 6,
Table 7, or Table 11. This encoding is
compatible with the definition given in [SEC1].¶
In the following measures are described that ensure secure implementations according to existing best practices and standards defining the operations of Elliptic Curve Cryptography.¶
Even though the zero point, also called the point at infinity, may occur as a result of arithmetic operations on points of an elliptic curve, it MUST NOT appear in any ECC data structure defined in this document.¶
Furthermore, when performing the explicitly listed operations in Section 5.1.1.1, Section 5.1.1.2 or Section 5.1.1.3 it is REQUIRED to follow the specification and security advisory mandated from the respective elliptic curve specification.¶
This section specifies the composite Kyber + ECC and Dilithium + ECC schemes as well as the standalone SPHINCS+ signature scheme. The composite schemes are fully specified via their algorithm ID. The SPHINCS+ signature schemes are fully specified by their algorithm ID and an additional parameter ID.¶
For encryption, the following composite KEM schemes are specified:¶
ID | Algorithm | Requirement | Definition |
---|---|---|---|
29 | Kyber768 + X25519 | MUST | Section 5.2 |
30 | Kyber1024 + X448 | SHOULD | Section 5.2 |
31 | Kyber768 + ECDH-NIST-P-256 | MAY | Section 5.2 |
32 | Kyber1024 + ECDH-NIST-P-384 | MAY | Section 5.2 |
33 | Kyber768 + ECDH-brainpoolP256r1 | MAY | Section 5.2 |
34 | Kyber1024 + ECDH-brainpoolP384r1 | MAY | Section 5.2 |
For signatures, the following (composite) signature schemes are specified:¶
ID | Algorithm | Requirement | Definition |
---|---|---|---|
35 | Dilithium3 + Ed25519 | MUST | Section 6.2 |
36 | Dilithium5 + Ed448 | SHOULD | Section 6.2 |
37 | Dilithium3 + ECDSA-NIST-P-256 | MAY | Section 6.2 |
38 | Dilithium5 + ECDSA-NIST-P-384 | MAY | Section 6.2 |
39 | Dilithium3 + ECDSA-brainpoolP256r1 | MAY | Section 6.2 |
40 | Dilithium5 + ECDSA-brainpoolP384r1 | MAY | Section 6.2 |
41 | SPHINCS+-simple-SHA2 | SHOULD | Section 1.2.3 |
42 | SPHINCS+-simple-SHAKE | MAY | Section 1.2.3 |
For the SPHINCS+-simple-SHA2 signature algorithm from Table 2, the following parameters are specified:¶
Parameter ID | Parameter |
---|---|
1 | SPHINCS+-simple-SHA2-128s |
2 | SPHINCS+-simple-SHA2-128f |
3 | SPHINCS+-simple-SHA2-192s |
4 | SPHINCS+-simple-SHA2-192f |
5 | SPHINCS+-simple-SHA2-256s |
6 | SPHINCS+-simple-SHA2-256f |
All security parameters inherit the requirement of SPHINCS+-simple-SHA2 from
Table 2. That is, implementations SHOULD implement the parameters
specified in Table 3. The values 0x00
and 0xFF
are reserved
for future extensions.¶
For the SPHINCS+-simple-SHAKE signature algorithm from Table 2, the following parameters are specified:¶
Parameter ID | Parameter |
---|---|
1 | SPHINCS+-simple-SHAKE-128s |
2 | SPHINCS+-simple-SHAKE-128f |
3 | SPHINCS+-simple-SHAKE-192s |
4 | SPHINCS+-simple-SHAKE-192f |
5 | SPHINCS+-simple-SHAKE-256s |
6 | SPHINCS+-simple-SHAKE-256f |
All security parameters inherit the requirement of SPHINCS+-simple-SHAKE from
Table 2. That is, implementations MAY implement the parameters
specified in Table 4. The values 0x00
and 0xFF
are reserved
for future extensions.¶
Kyber + ECC public-key encryption is meant to involve both the Kyber KEM and an ECC-based KEM in an a priori non-separable manner. This is achieved via KEM combination, i.e. both key encapsulations/decapsulations are performed in parallel, and the resulting key shares are fed into a key combiner to produce a single shared secret for message encryption.¶
As explained in Section 1.4.2, the OpenPGP protocol inherently supports parallel encryption to different keys of the same recipient. Implementations MUST NOT encrypt a message with a purely traditional public-key encryption key of a recipient if it is encrypted with a PQ/T key of the same recipient.¶
Dilithium + ECC signatures are meant to contain both the Dilithium and the ECC signature data, and an implementation MUST validate both algorithms to state that a signature is valid.¶
The OpenPGP message format allows multiple signatures of a message, i.e. the attachment of multiple signature packets.¶
An implementation MAY sign a message with a traditional key and a PQ(/T) key from the same sender. This ensures backwards compatibility due to [I-D.ietf-openpgp-crypto-refresh] Section 5.2.5, since a legacy implementation without PQ(/T) support can fall back on the traditional signature.¶
Newer implementations with PQ(/T) support MAY ignore the traditional signature(s) during validation.¶
Implementations SHOULD consider the message correctly signed if at least one of the non-ignored signatures validates successfully.¶
[Note to the reader: The last requirement, that one valid signature is sufficient to identify a message as correctly signed, is an interpretation of [I-D.ietf-openpgp-crypto-refresh] Section 5.2.5.]¶
In this section we define the encryption, decryption, and data formats for the ECDH component of the composite algorithms.¶
Table 5, Table 6, and Table 7 describe the ECC-KEM parameters and artifact lengths. The artefacts in Table 5 follow the encodings described in [RFC7748].¶
X25519 | X448 | |
---|---|---|
Algorithm ID reference | 29 | 30 |
Field size | 32 octets | 56 octets |
ECC-KEM | x25519Kem (Section 5.1.1.1) | x448Kem (Section 5.1.1.2) |
ECDH public key | 32 octets [RFC7748] | 56 octets [RFC7748] |
ECDH secret key | 32 octets [RFC7748] | 56 octets [RFC7748] |
ECDH ephemeral | 32 octets [RFC7748] | 56 octets [RFC7748] |
ECDH share | 32 octets [RFC7748] | 56 octets [RFC7748] |
Key share | 32 octets | 64 octets |
Hash | SHA3-256 | SHA3-512 |
NIST P-256 | NIST P-384 | |
---|---|---|
Algorithm ID reference | 31 | 32 |
Field size | 32 octets | 48 octets |
ECC-KEM | ecdhKem (Section 5.1.1.3) | ecdhKem (Section 5.1.1.3) |
ECDH public key | 65 octets of SEC1-encoded public point | 97 octets of SEC1-encoded public point |
ECDH secret key | 32 octets big-endian encoded secret scalar | 48 octets big-endian encoded secret scalar |
ECDH ephemeral | 65 octets of SEC1-encoded ephemeral point | 97 octets of SEC1-encoded ephemeral point |
ECDH share | 65 octets of SEC1-encoded shared point | 97 octets of SEC1-encoded shared point |
Key share | 32 octets | 64 octets |
Hash | SHA3-256 | SHA3-512 |
brainpoolP256r1 | brainpoolP384r1 | |
---|---|---|
Algorithm ID reference | 33 | 34 |
Field size | 32 octets | 48 octets |
ECC-KEM | ecdhKem (Section 5.1.1.3) | ecdhKem (Section 5.1.1.3) |
ECDH public key | 65 octets of SEC1-encoded public point | 97 octets of SEC1-encoded public point |
ECDH secret key | 32 octets big-endian encoded secret scalar | 48 octets big-endian encoded secret scalar |
ECDH ephemeral | 65 octets of SEC1-encoded ephemeral point | 97 octets of SEC1-encoded ephemeral point |
ECDH share | 65 octets of SEC1-encoded shared point | 97 octets of SEC1-encoded shared point |
Key share | 32 octets | 64 octets |
Hash | SHA3-256 | SHA3-512 |
The SEC1 format for point encoding is defined in Section 2.1.1.¶
The various procedures to perform the operations of an ECC-based KEM are defined in the following subsections. Specifically, each of these subsections defines the instances of the following operations:¶
(eccCipherText, eccKeyShare) <- eccKem.encap(eccPublicKey)¶
and¶
(eccKeyShare) <- eccKem.decap(eccPrivateKey, eccCipherText)¶
The placeholder eccKem
has to be replaced with the specific ECC-KEM from the
row "ECC-KEM" of Table 5, Table 6, and
Table 7.¶
The encapsulation and decapsulation operations of x25519kem
are described
using the function X25519()
and encodings defined in [RFC7748]. The
eccPrivateKey
is denoted as r
, the eccPublicKey
as R
, they are subject
to the equation R = X25519(r, U(P))
. Here, U(P)
denotes the u-coordinate of
the base point of Curve25519.¶
The operation x25519Kem.encap()
is defined as follows:¶
v
, V
} via V = X25519(v,U(P))
where v
is a random scalar¶
X = X25519(v, R)
where R
is the public key
eccPublicKey
¶
eccCipherText
to V
¶
eccKeyShare
to SHA3-256(X || eccCipherText || eccPublicKey)
¶
The operation x25519Kem.decap()
is defined as follows:¶
The encapsulation and decapsulation operations of x448kem
are described using
the function X448()
and encodings defined in [RFC7748]. The eccPrivateKey
is denoted as r
, the eccPublicKey
as R
, they are subject to the equation
R = X25519(r, U(P))
. Here, U(P)
denotes the u-coordinate of the base point
of Curve448.¶
The operation x448.encap()
is defined as follows:¶
v
, V
} via V = X448(v,U(P))
where v
is a random scalar¶
X = X448(v, R)
where R
is the public key
eccPublicKey
¶
eccCipherText
to V
¶
eccKeyShare
to SHA3-512(X || eccCipherText || eccPublicKey)
¶
The operation x448Kem.decap()
is defined as follows:¶
The operation ecdhKem.encap()
is defined as follows:¶
v
, V=vG
} as defined in
[SP800-186] or [RFC5639] where v
is a random scalar¶
S = vR
, where R
is the component public key
eccPublicKey
, according to [SP800-186] or [RFC5639]¶
X
coordinate from the SEC1 encoded point S = 04 || X || Y
as defined in section Section 2.1.1¶
eccCipherText
to the SEC1 encoding of V
¶
eccKeyShare
to Hash(X || eccCipherText || eccPublicKey)
, with Hash
chosen according to Table 6 or
Table 7¶
The operation ecdhKem.decap()
is defined as follows:¶
S
as rV
, where r
is the eccPrivateKey
and
V
is the eccCipherText
, according to [SP800-186] or [RFC5639]¶
X
coordinate from the SEC1 encoded point S = 04 || X || Y
as defined in section Section 2.1.1¶
eccKeyShare
to Hash(X || eccCipherText || eccPublicKey)
, with Hash
chosen according to Table 6 or
Table 7¶
Kyber-KEM features the following operations:¶
(kyberCipherText, kyberKeyShare) <- kyberKem.encap(kyberPublicKey)¶
and¶
(kyberKeyShare) <- kyberKem.decap(kyberCipherText, kyberPrivateKey)¶
The above are the operations Kyber.CCAKEM.Enc() and Kyber.CCAKEM.Dec() defined in [KYBER-Subm].¶
Kyber-KEM has the parameterization with the corresponding artifact lengths in octets as given in Table 8. All artifacts are encoded as defined in [KYBER-Subm].¶
Algorithm ID reference | Kyber-KEM | Public key | Secret key | Ciphertext | Key share |
---|---|---|---|---|---|
29, 31, 33 | kyberKem768 | 1184 | 2400 | 1088 | 32 |
30, 32, 34 | kyberKem1024 | 1568 | 3186 | 1568 | 32 |
The placeholder kyberKem
has to be replaced with the specific Kyber-KEM from
the column "Kyber-KEM" of Table 8.¶
The procedure to perform kyberKem.encap()
is as follows:¶
kyberPublicKey
that is part of the
recipient's composite public key¶
(kyberCipherText, keyShare) <- kyberKem.encap(kyberPublicKey)
¶
kyberCipherText
as the Kyber ciphertext¶
keyShare
as the Kyber symmetric key share¶
The procedure to perform kyberKem.decap()
is as follows:¶
Table 1 specifies the following Kyber + ECC composite public-key encryption schemes:¶
Algorithm ID reference | Kyber-KEM | ECC-KEM | ECDH-KEM curve |
---|---|---|---|
29 | kyberKem768 | x25519Kem | X25519 |
30 | kyberKem1024 | x448Kem | X448 |
31 | kyberKem768 | ecdhKem | NIST P-256 |
32 | kyberKem1024 | ecdhKem | NIST P-384 |
33 | kyberKem768 | ecdhKem | brainpoolP256r1 |
34 | kyberKem1024 | ecdhKem | brainpoolP384r1 |
The Kyber + ECC composite public-key encryption schemes are built according to the following principal design:¶
For the composite KEM schemes defined in Table 1 the following procedure, justified in Section 9.3, MUST be used to derive a string to use as binding between the KEK and the communication parties.¶
// Input: // algID - the algorithm ID encoded as octet fixedInfo = algID¶
SHA3-256 MUST be used to hash the publicKey
of the recipient.¶
For the composite KEM schemes defined in Table 1 the following procedure MUST be used to compute the KEK that wraps a session key. The construction is a one-step key derivation function compliant to [SP800-56C] Section 4, based on KMAC256 [SP800-185]. It is given by the following algorithm.¶
// multiKeyCombine(eccKeyShare, eccCipherText, // kyberKeyShare, kyberCipherText, // fixedInfo, oBits) // // Input: // eccKeyShare - the ECC key share encoded as an octet string // eccCipherText - the ECC ciphertext encoded as an octet string // kyberKeyShare - the Kyber key share encoded as an octet string // kyberCipherText - the Kyber ciphertext encoded as an octet string // fixedInfo - the fixed information octet string // oBits - the size of the output keying material in bits // // Constants: // domSeparation - the UTF-8 encoding of the string // "OpenPGPCompositeKeyDerivationFunction" // counter - the fixed 4 byte value 0x00000001 // customizationString - the UTF-8 encoding of the string "KDF" eccKemData = eccKeyShare || eccCipherText kyberKemData = kyberKeyShare || kyberCipherText encData = counter || eccKemData || kyberKemData || fixedInfo MB = KMAC256(domSeparation, encData, oBits, customizationString)¶
Note that the values eccKeyShare
defined in Section 5.1.1 and kyberKeyShare
defined in Section 5.1.2 already use the relative ciphertext in the
derivation. The ciphertext is by design included again in the key combiner to
provide a robust security proof.¶
The value of domSeparation
is the UTF-8 encoding of the string
"OpenPGPCompositeKeyDerivationFunction" and MUST be the following octet sequence:¶
domSeparation := 4F 70 65 6E 50 47 50 43 6F 6D 70 6F 73 69 74 65 4B 65 79 44 65 72 69 76 61 74 69 6F 6E 46 75 6E 63 74 69 6F 6E¶
The value of counter
MUST be set to the following octet sequence:¶
counter := 00 00 00 01¶
The value of fixedInfo
MUST be set according to Section 5.2.1.¶
The value of customizationString
is the UTF-8 encoding of the string "KDF"
and MUST be set to the following octet sequence:¶
customizationString := 4B 44 46¶
The implementation MUST independently generate the Kyber and the ECC component keys. Kyber key generation follows the specification [KYBER-Subm] and the artifacts are encoded as fixed-length octet strings. For ECC this is done following the relative specification in [RFC7748], [SP800-186], or [RFC5639], and encoding the outputs as fixed-length octet strings in the format specified in table Table 5, Table 6, or Table 7.¶
The procedure to perform public-key encryption with a Kyber + ECC composite scheme is as follows:¶
pkComposite
and
sessionKey
as input¶
pkComposite
¶
eccPublicKey
and kyberPublicKey
component from the
algorithm specific data encoded in pkComposite
with the format specified
in Section 5.3.2.¶
eccKem.encap()
and the Kyber-KEM
kyberKem.encap()
depending on the algorithm ID according to
Table 9¶
(eccCipherText, eccKeyShare) := eccKem.encap(eccPublicKey)
¶
(kyberCipherText, kyberKeyShare) :=
kyberKem.encap(kyberPublicKey)
¶
fixedInfo
as specified in Section 5.2.1¶
KEK := multiKeyCombine(eccKeyShare, eccCipherText, kyberKeyShare, kyberCipherText, fixedInfo, oBits=256)
as
defined in Section 5.2.2¶
C := AESKeyWrap(KEK, sessionKey)
with AES-256 as per [RFC3394]
that includes a 64 bit integrity check¶
eccCipherText || kyberCipherText || len(C) || C
¶
The procedure to perform public-key decryption with a Kyber + ECC composite scheme is as follows:¶
encryptedKey
¶
eccSecretKey
and kyberSecretKey
from the algorithm specific
data of the own secret key encoded in the format specified in
Section 5.3.2¶
eccKem.decap()
and the Kyber-KEM
kyberKem.decap()
depending on the algorithm ID according to
Table 9¶
eccCipherText
, kyberCipherText
, and C
from encryptedKey
encoded as eccCipherText || kyberCipherText || len(C) || C
as specified
in Section 5.3.1¶
(eccKeyShare) := eccKem.decap(eccCipherText, eccPrivateKey)
¶
(kyberKeyShare) := kyberKem.decap(kyberCipherText,
kyberPrivateKey)
¶
fixedInfo
as specified in Section 5.2.1¶
KEK := multiKeyCombine(eccKeyShare, eccCipherText, kyberKeyShare, kyberCipherText, fixedInfo, oBits=256)
as defined in Section 5.2.2¶
sessionKey := AESKeyUnwrap(KEK, C)
with AES-256 as per
[RFC3394], aborting if the 64 bit integrity check fails¶
sessionKey
¶
The algorithm-specific fields consists of:¶
A variable-length field containing the wrapped session key:¶
Note that unlike most public-key algorithms, in the case of a v3 PKESK packet, the symmetric algorithm identifier is not encrypted. Instead, it is prepended to the encrypted session key in plaintext. In this case, the symmetric algorithm used MUST be AES-128, AES-192 or AES-256 (algorithm ID 7, 8 or 9).¶
The algorithm-specific public key is this series of values:¶
The algorithm-specific secret key is these two values:¶
To sign and verify with EdDSA the following operations are defined:¶
(eddsaSignature) <- eddsa.sign(eddsaPrivateKey, dataDigest)¶
and¶
(verified) <- eddsa.verify(eddsaPublicKey, eddsaSignature, dataDigest)¶
The public and private keys, as well as the signature MUST be encoded according to [RFC8032] as fixed-length octet strings. The following table describes the EdDSA parameters and artifact lengths:¶
Algorithm ID reference | Curve | Field size | Public key | Secret key | Signature |
---|---|---|---|---|---|
35 | Ed25519 | 32 | 32 | 32 | 64 |
36 | Ed448 | 57 | 57 | 57 | 114 |
To sign and verify with ECDSA the following operations are defined:¶
(ecdsaSignatureR, ecdsaSignatureS) <- ecdsa.sign(ecdsaPrivateKey, dataDigest)¶
and¶
(verified) <- ecdsa.verify(ecdsaPublicKey, ecdsaSignatureR, ecdsaSignatureS, dataDigest)¶
The public keys MUST be encoded in SEC1 format as defined in section
Section 2.1.1. The secret key, as well as both values R
and S
of the
signature MUST each be encoded as a big-endian integer in a fixed-length octet
string of the specified size.¶
The following table describes the ECDSA parameters and artifact lengths:¶
Algorithm ID reference | Curve | Field size | Public key | Secret key | Signature value R | Signature value S |
---|---|---|---|---|---|---|
37 | NIST P-256 | 32 | 65 | 32 | 32 | 32 |
38 | NIST P-384 | 48 | 97 | 48 | 48 | 48 |
39 | brainpoolP256r1 | 32 | 65 | 32 | 32 | 32 |
40 | brainpoolP384r1 | 48 | 97 | 48 | 48 | 48 |
The procedure for Dilithium signature generation is the function Sign(sk, M)
given in Figure 4 in [DILITHIUM-Subm], where sk
is the Dilithium private key
and M
is the data to be signed. OpenPGP does not use the optional randomized
signing given as a variant in the definition of this function, i.e. rho' :=
H(K || mu)
is used. The signing function returns the Dilithium signature. That
is, to sign with Dilithium the following operation is defined:¶
(dilithiumSignature) <- dilithium.sign(dilithiumPrivateKey, dataDigest)¶
The procedure for Dilithium signature verification is the function Verify(pk,
M, sigma)
given in Figure 4 in [DILITHIUM-Subm], where pk
is the Dilithium
public key, M
is the data to be signed and sigma
is the Dilithium
signature. That is, to verify with Dilithium the following operation is
defined:¶
(verified) <- dilithium.verify(dilithiumPublicKey, dataDigest, dilithiumSignature)¶
Dilithium has the parameterization with the corresponding artifact lengths in octets as given in Table 12. All artifacts are encoded as defined in [DILITHIUM-Subm].¶
Algorithm ID reference | Dilithium instance | Public key | Secret key | Signature value |
---|---|---|---|---|
35, 37, 39 | Dilithium3 | 1952 | 4000 | 3293 |
36, 38, 40 | Dilithium5 | 2592 | 4864 | 4595 |
Composite Dilithium + ECC signatures MUST use SHA3-256 (hash algorithm ID 12) or SHA3-512 (hash algorithm ID 14) as hashing algorithm. Signatures using other hash algorithms MUST be considered invalid.¶
An implementation MUST support SHA3-256 and SHOULD support SHA3-512, in order to support the hash binding with Dilithium + ECC signatures.¶
The implementation MUST independently generate the Dilithium and the ECC component keys. Dilithium key generation follows the specification in [DILITHIUM-Subm] and the artifacts are encoded as fixed-length octet strings as defined in Section 6.1.3. For ECC this is done following the relative specification in [RFC7748], [SP800-186], or [RFC5639], and encoding the artifacts as specified in Section 6.1.1 or Section 6.1.2 as fixed-length octet strings.¶
To sign a message M
with Dilithium + EdDSA the following sequence of
operations has to be performed:¶
dataDigest
according to [I-D.ietf-openpgp-crypto-refresh]
Section 5.2.4¶
dataDigest
with eddsa.sign()
from
Section 6.1.1¶
dataDigest
with dilithium.sign()
from Section 6.1.3¶
To sign a message M
with Dilithium + ECDSA the following sequence of
operations has to be performed:¶
dataDigest
according to [I-D.ietf-openpgp-crypto-refresh]
Section 5.2.4¶
dataDigest
with ecdsa.sign()
from
Section 6.1.2¶
dataDigest
with dilithium.sign()
from Section 6.1.3¶
To verify a Dilithium + EdDSA signature the following sequence of operations has to be performed:¶
eddsa.verify()
from Section 6.1.1¶
dilithium.verify()
from
Section 6.1.3¶
To verify a Dilithium + ECDSA signature the following sequence of operations has to be performed:¶
ecdsa.verify()
from Section 6.1.2¶
dilithium.verify()
from
Section 6.1.3¶
As specified in Section 4.3 an implementation MUST validate both signatures, i.e. EdDSA/ECDSA and Dilithium, to state that a composite Dilithium + ECC signature is valid.¶
The composite Dilithium + ECC schemes MUST be used only with v6 signatures, as defined in [I-D.ietf-openpgp-crypto-refresh] Section 5.2.3.¶
The algorithm-specific v6 signature parameters for Dilithium + EdDSA signatures consists of:¶
The algorithm-specific v6 signature parameters for Dilithium + ECDSA signatures consists of:¶
R
, whose
length depends on the algorithm ID as specified in Table 11.¶
S
, whose
length depends on the algorithm ID as specified in Table 11.¶
The composite Dilithium + ECC schemes MUST be used only with v6 keys, as defined in [I-D.ietf-openpgp-crypto-refresh].¶
The algorithm-specific public key for Dilithium + EdDSA keys is this series of values:¶
The algorithm-specific private key for Dilithium + EdDSA keys is this series of values:¶
The algorithm-specific public key for Dilithium + ECDSA keys is this series of values:¶
The algorithm-specific private key for Dilithium + ECDSA keys is this series of values:¶
The following table describes the SPHINCS+ parameters and artifact lengths:¶
Parameter ID reference | Parameter name suffix | SPHINCS+ public key | SPHINCS+ secret key | SPHINCS+ signature |
---|---|---|---|---|
1 | 128s | 32 | 64 | 7856 |
2 | 128f | 32 | 64 | 17088 |
3 | 192s | 48 | 96 | 16224 |
4 | 192f | 48 | 96 | 35664 |
5 | 256s | 64 | 128 | 29792 |
6 | 256f | 64 | 128 | 49856 |
SPHINCS+ signature packets MUST use the associated hash as specified in Table 14. Signature packets using other hashes MUST be considered invalid.¶
Algorithm ID reference | Parameter ID reference | Hash function | Hash function ID reference |
---|---|---|---|
41 | 1, 2 | SHA-256 | 8 |
41 | 3, 4, 5, 6 | SHA-512 | 10 |
42 | 1, 2 | SHA3-256 | 12 |
42 | 3, 4, 5, 6 | SHA3-512 | 14 |
An implementation supporting a specific SPHINCS+ algorithm and parameter MUST also support the matching hash algorithm.¶
The SPHINCS+ key generation is performed according to the function
spx_keygen()
specified in [SPHINCS-Subm], Sec. 6.2 as Alg. 19. The private
and public key are encoded as defined in [SPHINCS-Subm].¶
The procedure for SPHINCS+ signature generation is the function spx_sign(M,
SK)
specified in [SPHINCS-Subm], Sec. 6.4 as Alg. 20. Here, M
is the
dataDigest
generated according to [I-D.ietf-openpgp-crypto-refresh] Section
5.2.4 and SK
is the SPHINCS+ private key. The global variable RANDOMIZE
specified in Alg. 20 is to be considered as not set, i.e. the variable opt
shall be initialized with PK.seed
. See also Section 9.4.¶
An implementation MUST set the Parameter ID in the signature equal to the issuing private key Parameter ID.¶
The procedure for SPHINCS+ signature verification is the function
spx_verify(M, SIG, PK)
specified in [SPHINCS-Subm], Sec. 6.5 as Alg. 21.
Here, M
is the dataDigest
generated according to
[I-D.ietf-openpgp-crypto-refresh] Section 5.2.4, SIG
is the signature, and
PK
is the SPHINCS+ public key.¶
An implementation MUST check that the Parameter ID in the signature and in the key match when verifying.¶
The SPHINCS+ algorithms MUST be used only with v6 signatures, as defined in [I-D.ietf-openpgp-crypto-refresh] Section 5.2.3.¶
The algorithm-specific v6 Signature parameters consists of:¶
The SPHINCS+ algorithms MUST be used only with v6 keys, as defined in [I-D.ietf-openpgp-crypto-refresh].¶
The algorithm-specific public key is this series of values:¶
0x00
and
0xFF
are reserved for future extensions.¶
The algorithm-specific private key is this value:¶
The post-quantum KEM algorithms defined in Table 1 and the signature algorithms defined in Table 2 are a set of new public key algorithms that extend the algorithm selection of [I-D.ietf-openpgp-crypto-refresh]. During the transition period, the post-quantum algorithms will not be supported by all clients. Therefore various migration considerations must be taken into account, in particular backwards compatibility to existing implementations that have not yet been updated to support the post-quantum algorithms.¶
Implementations SHOULD prefer PQ(/T) keys when multiple options are available.¶
For instance, if encrypting for a recipient for which both a valid PQ/T and a valid ECC certificate are available, the implementation SHOULD choose the PQ/T certificate. In case a certificate has both a PQ/T and an ECC encryption-capable valid subkey, the PQ/T subkey SHOULD be preferred.¶
An implementation MAY sign with both a PQ(/T) and an ECC key using multiple signatures over the same data as described in Section 4.4. Signing only with PQ(/T) key material is not backwards compatible.¶
Note that the confidentiality of a message is not post-quantum secure when encrypting to multiple recipients if at least one recipient does not support PQ/T encryption schemes. An implementation SHOULD NOT abort the encryption process in this case to allow for a smooth transition to post-quantum cryptography.¶
It is REQUIRED to generate fresh secrets when generating PQ(/T) keys. Reusing key material from existing ECC keys in PQ(/T) keys does not provide backwards compatibility, and the fingerprint will differ.¶
An OpenPGP (v6) certificate is composed of a certification-capable primary key and one or more subkeys for signature, encryption, and authentication. Two migration strategies are recommended:¶
Our construction of the ECC-KEMs, in particular the inclusion of
eccCipherText
in the final hashing step in encapsulation and decapsulation
that produces the eccKeyShare
, is standard and known as hashed ElGamal key
encapsulation, a hashed variant of ElGamal encryption. It ensures IND-CCA2
security in the random oracle model under some Diffie-Hellman intractability
assumptions [CS03]. The additional inclusion of eccPublicKey
follows the
security advice in Section 6.1 of [RFC7748].¶
For the key combination in Section 5.2.2 this specification limits itself to the use of KMAC. The sponge construction used by KMAC was proven to be indifferentiable from a random oracle [BDPA08]. This means, that in contrast to SHA2, which uses a Merkle-Damgard construction, no HMAC-based construction is required for key combination. Except for a domain separation it is sufficient to simply process the concatenation of any number of key shares when using a sponge-based construction like KMAC. The construction using KMAC ensures a standardized domain separation. In this case, the processed message is then the concatenation of any number of key shares.¶
More precisely, for a given capacity c
the indifferentiability proof shows
that assuming there are no weaknesses found in the Keccak permutation, an
attacker has to make an expected number of 2^(c/2)
calls to the permutation
to tell KMAC from a random oracle. For a random oracle, a difference in only a
single bit gives an unrelated, uniformly random output. Hence, to be able to
distinguish a key K
, derived from shared keys K1
and K2
(and ciphertexts
C1
and C2
) as¶
K = KMAC(domainSeparation, counter || K1 || C1 || K2 || C2 || fixedInfo, outputBits, customization)¶
from a random bit string, an adversary has to know (or correctly guess) both
key shares K1
and K2
, entirely.¶
The proposed construction in Section 5.2.2 preserves IND-CCA2 of any of its ingredient KEMs, i.e. the newly formed combined KEM is IND-CCA2 secure as long as at least one of the ingredient KEMs is. Indeed, the above stated indifferentiability from a random oracle qualifies Keccak as a split-key pseudorandom function as defined in [GHP18]. That is, Keccak behaves like a random function if at least one input shared secret is picked uniformly at random. Our construction can thus be seen as an instantiation of the IND-CCA2 preserving Example 3 in Figure 1 of [GHP18], up to some reordering of input shared secrets and ciphertexts. In the random oracle setting, the reordering does not influence the arguments in [GHP18].¶
The domSeparation
information defined in Section 5.2.2 provides the
domain separation for the key combiner construction. This ensures that the
input keying material is used to generate a KEK for a specific purpose or
context.¶
The fixedInfo
defined in Section 5.2.1 binds the derived KEK to the
chosen algorithm and communication parties. The algorithm ID identifies
univocally the algorithm, the parameters for its instantiation, and the length
of all artifacts, including the derived key.¶
This is in line with the Recommendation for ECC in section 5.5 of [SP800-56A]. Other fields included in the recommendation are not relevant for the OpenPGP protocol, since the sender is not required to have a key of their own, there are no pre-shared secrets, and all the other parameters are univocally defined by the algorithm ID.¶
Furthermore, we do not require the recipients public key into the key combiner as the public key material is already included in the component key derivation functions. Given two KEMs which we assume to be multi-user secure, we combine their outputs using a KEM-combiner:¶
K = H(K1, C1, K2, C2), C = (C1, C2)¶
Our aim is to preserve multi-user security. A common approach to this is to add the public key into the key derivation for K. However, it turns out that this is not necessary here. To break security of the combined scheme in the multi-user setting, the adversary has to distinguish a set of challenge keys¶
K_u = H(K1_u, C1_u, K2_u, C2*_u)¶
for users u in some set from random, also given ciphertexts C*_u = (C1*_u,
C2*_u)
.
For each of these K* it holds that if the adversary never makes a query¶
H(K1*_u, C1*_u, K2*_u, C2*_u)¶
they have a zero advantage over guessing.¶
The only multi-user advantage that the adversary could gain therefore consists of queries to H that are meaningful for two different users u1 != u2 and their associated public keys. This is only the case if¶
(c1*_u1, c2*_u1) = (c1*_u2, c2*_u2)¶
as the ciphertext values decide for which challenge the query is meaningful. This means that a ciphertext collision is needed between challenges. Assuming that the randomness used in the generation of the two challenges is uncorrelated, this is negligible.¶
In consequence, the ciphertexts already work sufficiently well as domain-separator.¶
The original specification of SPHINCS+ [SPHINCS-Subm] prescribes an optional randomized hashing. This is not used in this specification, as OpenPGP v6 signatures already provide a salted hash of the appropriate size.¶
In order not to extend the attack surface, we bind the hash algorithm used for message digestion to the hash algorithm used internally by the signature algorithm. Dilithium internally uses a SHAKE256 digest, therefore we require SHA3 in the Dilithium + ECC signature packet. In the case of SPHINCS+ the internal hash algorithm varies based on the algorithm and parameter ID.¶
This specification introduces both Dilithium + ECC as well as SPHINCS+ as PQ(/T) signature schemes.¶
Generally, it can be said that Dilithium + ECC provides a performance in terms of execution time and space requirements that is close to that of traditional ECC signature schemes. Implementers may want to offer SPHINCS+ for applications where a higher degree of trust in the signature scheme is required. However, SPHINCS+ has performance characteristics in terms of execution time of the signature generation as well as space requirements for the signature that can be, depending on the parameter choice, far greater than those of traditional or Dilithium + ECC signature schemes.¶
Pertaining to the execution time, the particularly costly operation in SPHINCS+ is the signature generation. In order to achieve short signature generation times, one of the parameter sets with the name ending in the letter "f" for "fast" should be chosen. This comes at the expense of a larger signature size.¶
In order to minimize the space requirements of a SPHINCS+ signature, a parameter set ending in "s" for "small" should be chosen. This comes at the expense of a larger signature generation time.¶
IANA will add the following registries to the Pretty Good Privacy (PGP)
registry group at https://www.iana.org/assignments/pgp-parameters:¶
Registry name: SPHINCS+-simple-SHA2 parameters
¶
Registry name: SPHINCS+-simple-SHAKE parameters
¶
Furthermore IANA will add the algorithm IDs defined in Table 1 and
Table 2 to the registry Public Key Algorithms
.¶
Stephan Ehlen (BSI)
Carl-Daniel Hailfinger (BSI)
Andreas Huelsing (TU Eindhoven)
Johannes Roth (MTG AG)¶
Thanks to Daniel Huigens and Evangelos Karatsiolis for the early review and feedback on this document.¶