|
1 | 1 | using System.Globalization;
|
2 | 2 | using System.Linq;
|
3 | 3 |
|
4 |
| -using Org.BouncyCastle.Crypto.Agreement; |
5 | 4 | using Org.BouncyCastle.Crypto.Generators;
|
6 | 5 | using Org.BouncyCastle.Crypto.Kems;
|
7 | 6 | using Org.BouncyCastle.Crypto.Parameters;
|
|
12 | 11 |
|
13 | 12 | namespace Renci.SshNet.Security
|
14 | 13 | {
|
15 |
| - internal sealed class KeyExchangeMLKem768X25519Sha256 : KeyExchangeEC |
| 14 | + internal sealed class KeyExchangeMLKem768X25519Sha256 : KeyExchangeECCurve25519 |
16 | 15 | {
|
17 | 16 | private MLKemDecapsulator _mlkemDecapsulator;
|
18 |
| - private X25519Agreement _x25519Agreement; |
| 17 | +#if NET |
| 18 | + private Impl _impl; |
| 19 | +#else |
| 20 | + private BouncyCastleImpl _impl; |
| 21 | +#endif |
19 | 22 |
|
20 | 23 | /// <summary>
|
21 | 24 | /// Gets algorithm name.
|
@@ -52,15 +55,20 @@ public override void Start(Session session, KeyExchangeInitMessage message, bool
|
52 | 55 | _mlkemDecapsulator = new MLKemDecapsulator(MLKemParameters.ml_kem_768);
|
53 | 56 | _mlkemDecapsulator.Init(mlkem768KeyPair.Private);
|
54 | 57 |
|
55 |
| - var x25519KeyPairGenerator = new X25519KeyPairGenerator(); |
56 |
| - x25519KeyPairGenerator.Init(new X25519KeyGenerationParameters(CryptoAbstraction.SecureRandom)); |
57 |
| - var x25519KeyPair = x25519KeyPairGenerator.GenerateKeyPair(); |
58 |
| - |
59 |
| - _x25519Agreement = new X25519Agreement(); |
60 |
| - _x25519Agreement.Init(x25519KeyPair.Private); |
61 |
| - |
62 | 58 | var mlkem768PublicKey = ((MLKemPublicKeyParameters)mlkem768KeyPair.Public).GetEncoded();
|
63 |
| - var x25519PublicKey = ((X25519PublicKeyParameters)x25519KeyPair.Public).GetEncoded(); |
| 59 | +#if NET |
| 60 | + if (System.OperatingSystem.IsWindowsVersionAtLeast(10)) |
| 61 | + { |
| 62 | + var curve = System.Security.Cryptography.ECCurve.CreateFromFriendlyName("Curve25519"); |
| 63 | + _impl = new BclImpl(curve); |
| 64 | + } |
| 65 | + else |
| 66 | +#endif |
| 67 | + { |
| 68 | + _impl = new BouncyCastleImpl(); |
| 69 | + } |
| 70 | + |
| 71 | + var x25519PublicKey = _impl.GenerateClientECPoint(); |
64 | 72 |
|
65 | 73 | _clientExchangeValue = mlkem768PublicKey.Concat(x25519PublicKey);
|
66 | 74 |
|
@@ -114,21 +122,31 @@ private void HandleServerHybridReply(byte[] hostKey, byte[] serverExchangeValue,
|
114 | 122 | _hostKey = hostKey;
|
115 | 123 | _signature = signature;
|
116 | 124 |
|
117 |
| - if (serverExchangeValue.Length != _mlkemDecapsulator.EncapsulationLength + _x25519Agreement.AgreementSize) |
| 125 | + if (serverExchangeValue.Length != _mlkemDecapsulator.EncapsulationLength + X25519PublicKeyParameters.KeySize) |
118 | 126 | {
|
119 | 127 | throw new SshConnectionException(
|
120 | 128 | string.Format(CultureInfo.CurrentCulture, "Bad S_Reply length: {0}.", serverExchangeValue.Length),
|
121 | 129 | DisconnectReason.KeyExchangeFailed);
|
122 | 130 | }
|
123 | 131 |
|
124 |
| - var secret = new byte[_mlkemDecapsulator.SecretLength + _x25519Agreement.AgreementSize]; |
| 132 | + var mlkemSecret = new byte[_mlkemDecapsulator.SecretLength]; |
125 | 133 |
|
126 |
| - _mlkemDecapsulator.Decapsulate(serverExchangeValue, 0, _mlkemDecapsulator.EncapsulationLength, secret, 0, _mlkemDecapsulator.SecretLength); |
| 134 | + _mlkemDecapsulator.Decapsulate(serverExchangeValue, 0, _mlkemDecapsulator.EncapsulationLength, mlkemSecret, 0, _mlkemDecapsulator.SecretLength); |
127 | 135 |
|
128 |
| - var x25519PublicKey = new X25519PublicKeyParameters(serverExchangeValue, _mlkemDecapsulator.EncapsulationLength); |
129 |
| - _x25519Agreement.CalculateAgreement(x25519PublicKey, secret, _mlkemDecapsulator.SecretLength); |
| 136 | + var x25519Agreement = _impl.CalculateAgreement(serverExchangeValue.Take(_mlkemDecapsulator.EncapsulationLength, X25519PublicKeyParameters.KeySize)); |
130 | 137 |
|
131 |
| - SharedKey = CryptoAbstraction.HashSHA256(secret); |
| 138 | + SharedKey = mlkemSecret.Concat(x25519Agreement); |
| 139 | + } |
| 140 | + |
| 141 | + /// <inheritdoc/> |
| 142 | + protected override void Dispose(bool disposing) |
| 143 | + { |
| 144 | + base.Dispose(disposing); |
| 145 | + |
| 146 | + if (disposing) |
| 147 | + { |
| 148 | + _impl?.Dispose(); |
| 149 | + } |
132 | 150 | }
|
133 | 151 | }
|
134 | 152 | }
|
0 commit comments