7
7
"fmt"
8
8
"io"
9
9
10
- "github.com/ProtonMail/go-crypto/internal/kmac"
11
10
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
12
11
"golang.org/x/crypto/sha3"
13
12
@@ -19,7 +18,6 @@ import (
19
18
20
19
const (
21
20
maxSessionKeyLength = 64
22
- domainSeparator = "OpenPGPCompositeKDFv1"
23
21
MlKemSeedLen = 64
24
22
)
25
23
@@ -140,8 +138,8 @@ func Decrypt(priv *PrivateKey, kEphemeral, ecEphemeral, ciphertext []byte) (msg
140
138
return keywrap .Unwrap (kek , ciphertext )
141
139
}
142
140
143
- // buildKey implements the composite KDF as specified in
144
- // https://www .ietf.org/archive/id/draft-ietf- openpgp-pqc-05.html#name-key-combiner
141
+ // buildKey implements the composite KDF 2a from
142
+ // https://mailarchive .ietf.org/arch/msg/ openpgp/NMTCy707LICtxIhP3Xt1U5C8MF0/
145
143
func buildKey (pub * PublicKey , eccSecretPoint , eccEphemeral , eccPublicKey , mlkemKeyShare , mlkemEphemeral []byte , mlkemPublicKey kem.PublicKey ) ([]byte , error ) {
146
144
h := sha3 .New256 ()
147
145
@@ -160,35 +158,21 @@ func buildKey(pub *PublicKey, eccSecretPoint, eccEphemeral, eccPublicKey, mlkemK
160
158
// mlkemEphemeral - the ML-KEM ciphertext encoded as an octet string
161
159
// mlkemPublicKey - The ML-KEM public key of the recipient as an octet string
162
160
// algId - the OpenPGP algorithm ID of the public-key encryption algorithm
163
- // domainSeparator – the UTF-8 encoding of the string "OpenPGPCompositeKDFv1"
164
161
// eccKeyShare - the ECDH key share encoded as an octet string
165
162
// eccEphemeral - the ECDH ciphertext encoded as an octet string
166
163
// eccPublicKey - The ECDH public key of the recipient as an octet string
167
164
168
- // KEK = KMAC256(
169
- // mlkemKeyShare || eccKeyShare,
170
- // mlkemEphemeral || eccEphemeral || mlkemPublicKey || ecdhPublicKey || algId,
171
- // 256 (32 bytes),
172
- // domainSeparator
173
- // )
174
-
175
- kMacKeyBuffer := make ([]byte , len (mlkemKeyShare )+ len (eccKeyShare ))
176
- copy (kMacKeyBuffer [:len (mlkemKeyShare )], mlkemKeyShare )
177
- copy (kMacKeyBuffer [len (mlkemKeyShare ):], eccKeyShare )
178
-
179
- k , err := kmac .NewKMAC256 (kMacKeyBuffer , 32 , []byte (domainSeparator ))
180
- if err != nil {
181
- return nil , err
182
- }
183
-
184
- // kmac hash never returns an error
185
- _ , _ = k .Write (mlkemEphemeral )
186
- _ , _ = k .Write (eccEphemeral )
187
- _ , _ = k .Write (serializedMlkemPublicKey )
188
- _ , _ = k .Write (eccPublicKey )
189
- _ , _ = k .Write ([]byte {pub .AlgId })
190
-
191
- return k .Sum (nil ), nil
165
+ // 2a. SHA3-256(mlkemKeyShare || eccKeyShare || eccEphemeral || eccPublicKey || Domain)
166
+ // where Domain is "Domain" for LAMPS, and "mlkemEphemeral || mlkemPublicKey || algId" for OpenPGP
167
+ h .Reset ()
168
+ _ , _ = h .Write (mlkemKeyShare )
169
+ _ , _ = h .Write (eccKeyShare )
170
+ _ , _ = h .Write (eccEphemeral )
171
+ _ , _ = h .Write (eccPublicKey )
172
+ _ , _ = h .Write (mlkemEphemeral )
173
+ _ , _ = h .Write (serializedMlkemPublicKey )
174
+ _ , _ = h .Write ([]byte {pub .AlgId })
175
+ return h .Sum (nil ), nil
192
176
}
193
177
194
178
// Validate checks that the public key corresponds to the private key
0 commit comments