Skip to content

Commit e66b699

Browse files
committed
Use BCL MLKem
1 parent af279d2 commit e66b699

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
1212
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.220" />
1313
<!-- Should stay on LTS .NET releases. -->
14+
<PackageVersion Include="Microsoft.Bcl.Cryptography" Version="10.0.0-rc.1.25451.107" />
1415
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
1516
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.9" />
1617
<PackageVersion Include="MSTest" Version="3.9.3" />

src/Renci.SshNet/Renci.SshNet.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@
4949
</PackageReference>
5050
</ItemGroup>
5151

52-
<ItemGroup Condition=" !$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0')) ">
53-
<PackageReference Include="System.Formats.Asn1" />
52+
<ItemGroup>
53+
<PackageReference Include="Microsoft.Bcl.Cryptography" />
5454
</ItemGroup>
5555

56+
5657
<ItemGroup>
5758
<None Include="..\..\images\logo\png\SS-NET-icon-h500.png">
5859
<Pack>True</Pack>

src/Renci.SshNet/Security/KeyExchangeMLKem768X25519Sha256.cs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System.Globalization;
2-
using System.Linq;
1+
using System;
2+
using System.Globalization;
3+
using System.Security.Cryptography;
34

45
using Org.BouncyCastle.Crypto.Generators;
56
using 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

Comments
 (0)