Skip to content

Commit

Permalink
PrivateKeyCredential: fix issue when loading some RSA keys.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmds committed Dec 12, 2024
1 parent f4501c5 commit 7620058
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
19 changes: 19 additions & 0 deletions src/Tmds.Ssh/BigIntegerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Tmds.Ssh;

static class BigIntegerExtensions
{
public static byte[] ToBEByteArray(this BigInteger integer, bool isUnsigned, int minLength)

Check failure on line 5 in src/Tmds.Ssh/BigIntegerExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'BigInteger' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in src/Tmds.Ssh/BigIntegerExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'BigInteger' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in src/Tmds.Ssh/BigIntegerExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'BigInteger' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 5 in src/Tmds.Ssh/BigIntegerExtensions.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'BigInteger' could not be found (are you missing a using directive or an assembly reference?)
{
int bytesNeeded = integer.GetByteCount(isUnsigned);
int length = Math.Max(bytesNeeded, minLength);
byte[] array = new byte[length];
int prefixLength = length - bytesNeeded;
bool success = integer.TryWriteBytes(array.AsSpan(prefixLength), out _, isUnsigned, isBigEndian: true);
Debug.Assert(success); // Can't fail since the array is large enough.
if (prefixLength != 0 && integer.Sign < 0)
{
array.AsSpan(0, prefixLength).Fill(0xff);
}
return array;
}
}
17 changes: 11 additions & 6 deletions src/Tmds.Ssh/PrivateKeyParser.OpenSsh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,14 @@ uint32 rounds

private static PrivateKey ParseOpenSshRsaKey(SequenceReader reader)
{
// .NET RSA's class has some length expectations:
// D must have the same length as Modulus.
// P, Q, DP, DQ, and InverseQ must have half the length of Modulus rounded up.
byte[] modulus = reader.ReadMPIntAsByteArray(isUnsigned: true);
int halfLength = (modulus.Length + 1) / 2;
byte[] exponent = reader.ReadMPIntAsByteArray(isUnsigned: true);
BigInteger d = reader.ReadMPInt();
byte[] inverseQ = reader.ReadMPIntAsByteArray(isUnsigned: true);
byte[] inverseQ = reader.ReadMPIntAsByteArray(isUnsigned: true, minLength: halfLength);
BigInteger p = reader.ReadMPInt();
BigInteger q = reader.ReadMPInt();

Expand All @@ -182,12 +186,13 @@ private static PrivateKey ParseOpenSshRsaKey(SequenceReader reader)
{
Modulus = modulus,
Exponent = exponent,
D = d.ToByteArray(isUnsigned: true, isBigEndian: true),
D = d.ToBEByteArray(isUnsigned: true, minLength: modulus.Length),
InverseQ = inverseQ,
P = p.ToByteArray(isUnsigned: true, isBigEndian: true),
Q = q.ToByteArray(isUnsigned: true, isBigEndian: true),
DP = dp.ToByteArray(isUnsigned: true, isBigEndian: true),
DQ = dq.ToByteArray(isUnsigned: true, isBigEndian: true)

P = p.ToBEByteArray(isUnsigned: true, minLength: halfLength),
Q = q.ToBEByteArray(isUnsigned: true, minLength: halfLength),
DP = dp.ToBEByteArray(isUnsigned: true, minLength: halfLength),
DQ = dq.ToBEByteArray(isUnsigned: true, minLength: halfLength)
};
RSA rsa = RSA.Create();
try
Expand Down

0 comments on commit 7620058

Please sign in to comment.