11//! Generic Elliptic Curve Diffie-Hellman KEM adapter.
22
3- use crate :: { DhDecapsulator , DhEncapsulator , DhKem } ;
3+ use crate :: { DecapsulationKey , DhKem , EncapsulationKey } ;
44use core:: marker:: PhantomData ;
55use elliptic_curve:: {
6- AffinePoint , CurveArithmetic , FieldBytesSize , Generate , PublicKey ,
7- ecdh:: { EphemeralSecret , SharedSecret } ,
6+ AffinePoint , CurveArithmetic , Error , FieldBytesSize , PublicKey ,
7+ ecdh:: EphemeralSecret ,
88 sec1:: {
99 FromEncodedPoint , ModulusSize , ToEncodedPoint , UncompressedPoint , UncompressedPointSize ,
1010 } ,
1111} ;
12- use kem:: { Decapsulate , Encapsulate , InvalidKey , KeyExport , KeySizeUser , TryKeyInit } ;
12+ use kem:: {
13+ Ciphertext , Encapsulate , Generate , InvalidKey , Kem , KeyExport , KeySizeUser , SharedSecret ,
14+ TryDecapsulate , TryKeyInit ,
15+ } ;
1316use rand_core:: { CryptoRng , TryCryptoRng } ;
1417
18+ /// Elliptic Curve Diffie-Hellman Decapsulation Key (i.e. secret decryption key)
19+ ///
20+ /// Generic around an elliptic curve `C`.
21+ pub type EcdhDecapsulationKey < C > = DecapsulationKey < EphemeralSecret < C > , PublicKey < C > > ;
22+
23+ /// Elliptic Curve Diffie-Hellman Encapsulation Key (i.e. public encryption key)
24+ ///
25+ /// Generic around an elliptic curve `C`.
26+ pub type EcdhEncapsulationKey < C > = EncapsulationKey < PublicKey < C > > ;
27+
1528/// Generic Elliptic Curve Diffie-Hellman KEM adapter compatible with curves implemented using
1629/// traits from the `elliptic-curve` crate.
1730///
1831/// Implements a KEM interface that internally uses ECDH.
1932pub struct EcdhKem < C : CurveArithmetic > ( PhantomData < C > ) ;
2033
34+ impl < C > Kem for EcdhEncapsulationKey < C >
35+ where
36+ C : CurveArithmetic ,
37+ FieldBytesSize < C > : ModulusSize ,
38+ {
39+ type CiphertextSize = UncompressedPointSize < C > ;
40+ type SharedSecretSize = FieldBytesSize < C > ;
41+ }
42+
2143/// From [RFC9810 §7.1.1]: `SerializePublicKey` and `DeserializePublicKey`:
2244///
2345/// > For P-256, P-384, and P-521, the SerializePublicKey() function of the
@@ -26,7 +48,7 @@ pub struct EcdhKem<C: CurveArithmetic>(PhantomData<C>);
2648///
2749/// [RFC9810 §7.1.1]: https://datatracker.ietf.org/doc/html/rfc9180#name-serializepublickey-and-dese
2850/// [SECG]: https://www.secg.org/sec1-v2.pdf
29- impl < C > KeySizeUser for DhEncapsulator < PublicKey < C > >
51+ impl < C > KeySizeUser for EcdhEncapsulationKey < C >
3052where
3153 C : CurveArithmetic ,
3254 FieldBytesSize < C > : ModulusSize ,
4062/// > Octet-String-to-Elliptic-Curve-Point conversion.
4163///
4264/// [RFC9810 §7.1.1]: https://datatracker.ietf.org/doc/html/rfc9180#name-serializepublickey-and-dese
43- impl < C > TryKeyInit for DhEncapsulator < PublicKey < C > >
65+ impl < C > TryKeyInit for EcdhEncapsulationKey < C >
4466where
4567 C : CurveArithmetic ,
4668 FieldBytesSize < C > : ModulusSize ,
@@ -61,21 +83,18 @@ where
6183///
6284/// [RFC9810 §7.1.1]: https://datatracker.ietf.org/doc/html/rfc9180#name-serializepublickey-and-dese
6385/// [SECG]: https://www.secg.org/sec1-v2.pdf
64- impl < C > KeyExport for DhEncapsulator < PublicKey < C > >
86+ impl < C > KeyExport for EcdhEncapsulationKey < C >
6587where
6688 C : CurveArithmetic ,
6789 FieldBytesSize < C > : ModulusSize ,
6890 AffinePoint < C > : FromEncodedPoint < C > + ToEncodedPoint < C > ,
6991{
7092 fn to_bytes ( & self ) -> UncompressedPoint < C > {
71- // TODO(tarcieri): use `ToEncodedPoint::to_uncompressed_point` (RustCrypto/traits#2221)
72- let mut ret = UncompressedPoint :: < C > :: default ( ) ;
73- ret. copy_from_slice ( self . 0 . to_encoded_point ( false ) . as_bytes ( ) ) ;
74- ret
93+ self . 0 . to_uncompressed_point ( )
7594 }
7695}
7796
78- impl < C > Encapsulate < PublicKey < C > , SharedSecret < C > > for DhEncapsulator < PublicKey < C > >
97+ impl < C > Encapsulate for EcdhEncapsulationKey < C >
7998where
8099 C : CurveArithmetic ,
81100 FieldBytesSize < C > : ModulusSize ,
@@ -84,31 +103,42 @@ where
84103 fn encapsulate_with_rng < R : TryCryptoRng + ?Sized > (
85104 & self ,
86105 rng : & mut R ,
87- ) -> Result < ( PublicKey < C > , SharedSecret < C > ) , R :: Error > {
106+ ) -> Result < ( Ciphertext < Self > , SharedSecret < Self > ) , R :: Error > {
88107 // ECDH encapsulation involves creating a new ephemeral key pair and then doing DH
89108 // TODO(tarcieri): propagate RNG errors
90109 let sk = EphemeralSecret :: try_generate_from_rng ( rng) . expect ( "RNG failure" ) ;
91110 let pk = sk. public_key ( ) ;
92111 let ss = sk. diffie_hellman ( & self . 0 ) ;
93112
94- Ok ( ( pk, ss) )
113+ Ok ( ( pk. to_uncompressed_point ( ) , ss. raw_secret_bytes ( ) . clone ( ) ) )
95114 }
96115}
97116
98- impl < C > Decapsulate < PublicKey < C > , SharedSecret < C > > for DhDecapsulator < EphemeralSecret < C > >
117+ impl < C > Generate for EcdhDecapsulationKey < C >
99118where
100119 C : CurveArithmetic ,
101120 FieldBytesSize < C > : ModulusSize ,
102- AffinePoint < C > : FromEncodedPoint < C > + ToEncodedPoint < C > ,
103121{
104- type Encapsulator = DhEncapsulator < PublicKey < C > > ;
105-
106- fn decapsulate ( & self , encapsulated_key : & PublicKey < C > ) -> SharedSecret < C > {
107- self . 0 . diffie_hellman ( encapsulated_key)
122+ fn try_generate_from_rng < R : TryCryptoRng + ?Sized > ( rng : & mut R ) -> Result < Self , R :: Error > {
123+ Ok ( EphemeralSecret :: try_generate_from_rng ( rng) ?. into ( ) )
108124 }
125+ }
126+
127+ impl < C > TryDecapsulate for EcdhDecapsulationKey < C >
128+ where
129+ C : CurveArithmetic ,
130+ FieldBytesSize < C > : ModulusSize ,
131+ AffinePoint < C > : FromEncodedPoint < C > + ToEncodedPoint < C > ,
132+ {
133+ type Error = Error ;
109134
110- fn encapsulator ( & self ) -> DhEncapsulator < PublicKey < C > > {
111- DhEncapsulator ( self . 0 . public_key ( ) )
135+ fn try_decapsulate (
136+ & self ,
137+ encapsulated_key : & Ciphertext < Self > ,
138+ ) -> Result < SharedSecret < Self > , Error > {
139+ let encapsulated_key = PublicKey :: < C > :: from_sec1_bytes ( encapsulated_key) ?;
140+ let shared_secret = self . dk . diffie_hellman ( & encapsulated_key) ;
141+ Ok ( shared_secret. raw_secret_bytes ( ) . clone ( ) )
112142 }
113143}
114144
@@ -118,10 +148,10 @@ where
118148 FieldBytesSize < C > : ModulusSize ,
119149 AffinePoint < C > : FromEncodedPoint < C > + ToEncodedPoint < C > ,
120150{
121- type DecapsulatingKey = DhDecapsulator < EphemeralSecret < C > > ;
122- type EncapsulatingKey = DhEncapsulator < PublicKey < C > > ;
123- type EncapsulatedKey = PublicKey < C > ;
124- type SharedSecret = SharedSecret < C > ;
151+ type DecapsulatingKey = EcdhDecapsulationKey < C > ;
152+ type EncapsulatingKey = EcdhEncapsulationKey < C > ;
153+ type EncapsulatedKey = Ciphertext < EcdhDecapsulationKey < C > > ;
154+ type SharedSecret = SharedSecret < EcdhDecapsulationKey < C > > ;
125155
126156 fn random_keypair < R : CryptoRng + ?Sized > (
127157 rng : & mut R ,
@@ -130,6 +160,6 @@ where
130160 let sk = EphemeralSecret :: try_generate_from_rng ( rng) . expect ( "RNG failure" ) ;
131161 let pk = PublicKey :: from ( & sk) ;
132162
133- ( DhDecapsulator ( sk) , DhEncapsulator ( pk) )
163+ ( DecapsulationKey :: from ( sk) , EncapsulationKey ( pk) )
134164 }
135165}
0 commit comments