Skip to content

Commit d06dfa5

Browse files
authored
Use System.Numerics.BigInteger (#1469)
Instead of the point-in-time copy
1 parent fe827a5 commit d06dfa5

30 files changed

+221
-6915
lines changed

src/Renci.SshNet/Common/BigInteger.cs

Lines changed: 0 additions & 4956 deletions
This file was deleted.

src/Renci.SshNet/Common/DerData.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Buffers.Binary;
33
using System.Collections.Generic;
4+
using System.Numerics;
45

56
namespace Renci.SshNet.Common
67
{
@@ -96,7 +97,11 @@ public BigInteger ReadBigInteger()
9697

9798
var data = ReadBytes(length);
9899

100+
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
101+
return new BigInteger(data, isBigEndian: true);
102+
#else
99103
return new BigInteger(data.Reverse());
104+
#endif
100105
}
101106

102107
/// <summary>
@@ -213,7 +218,7 @@ public void Write(uint data)
213218
/// <param name="data">BigInteger data to write.</param>
214219
public void Write(BigInteger data)
215220
{
216-
var bytes = data.ToByteArray().Reverse();
221+
var bytes = data.ToByteArray(isBigEndian: true);
217222
_data.Add(Integer);
218223
var length = GetLength(bytes.Length);
219224
WriteBytes(length);

src/Renci.SshNet/Common/Extensions.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Globalization;
55
using System.Net;
66
using System.Net.Sockets;
7+
using System.Numerics;
78
using System.Text;
89

910
using Renci.SshNet.Abstractions;
@@ -14,7 +15,7 @@ namespace Renci.SshNet.Common
1415
/// <summary>
1516
/// Collection of different extension methods.
1617
/// </summary>
17-
internal static partial class Extensions
18+
internal static class Extensions
1819
{
1920
internal static byte[] ToArray(this ServiceName serviceName)
2021
{
@@ -45,26 +46,35 @@ internal static ServiceName ToServiceName(this byte[] data)
4546

4647
internal static BigInteger ToBigInteger(this byte[] data)
4748
{
49+
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
50+
return new BigInteger(data, isBigEndian: true);
51+
#else
4852
var reversed = new byte[data.Length];
4953
Buffer.BlockCopy(data, 0, reversed, 0, data.Length);
5054
return new BigInteger(reversed.Reverse());
55+
#endif
5156
}
5257

5358
/// <summary>
5459
/// Initializes a new instance of the <see cref="BigInteger"/> structure using the SSH BigNum2 Format.
5560
/// </summary>
5661
public static BigInteger ToBigInteger2(this byte[] data)
5762
{
63+
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
64+
return new BigInteger(data, isBigEndian: true, isUnsigned: true);
65+
#else
5866
if ((data[0] & (1 << 7)) != 0)
5967
{
6068
var buf = new byte[data.Length + 1];
6169
Buffer.BlockCopy(data, 0, buf, 1, data.Length);
62-
data = buf;
70+
return new BigInteger(buf.Reverse());
6371
}
6472

6573
return data.ToBigInteger();
74+
#endif
6675
}
6776

77+
#if NETFRAMEWORK || NETSTANDARD2_0
6878
public static byte[] ToByteArray(this BigInteger bigInt, bool isUnsigned = false, bool isBigEndian = false)
6979
{
7080
var data = bigInt.ToByteArray();
@@ -81,6 +91,15 @@ public static byte[] ToByteArray(this BigInteger bigInt, bool isUnsigned = false
8191

8292
return data;
8393
}
94+
#endif
95+
96+
#if !NET6_0_OR_GREATER
97+
public static long GetBitLength(this BigInteger bigint)
98+
{
99+
// Taken from https://github.com/dotnet/runtime/issues/31308
100+
return (long)Math.Ceiling(BigInteger.Log(bigint.Sign < 0 ? -bigint : bigint + 1, 2));
101+
}
102+
#endif
84103

85104
// See https://github.com/dotnet/runtime/blob/9b57a265c7efd3732b035bade005561a04767128/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs#L51
86105
public static byte[] ExportKeyParameter(this BigInteger value, int length)

src/Renci.SshNet/Common/SshData.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Numerics;
34
using System.Text;
45

56
namespace Renci.SshNet.Common

src/Renci.SshNet/Common/SshDataStream.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Globalization;
33
using System.IO;
4+
using System.Numerics;
45
using System.Text;
56

67
namespace Renci.SshNet.Common
@@ -110,7 +111,8 @@ public void Write(ulong value)
110111
/// <param name="data">The <see cref="BigInteger" /> to write.</param>
111112
public void Write(BigInteger data)
112113
{
113-
var bytes = data.ToByteArray().Reverse();
114+
var bytes = data.ToByteArray(isBigEndian: true);
115+
114116
WriteBinary(bytes, 0, bytes.Length);
115117
}
116118

@@ -211,9 +213,13 @@ public void WriteBinary(byte[] buffer, int offset, int count)
211213
/// </returns>
212214
public BigInteger ReadBigInt()
213215
{
214-
var length = ReadUInt32();
215-
var data = ReadBytes((int)length);
216+
var data = ReadBinary();
217+
218+
#if NETSTANDARD2_1_OR_GREATER || NET6_0_OR_GREATER
219+
return new BigInteger(data, isBigEndian: true);
220+
#else
216221
return new BigInteger(data.Reverse());
222+
#endif
217223
}
218224

219225
/// <summary>

src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeGroup.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Renci.SshNet.Common;
1+
using System.Numerics;
2+
3+
using Renci.SshNet.Common;
24

35
namespace Renci.SshNet.Messages.Transport
46
{

src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
22

3-
using Renci.SshNet.Common;
4-
53
namespace Renci.SshNet.Messages.Transport
64
{
75
/// <summary>
@@ -57,21 +55,6 @@ public KeyExchangeEcdhInitMessage(byte[] q)
5755
QC = q;
5856
}
5957

60-
/// <summary>
61-
/// Initializes a new instance of the <see cref="KeyExchangeEcdhInitMessage"/> class.
62-
/// </summary>
63-
public KeyExchangeEcdhInitMessage(BigInteger d, BigInteger q)
64-
{
65-
var dBytes = d.ToByteArray().Reverse();
66-
var qBytes = q.ToByteArray().Reverse();
67-
68-
var data = new byte[dBytes.Length + qBytes.Length + 1];
69-
data[0] = 0x04;
70-
Buffer.BlockCopy(dBytes, 0, data, 1, dBytes.Length);
71-
Buffer.BlockCopy(qBytes, 0, data, dBytes.Length + 1, qBytes.Length);
72-
QC = data;
73-
}
74-
7558
/// <summary>
7659
/// Called when type specific data need to be loaded.
7760
/// </summary>

src/Renci.SshNet/PrivateKeyFile.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Diagnostics;
44
using System.Globalization;
55
using System.IO;
6+
using System.Numerics;
67
using System.Security.Cryptography;
78
using System.Text;
89
using System.Text.RegularExpressions;
@@ -713,22 +714,17 @@ public BigInteger ReadBigIntWithBits()
713714

714715
length = (length + 7) / 8;
715716

716-
var data = base.ReadBytes(length);
717-
var bytesArray = new byte[data.Length + 1];
718-
Buffer.BlockCopy(data, 0, bytesArray, 1, data.Length);
719-
720-
return new BigInteger(bytesArray.Reverse());
717+
return base.ReadBytes(length).ToBigInteger2();
721718
}
722719

723720
public BigInteger ReadBignum()
724721
{
725-
return new BigInteger(ReadBignum2().Reverse());
722+
return DataStream.ReadBigInt();
726723
}
727724

728725
public byte[] ReadBignum2()
729726
{
730-
var length = (int)base.ReadUInt32();
731-
return base.ReadBytes(length);
727+
return ReadBinary();
732728
}
733729

734730
protected override void LoadData()

src/Renci.SshNet/Security/Cryptography/DsaKey.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#nullable enable
22
using System;
3+
using System.Numerics;
34
using System.Security.Cryptography;
45

56
using Renci.SshNet.Common;
@@ -46,7 +47,7 @@ public override int KeyLength
4647
{
4748
get
4849
{
49-
return P.BitLength;
50+
return (int)P.GetBitLength();
5051
}
5152
}
5253

src/Renci.SshNet/Security/Cryptography/ED25519Key.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Numerics;
23

34
using Org.BouncyCastle.Math.EC.Rfc8032;
45

@@ -87,7 +88,8 @@ public ED25519Key(SshKeyData publicKeyData)
8788
throw new ArgumentException($"Invalid Ed25519 public key data ({publicKeyData.Name}, {publicKeyData.Keys.Length}).", nameof(publicKeyData));
8889
}
8990

90-
PublicKey = publicKeyData.Keys[0].ToByteArray().Reverse().TrimLeadingZeros().Pad(Ed25519.PublicKeySize);
91+
PublicKey = publicKeyData.Keys[0].ToByteArray(isBigEndian: true).TrimLeadingZeros().Pad(Ed25519.PublicKeySize);
92+
PrivateKey = new byte[Ed25519.SecretKeySize];
9193
}
9294

9395
/// <summary>

0 commit comments

Comments
 (0)