This section describes the One-Pass Diffie-Hellman method, which is a
combination of the ECC Diffie-Hellman method that establishes a
shared secret and the key derivation method that processes the
shared secret into a derived key. Additionally, this section
describes a key wrapping method that uses the derived key to protect
a session key used to encrypt a message.¶
The One-Pass Diffie-Hellman method C(1, 1, ECC CDH) [SP800-56A] MUST be implemented with the following restrictions: the ECC Cofactor Diffie-Hellman (CDH) primitive employed by this method is modified to always assume the cofactor is 1, the KDF specified in Section 11.4 is used, and the KDF parameters specified below are used.¶
The KDF parameters are encoded as a concatenation of the following 5 variable-length and fixed-length fields, which are compatible with the definition of the OtherInfo bit string [SP800-56A]:¶
-
A variable-length field containing a curve OID, which is formatted as follows:¶
-
A 1-octet size of the following field.¶
-
The octets representing a curve OID, as defined in Section 9.2.¶
-
A 1-octet public key algorithm ID, as defined in Section 9.1.¶
-
A variable-length field containing KDF parameters, which are identical to the corresponding field in the ECDH public key and formatted as follows:¶
-
A 1-octet size of the following fields; values 0 and 0xFF are reserved for future extensions.¶
-
A 1-octet value 0x01, reserved for future extensions.¶
-
A 1-octet hash function ID used with the KDF.¶
-
A 1-octet algorithm ID for the symmetric algorithm that is used to wrap the symmetric key for message encryption; see Section 11.5 for details.¶
-
20 octets representing the UTF-8 encoding of the string "Anonymous Sender" padded at the end with spaces (0x20) to 20 octets, which is the octet sequence 41 6E 6F 6E 79 6D 6F 75 73 20 53 65 6E 64 65 72 20 20 20 20.¶
-
A variable-length field containing the fingerprint of the recipient encryption subkey identifying the key material that is needed for decryption.
For version 4 keys, this field is 20 octets.
For version 6 keys, this field is 32 octets.¶
The size in octets of the KDF parameters sequence, as defined above, for encrypting to a version 4 key is 54 for curve NIST P-256; 51 for curves NIST P-384 and NIST P-521; 55 for curves brainpoolP256r1, brainpoolP384r1, and brainpoolP512r1; or 56 for Curve25519Legacy. For encrypting to a version 6 key, the size of the sequence is 66 for curve NIST P-256; 63 for curves NIST P-384 and NIST P-521; or 67 for curves brainpoolP256r1, brainpoolP384r1, and brainpoolP512r1.¶
The key wrapping method is described in [RFC3394].
The KDF produces a symmetric key that is used as a KEK as specified in [RFC3394]. Refer to Section 11.5.1 for the details regarding the choice of the KEK algorithm, which SHOULD be one of the three AES algorithms.
Key wrapping and unwrapping is performed with the default initial value of [RFC3394].¶
To produce the input to the key wrapping method, first concatenate the following values:¶
-
The 1-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).¶
-
The session key.¶
-
A 2-octet checksum of the session key, equal to the sum of the session key octets, modulo 65536.¶
Then, the above values are padded to an 8-octet granularity using the method described in [RFC8018].¶
For example, in a version 3 Public Key Encrypted Session Key packet, an AES-256 session key is encoded as follows, forming a 40-octet sequence:¶
09 k0 k1 ... k31 s0 s1 05 05 05 05 05
¶
The octets k0 to k31 above denote the session key, and the octets s0 and s1 denote the checksum of the session key octets.
This encoding allows the sender to obfuscate the size of the symmetric encryption key used to encrypt the data.
For example, assuming that an AES algorithm is used for the session key, the sender MAY use 21, 13, and 5 octets of padding for AES-128, AES-192, and AES-256, respectively, to provide the same number of octets, 40 total, as an input to the key wrapping method.¶
In a version 6 Public Key Encrypted Session Key packet, the symmetric algorithm is not included, as described in Section 5.1.
For example, an AES-256 session key would be composed as follows:¶
k0 k1 ... k31 s0 s1 06 06 06 06 06 06
¶
The octets k0 to k31 above again denote the session key, and the octets s0 and s1 denote the checksum.
In this case, assuming that an AES algorithm is used for the session key, the sender MAY use 22, 14, and 6 octets of padding for AES-128, AES-192, and AES-256, respectively, to provide the same number of octets, 40 total, as an input to the key wrapping method.¶
The output of the method consists of two fields.
The first field is the MPI containing the ephemeral key used to establish the shared secret.
The second field is composed of the following two subfields:¶
-
One octet encoding the size in octets of the result of the key wrapping method; the value 255 is reserved for future extensions.¶
-
Up to 254 octets representing the result of the key wrapping method, applied to the 8-octet padded session key, as described above.¶
Note that for session key sizes 128, 192, and 256 bits, the size of the result of the key wrapping method is, respectively, 32, 40, and 48 octets, unless size obfuscation is used.¶
For convenience, the synopsis of the encoding method is given below; however, this section, [SP800-56A], and [RFC3394] are the normative sources of the definition.¶
-
Obtain the authenticated recipient public key R¶
-
Generate an ephemeral, single-use key pair {v, V=vG}¶
-
Compute the shared point S = vR¶
-
m = symm_alg_ID || session key || checksum || pkcs5_padding¶
-
curve_OID_len = (octet)len(curve_OID)¶
-
Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || 41 6E 6F 6E 79 6D 6F 75 73 20 53 65 6E 64 65 72 20 20 20 20 || recipient_fingerprint¶
-
Z_len = the key size for the KEK_alg_ID used with AESKeyWrap¶
-
Compute Z = KDF( S, Z_len, Param )¶
-
Compute C = AESKeyWrap( Z, m ) (per [RFC3394])¶
-
Wipe the memory that contained S, v, and Z to avoid leaking ephemeral secrets¶
-
VB = convert point V to the octet string¶
-
Output (MPI(VB) || len(C) || C)¶
The decryption is the inverse of the method given.
Note that the recipient with key pair (r,R) obtains the shared secret by calculating:¶
ECDH keys have a hash algorithm parameter for key derivation and a symmetric algorithm for key encapsulation.¶
For version 6 keys, the following algorithms MUST be used depending on the curve.
An implementation MUST NOT generate a version 6 ECDH key over any listed curve that uses different KDF or KEK parameters.
An implementation MUST NOT encrypt any message to a version 6 ECDH key over a listed curve that announces a different KDF or KEK parameter.¶
For version 4 keys, the following algorithms SHOULD be used depending on the curve.
An implementation SHOULD only use an AES algorithm as a KEK algorithm.¶
Table 30:
OpenPGP ECDH KDF and KEK Parameters Registry
Curve |
Hash Algorithm |
Symmetric Algorithm |
NIST P-256 |
SHA2-256 |
AES-128 |
NIST P-384 |
SHA2-384 |
AES-192 |
NIST P-521 |
SHA2-512 |
AES-256 |
brainpoolP256r1 |
SHA2-256 |
AES-128 |
brainpoolP384r1 |
SHA2-384 |
AES-192 |
brainpoolP512r1 |
SHA2-512 |
AES-256 |
Curve25519Legacy |
SHA2-256 |
AES-128 |