1- using System ;
2- using System . Globalization ;
1+ using System . Globalization ;
32using System . Security . Cryptography ;
43
5- using Org . BouncyCastle . Crypto . Generators ;
6- using Org . BouncyCastle . Crypto . Kems ;
74using Org . BouncyCastle . Crypto . Parameters ;
85
96using Renci . SshNet . Abstractions ;
129
1310namespace Renci . SshNet . Security
1411{
15- internal sealed class KeyExchangeMLKem768X25519Sha256 : KeyExchangeECCurve25519
12+ internal sealed partial class KeyExchangeMLKem768X25519Sha256 : KeyExchangeECCurve25519
1613 {
17- private readonly MLKemAlgorithm _mlkem768 = MLKemAlgorithm . MLKem768 ;
18- private MLKem _mlkem ;
19- private MLKemDecapsulator _mlkemDecapsulator ;
14+ private Impl _mlkemImpl ;
2015
2116 /// <summary>
2217 /// Gets algorithm name.
@@ -44,24 +39,17 @@ protected override void StartImpl()
4439
4540 Session . KeyExchangeHybridReplyMessageReceived += Session_KeyExchangeHybridReplyMessageReceived ;
4641
47- byte [ ] mlkem768PublicKey ;
4842 if ( MLKem . IsSupported )
4943 {
50- _mlkem = MLKem . GenerateKey ( _mlkem768 ) ;
51- mlkem768PublicKey = _mlkem . ExportEncapsulationKey ( ) ;
44+ _mlkemImpl = new MLKemBclImpl ( ) ;
5245 }
5346 else
5447 {
55- var mlkem768KeyPairGenerator = new MLKemKeyPairGenerator ( ) ;
56- mlkem768KeyPairGenerator . Init ( new MLKemKeyGenerationParameters ( CryptoAbstraction . SecureRandom , MLKemParameters . ml_kem_768 ) ) ;
57- var mlkem768KeyPair = mlkem768KeyPairGenerator . GenerateKeyPair ( ) ;
58-
59- _mlkemDecapsulator = new MLKemDecapsulator ( MLKemParameters . ml_kem_768 ) ;
60- _mlkemDecapsulator . Init ( mlkem768KeyPair . Private ) ;
61-
62- mlkem768PublicKey = ( ( MLKemPublicKeyParameters ) mlkem768KeyPair . Public ) . GetEncoded ( ) ;
48+ _mlkemImpl = new MLKemBouncyCastleImpl ( ) ;
6349 }
6450
51+ var mlkem768PublicKey = _mlkemImpl . GenerateClientPublicKey ( ) ;
52+
6553 var x25519PublicKey = _impl . GenerateClientPublicKey ( ) ;
6654
6755 _clientExchangeValue = mlkem768PublicKey . Concat ( x25519PublicKey ) ;
@@ -112,25 +100,16 @@ private void HandleServerHybridReply(byte[] hostKey, byte[] serverExchangeValue,
112100 _hostKey = hostKey ;
113101 _signature = signature ;
114102
115- if ( serverExchangeValue . Length != _mlkemDecapsulator . EncapsulationLength + X25519PublicKeyParameters . KeySize )
103+ if ( serverExchangeValue . Length != MLKemAlgorithm . MLKem768 . CiphertextSizeInBytes + X25519PublicKeyParameters . KeySize )
116104 {
117105 throw new SshConnectionException (
118106 string . Format ( CultureInfo . CurrentCulture , "Bad S_Reply length: {0}." , serverExchangeValue . Length ) ,
119107 DisconnectReason . KeyExchangeFailed ) ;
120108 }
121109
122- var mlkemSecret = new byte [ _mlkemDecapsulator . SecretLength ] ;
123-
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- }
110+ var mlkemSecret = _mlkemImpl . CalculateAgreement ( serverExchangeValue ) ;
132111
133- var x25519Agreement = _impl . CalculateAgreement ( serverExchangeValue . Take ( _mlkemDecapsulator . EncapsulationLength , X25519PublicKeyParameters . KeySize ) ) ;
112+ var x25519Agreement = _impl . CalculateAgreement ( serverExchangeValue . Take ( MLKemAlgorithm . MLKem768 . CiphertextSizeInBytes , X25519PublicKeyParameters . KeySize ) ) ;
134113
135114 SharedKey = CryptoAbstraction . HashSHA256 ( mlkemSecret . Concat ( x25519Agreement ) ) ;
136115 }
@@ -139,7 +118,7 @@ protected override void Dispose(bool disposing)
139118 {
140119 if ( disposing )
141120 {
142- _mlkem ? . Dispose ( ) ;
121+ _mlkemImpl ? . Dispose ( ) ;
143122 }
144123
145124 base . Dispose ( disposing ) ;
0 commit comments