1717package josecipher
1818
1919import (
20+ "bytes"
2021 "crypto"
2122 "crypto/ecdsa"
23+ "crypto/elliptic"
2224 "encoding/binary"
2325)
2426
@@ -44,16 +46,38 @@ func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, p
4446 panic ("public key not on same curve as private key" )
4547 }
4648
47- z , _ := priv .PublicKey . Curve .ScalarMult (pub .X , pub .Y , priv .D .Bytes ())
48- reader := NewConcatKDF ( crypto . SHA256 , z .Bytes (), algID , ptyUInfo , ptyVInfo , supPubInfo , [] byte {} )
49+ z , _ := priv .Curve .ScalarMult (pub .X , pub .Y , priv .D .Bytes ())
50+ zBytes := z .Bytes ()
4951
52+ // Note that calling z.Bytes() on a big.Int may strip leading zero bytes from
53+ // the returned byte array. This can lead to a problem where zBytes will be
54+ // shorter than expected which breaks the key derivation. Therefore we must pad
55+ // to the full length of the expected coordinate here before calling the KDF.
56+ octSize := dSize (priv .Curve )
57+ if len (zBytes ) != octSize {
58+ zBytes = append (bytes .Repeat ([]byte {0 }, octSize - len (zBytes )), zBytes ... )
59+ }
60+
61+ reader := NewConcatKDF (crypto .SHA256 , zBytes , algID , ptyUInfo , ptyVInfo , supPubInfo , []byte {})
5062 key := make ([]byte , size )
5163
5264 // Read on the KDF will never fail
5365 _ , _ = reader .Read (key )
66+
5467 return key
5568}
5669
70+ // dSize returns the size in octets for a coordinate on a elliptic curve.
71+ func dSize (curve elliptic.Curve ) int {
72+ order := curve .Params ().P
73+ bitLen := order .BitLen ()
74+ size := bitLen / 8
75+ if bitLen % 8 != 0 {
76+ size ++
77+ }
78+ return size
79+ }
80+
5781func lengthPrefixed (data []byte ) []byte {
5882 out := make ([]byte , len (data )+ 4 )
5983 binary .BigEndian .PutUint32 (out , uint32 (len (data )))
0 commit comments