Skip to content

Commit 9e68521

Browse files
committed
Split into BclImpl and BouncyCastleImpl
1 parent e66b699 commit 9e68521

File tree

3 files changed

+83
-32
lines changed

3 files changed

+83
-32
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using System.Security.Cryptography;
3+
4+
namespace Renci.SshNet.Security
5+
{
6+
internal sealed partial class KeyExchangeMLKem768X25519Sha256
7+
{
8+
private sealed class MLKemBclImpl : Impl
9+
{
10+
private MLKem _mlkem;
11+
12+
public override byte[] GenerateClientPublicKey()
13+
{
14+
_mlkem = MLKem.GenerateKey(MLKemAlgorithm.MLKem768);
15+
return _mlkem.ExportEncapsulationKey();
16+
}
17+
18+
public override byte[] CalculateAgreement(byte[] serverPublicKey)
19+
{
20+
var mlkemSecret = new byte[MLKemAlgorithm.MLKem768.SharedSecretSizeInBytes];
21+
_mlkem.Decapsulate(serverPublicKey.AsSpan(0, MLKemAlgorithm.MLKem768.CiphertextSizeInBytes), mlkemSecret);
22+
return mlkemSecret;
23+
}
24+
25+
protected override void Dispose(bool disposing)
26+
{
27+
if (disposing)
28+
{
29+
_mlkem?.Dispose();
30+
}
31+
32+
base.Dispose(disposing);
33+
}
34+
}
35+
}
36+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Org.BouncyCastle.Crypto.Generators;
2+
using Org.BouncyCastle.Crypto.Kems;
3+
using Org.BouncyCastle.Crypto.Parameters;
4+
5+
using Renci.SshNet.Abstractions;
6+
7+
namespace Renci.SshNet.Security
8+
{
9+
internal sealed partial class KeyExchangeMLKem768X25519Sha256
10+
{
11+
private sealed class MLKemBouncyCastleImpl : Impl
12+
{
13+
private MLKemDecapsulator _mlkemDecapsulator;
14+
15+
public override byte[] GenerateClientPublicKey()
16+
{
17+
var mlkem768KeyPairGenerator = new MLKemKeyPairGenerator();
18+
mlkem768KeyPairGenerator.Init(new MLKemKeyGenerationParameters(CryptoAbstraction.SecureRandom, MLKemParameters.ml_kem_768));
19+
var mlkem768KeyPair = mlkem768KeyPairGenerator.GenerateKeyPair();
20+
21+
_mlkemDecapsulator = new MLKemDecapsulator(MLKemParameters.ml_kem_768);
22+
_mlkemDecapsulator.Init(mlkem768KeyPair.Private);
23+
24+
return ((MLKemPublicKeyParameters)mlkem768KeyPair.Public).GetEncoded();
25+
}
26+
27+
public override byte[] CalculateAgreement(byte[] serverPublicKey)
28+
{
29+
var mlkemSecret = new byte[_mlkemDecapsulator.SecretLength];
30+
_mlkemDecapsulator.Decapsulate(serverPublicKey, 0, _mlkemDecapsulator.EncapsulationLength, mlkemSecret, 0, _mlkemDecapsulator.SecretLength);
31+
32+
return mlkemSecret;
33+
}
34+
}
35+
}
36+
}

src/Renci.SshNet/Security/KeyExchangeMLKem768X25519Sha256.cs

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
using System;
2-
using System.Globalization;
1+
using System.Globalization;
32
using System.Security.Cryptography;
43

5-
using Org.BouncyCastle.Crypto.Generators;
6-
using Org.BouncyCastle.Crypto.Kems;
74
using Org.BouncyCastle.Crypto.Parameters;
85

96
using Renci.SshNet.Abstractions;
@@ -12,11 +9,9 @@
129

1310
namespace 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

Comments
 (0)