33using System . Diagnostics ;
44using System . IO ;
55
6+ using Org . BouncyCastle . Asn1 . Misc ;
67using Org . BouncyCastle . Asn1 . X9 ;
78using Org . BouncyCastle . Crypto ;
89using Org . BouncyCastle . Crypto . IO ;
910using Org . BouncyCastle . Crypto . Generators ;
1011using Org . BouncyCastle . Crypto . Parameters ;
1112using Org . BouncyCastle . Math ;
1213using Org . BouncyCastle . Math . EC ;
14+ using Org . BouncyCastle . Math . EC . Rfc7748 ;
1315using Org . BouncyCastle . Security ;
1416using Org . BouncyCastle . Utilities ;
1517
@@ -105,7 +107,7 @@ private byte[] EncryptSessionInfo(byte[] sessionInfo, SecureRandom random)
105107 if ( pubKey . Algorithm != PublicKeyAlgorithmTag . ECDH )
106108 {
107109 IBufferedCipher c ;
108- switch ( pubKey . Algorithm )
110+ switch ( pubKey . Algorithm )
109111 {
110112 case PublicKeyAlgorithmTag . RsaEncrypt :
111113 case PublicKeyAlgorithmTag . RsaGeneral :
@@ -119,37 +121,57 @@ private byte[] EncryptSessionInfo(byte[] sessionInfo, SecureRandom random)
119121 throw new PgpException ( "Can't use DSA for encryption." ) ;
120122 case PublicKeyAlgorithmTag . ECDsa :
121123 throw new PgpException ( "Can't use ECDSA for encryption." ) ;
124+ case PublicKeyAlgorithmTag . EdDsa :
125+ throw new PgpException ( "Can't use EdDSA for encryption." ) ;
122126 default :
123127 throw new PgpException ( "unknown asymmetric algorithm: " + pubKey . Algorithm ) ;
124128 }
125129
126130 AsymmetricKeyParameter akp = pubKey . GetKey ( ) ;
127- c . Init ( true , new ParametersWithRandom ( akp , random ) ) ;
131+ c . Init ( true , new ParametersWithRandom ( akp , random ) ) ;
128132 return c . DoFinal ( sessionInfo ) ;
129133 }
130134
131135 ECDHPublicBcpgKey ecKey = ( ECDHPublicBcpgKey ) pubKey . PublicKeyPacket . Key ;
136+ KeyParameter key ;
137+ byte [ ] encodedPublicKey ;
132138
133- // Generate the ephemeral key pair
134- IAsymmetricCipherKeyPairGenerator gen = GeneratorUtilities . GetKeyPairGenerator ( "ECDH" ) ;
135- gen . Init ( new ECKeyGenerationParameters ( ecKey . CurveOid , random ) ) ;
139+ if ( ecKey . CurveOid . Id . Equals ( MiscObjectIdentifiers . Curve25519 . Id ) )
140+ {
141+ byte [ ] privateKey = new byte [ X25519 . PointSize ] ;
142+ X25519 . GeneratePrivateKey ( random , privateKey ) ;
143+ byte [ ] sharedKey = new byte [ 32 ] ;
144+ X25519 . CalculateAgreement ( privateKey , 0 , BigIntegers . AsUnsignedByteArray ( ecKey . EncodedPoint ) , 1 , sharedKey , 0 ) ;
145+ byte [ ] publicKey = new byte [ X25519 . PointSize + 1 ] ;
146+ publicKey [ 0 ] = 0x40 ; // compressed point
147+ X25519 . GeneratePublicKey ( privateKey , 0 , publicKey , 1 ) ;
148+ encodedPublicKey = publicKey ;
149+ key = new KeyParameter ( Rfc6637Utilities . CreateKey ( pubKey . PublicKeyPacket , sharedKey ) ) ;
150+ }
151+ else
152+ {
153+ // Generate the ephemeral key pair
154+ IAsymmetricCipherKeyPairGenerator gen = GeneratorUtilities . GetKeyPairGenerator ( "ECDH" ) ;
155+ gen . Init ( new ECKeyGenerationParameters ( ecKey . CurveOid , random ) ) ;
136156
137- AsymmetricCipherKeyPair ephKp = gen . GenerateKeyPair ( ) ;
138- ECPrivateKeyParameters ephPriv = ( ECPrivateKeyParameters ) ephKp . Private ;
139- ECPublicKeyParameters ephPub = ( ECPublicKeyParameters ) ephKp . Public ;
157+ AsymmetricCipherKeyPair ephKp = gen . GenerateKeyPair ( ) ;
158+ ECPrivateKeyParameters ephPriv = ( ECPrivateKeyParameters ) ephKp . Private ;
159+ ECPublicKeyParameters ephPub = ( ECPublicKeyParameters ) ephKp . Public ;
140160
141- ECPublicKeyParameters pub = ( ECPublicKeyParameters ) pubKey . GetKey ( ) ;
142- ECPoint S = pub . Q . Multiply ( ephPriv . D ) . Normalize ( ) ;
161+ ECPublicKeyParameters pub = ( ECPublicKeyParameters ) pubKey . GetKey ( ) ;
162+ ECPoint S = pub . Q . Multiply ( ephPriv . D ) . Normalize ( ) ;
143163
144- KeyParameter key = new KeyParameter ( Rfc6637Utilities . CreateKey ( pubKey . PublicKeyPacket , S ) ) ;
164+ key = new KeyParameter ( Rfc6637Utilities . CreateKey ( pubKey . PublicKeyPacket , S ) ) ;
165+ encodedPublicKey = ephPub . Q . GetEncoded ( false ) ;
166+ }
145167
146168 IWrapper w = PgpUtilities . CreateWrapper ( ecKey . SymmetricKeyAlgorithm ) ;
147169 w . Init ( true , new ParametersWithRandom ( key , random ) ) ;
148170
149171 byte [ ] paddedSessionData = PgpPad . PadSessionData ( sessionInfo , sessionKeyObfuscation ) ;
150172
151173 byte [ ] C = w . Wrap ( paddedSessionData , 0 , paddedSessionData . Length ) ;
152- byte [ ] VB = new MPInteger ( new BigInteger ( 1 , ephPub . Q . GetEncoded ( false ) ) ) . GetEncoded ( ) ;
174+ byte [ ] VB = new MPInteger ( new BigInteger ( 1 , encodedPublicKey ) ) . GetEncoded ( ) ;
153175
154176 byte [ ] rv = new byte [ VB . Length + 1 + C . Length ] ;
155177
0 commit comments