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,8 +18,8 @@ import (
19
18
20
19
const (
21
20
maxSessionKeyLength = 64
22
- domainSeparator = "OpenPGPCompositeKDFv1"
23
21
MlKemSeedLen = 64
22
+ kdfContext = "OpenPGPCompositeKDFv1"
24
23
)
25
24
26
25
type PublicKey struct {
@@ -140,16 +139,11 @@ func Decrypt(priv *PrivateKey, kEphemeral, ecEphemeral, ciphertext []byte) (msg
140
139
return keywrap .Unwrap (kek , ciphertext )
141
140
}
142
141
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
142
+ // buildKey implements the composite KDF from
143
+ // https://github.com/openpgp-pqc/ draft-openpgp-pqc/pull/161
145
144
func buildKey (pub * PublicKey , eccSecretPoint , eccEphemeral , eccPublicKey , mlkemKeyShare , mlkemEphemeral []byte , mlkemPublicKey kem.PublicKey ) ([]byte , error ) {
146
- h := sha3 .New256 ()
147
-
148
- // SHA3 never returns error
149
- _ , _ = h .Write (eccSecretPoint )
150
- _ , _ = h .Write (eccEphemeral )
151
- _ , _ = h .Write (eccPublicKey )
152
- eccKeyShare := h .Sum (nil )
145
+ /// Set the output `ecdhKeyShare` to `eccSecretPoint`
146
+ eccKeyShare := eccSecretPoint
153
147
154
148
serializedMlkemPublicKey , err := mlkemPublicKey .MarshalBinary ()
155
149
if err != nil {
@@ -160,35 +154,22 @@ func buildKey(pub *PublicKey, eccSecretPoint, eccEphemeral, eccPublicKey, mlkemK
160
154
// mlkemEphemeral - the ML-KEM ciphertext encoded as an octet string
161
155
// mlkemPublicKey - The ML-KEM public key of the recipient as an octet string
162
156
// algId - the OpenPGP algorithm ID of the public-key encryption algorithm
163
- // domainSeparator – the UTF-8 encoding of the string "OpenPGPCompositeKDFv1"
164
157
// eccKeyShare - the ECDH key share encoded as an octet string
165
158
// eccEphemeral - the ECDH ciphertext encoded as an octet string
166
159
// eccPublicKey - The ECDH public key of the recipient as an octet string
167
160
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
161
+ // SHA3-256(mlkemKeyShare || eccKeyShare || eccEphemeral || eccPublicKey ||
162
+ // mlkemEphemeral || mlkemPublicKey || algId || "OpenPGPCompositeKDFv1")
163
+ h := sha3 .New256 ()
164
+ _ , _ = h .Write (mlkemKeyShare )
165
+ _ , _ = h .Write (eccKeyShare )
166
+ _ , _ = h .Write (eccEphemeral )
167
+ _ , _ = h .Write (eccPublicKey )
168
+ _ , _ = h .Write (mlkemEphemeral )
169
+ _ , _ = h .Write (serializedMlkemPublicKey )
170
+ _ , _ = h .Write ([]byte {pub .AlgId })
171
+ _ , _ = h .Write ([]byte (kdfContext ))
172
+ return h .Sum (nil ), nil
192
173
}
193
174
194
175
// Validate checks that the public key corresponds to the private key
0 commit comments