1
- using System . Globalization ;
2
- using System . Linq ;
1
+ using System ;
2
+ using System . Globalization ;
3
+ using System . Security . Cryptography ;
3
4
4
5
using Org . BouncyCastle . Crypto . Generators ;
5
6
using Org . BouncyCastle . Crypto . Kems ;
@@ -13,6 +14,8 @@ namespace Renci.SshNet.Security
13
14
{
14
15
internal sealed class KeyExchangeMLKem768X25519Sha256 : KeyExchangeECCurve25519
15
16
{
17
+ private readonly MLKemAlgorithm _mlkem768 = MLKemAlgorithm . MLKem768 ;
18
+ private MLKem _mlkem ;
16
19
private MLKemDecapsulator _mlkemDecapsulator ;
17
20
18
21
/// <summary>
@@ -41,14 +44,23 @@ protected override void StartImpl()
41
44
42
45
Session . KeyExchangeHybridReplyMessageReceived += Session_KeyExchangeHybridReplyMessageReceived ;
43
46
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 ( ) ;
47
58
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 ) ;
50
61
51
- var mlkem768PublicKey = ( ( MLKemPublicKeyParameters ) mlkem768KeyPair . Public ) . GetEncoded ( ) ;
62
+ mlkem768PublicKey = ( ( MLKemPublicKeyParameters ) mlkem768KeyPair . Public ) . GetEncoded ( ) ;
63
+ }
52
64
53
65
var x25519PublicKey = _impl . GenerateClientPublicKey ( ) ;
54
66
@@ -109,11 +121,28 @@ private void HandleServerHybridReply(byte[] hostKey, byte[] serverExchangeValue,
109
121
110
122
var mlkemSecret = new byte [ _mlkemDecapsulator . SecretLength ] ;
111
123
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
+ }
113
132
114
133
var x25519Agreement = _impl . CalculateAgreement ( serverExchangeValue . Take ( _mlkemDecapsulator . EncapsulationLength , X25519PublicKeyParameters . KeySize ) ) ;
115
134
116
135
SharedKey = CryptoAbstraction . HashSHA256 ( mlkemSecret . Concat ( x25519Agreement ) ) ;
117
136
}
137
+
138
+ protected override void Dispose ( bool disposing )
139
+ {
140
+ if ( disposing )
141
+ {
142
+ _mlkem ? . Dispose ( ) ;
143
+ }
144
+
145
+ base . Dispose ( disposing ) ;
146
+ }
118
147
}
119
148
}
0 commit comments