1- using System . Globalization ;
2- using System . Linq ;
1+ using System ;
2+ using System . Globalization ;
3+ using System . Security . Cryptography ;
34
45using Org . BouncyCastle . Crypto . Generators ;
56using Org . BouncyCastle . Crypto . Kems ;
@@ -13,6 +14,8 @@ namespace Renci.SshNet.Security
1314{
1415 internal sealed class KeyExchangeMLKem768X25519Sha256 : KeyExchangeECCurve25519
1516 {
17+ private readonly MLKemAlgorithm _mlkem768 = MLKemAlgorithm . MLKem768 ;
18+ private MLKem _mlkem ;
1619 private MLKemDecapsulator _mlkemDecapsulator ;
1720
1821 /// <summary>
@@ -41,14 +44,23 @@ protected override void StartImpl()
4144
4245 Session . KeyExchangeHybridReplyMessageReceived += Session_KeyExchangeHybridReplyMessageReceived ;
4346
44- var mlkem768KeyPairGenerator = new MLKemKeyPairGenerator ( ) ;
45- mlkem768KeyPairGenerator . Init ( new MLKemKeyGenerationParameters ( CryptoAbstraction . SecureRandom , MLKemParameters . ml_kem_768 ) ) ;
46- var mlkem768KeyPair = mlkem768KeyPairGenerator . GenerateKeyPair ( ) ;
47+ byte [ ] mlkem768PublicKey ;
48+ if ( MLKem . IsSupported )
49+ {
50+ _mlkem = MLKem . GenerateKey ( _mlkem768 ) ;
51+ mlkem768PublicKey = _mlkem . ExportEncapsulationKey ( ) ;
52+ }
53+ else
54+ {
55+ var mlkem768KeyPairGenerator = new MLKemKeyPairGenerator ( ) ;
56+ mlkem768KeyPairGenerator . Init ( new MLKemKeyGenerationParameters ( CryptoAbstraction . SecureRandom , MLKemParameters . ml_kem_768 ) ) ;
57+ var mlkem768KeyPair = mlkem768KeyPairGenerator . GenerateKeyPair ( ) ;
4758
48- _mlkemDecapsulator = new MLKemDecapsulator ( MLKemParameters . ml_kem_768 ) ;
49- _mlkemDecapsulator . Init ( mlkem768KeyPair . Private ) ;
59+ _mlkemDecapsulator = new MLKemDecapsulator ( MLKemParameters . ml_kem_768 ) ;
60+ _mlkemDecapsulator . Init ( mlkem768KeyPair . Private ) ;
5061
51- var mlkem768PublicKey = ( ( MLKemPublicKeyParameters ) mlkem768KeyPair . Public ) . GetEncoded ( ) ;
62+ mlkem768PublicKey = ( ( MLKemPublicKeyParameters ) mlkem768KeyPair . Public ) . GetEncoded ( ) ;
63+ }
5264
5365 var x25519PublicKey = _impl . GenerateClientPublicKey ( ) ;
5466
@@ -109,11 +121,28 @@ private void HandleServerHybridReply(byte[] hostKey, byte[] serverExchangeValue,
109121
110122 var mlkemSecret = new byte [ _mlkemDecapsulator . SecretLength ] ;
111123
112- _mlkemDecapsulator . Decapsulate ( serverExchangeValue , 0 , _mlkemDecapsulator . EncapsulationLength , mlkemSecret , 0 , _mlkemDecapsulator . SecretLength ) ;
124+ if ( MLKem . IsSupported )
125+ {
126+ _mlkem . Decapsulate ( serverExchangeValue . AsSpan ( 0 , _mlkem768 . CiphertextSizeInBytes ) , mlkemSecret ) ;
127+ }
128+ else
129+ {
130+ _mlkemDecapsulator . Decapsulate ( serverExchangeValue , 0 , _mlkemDecapsulator . EncapsulationLength , mlkemSecret , 0 , _mlkemDecapsulator . SecretLength ) ;
131+ }
113132
114133 var x25519Agreement = _impl . CalculateAgreement ( serverExchangeValue . Take ( _mlkemDecapsulator . EncapsulationLength , X25519PublicKeyParameters . KeySize ) ) ;
115134
116135 SharedKey = CryptoAbstraction . HashSHA256 ( mlkemSecret . Concat ( x25519Agreement ) ) ;
117136 }
137+
138+ protected override void Dispose ( bool disposing )
139+ {
140+ if ( disposing )
141+ {
142+ _mlkem ? . Dispose ( ) ;
143+ }
144+
145+ base . Dispose ( disposing ) ;
146+ }
118147 }
119148}
0 commit comments