RsaKey
Contains the RSA private and public key.
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography;
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
namespace Renci.SshNet.Security
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class RsaKey : Key, IDisposable
{
[System.Runtime.CompilerServices.Nullable(2)]
private RsaDigitalSignature _digitalSignature;
internal RSA RSA { get; }
public BigInteger Modulus { get; }
public BigInteger Exponent { get; }
public BigInteger D { get; }
public BigInteger P { get; }
public BigInteger Q { get; }
public BigInteger DP { get; }
public BigInteger DQ { get; }
public BigInteger InverseQ { get; }
public override int KeyLength => Modulus.BitLength;
protected internal override DigitalSignature DigitalSignature {
get {
if (_digitalSignature == null)
_digitalSignature = new RsaDigitalSignature(this);
return _digitalSignature;
}
}
public override BigInteger[] Public => new BigInteger[2] {
Exponent,
Modulus
};
public override string ToString()
{
return "ssh-rsa";
}
public RsaKey(SshKeyData publicKeyData)
{
if (publicKeyData == null)
throw new ArgumentNullException("publicKeyData");
if (publicKeyData.Name != "ssh-rsa" || publicKeyData.Keys.Length != 2)
throw new ArgumentException($"""{publicKeyData.Name}""{publicKeyData.Keys.Length}""", "publicKeyData");
Exponent = publicKeyData.Keys[0];
Modulus = publicKeyData.Keys[1];
RSA = RSA.Create();
RSA.ImportParameters(GetRSAParameters());
}
public RsaKey(byte[] privateKeyData)
{
if (privateKeyData == null)
throw new ArgumentNullException("privateKeyData");
DerData derData = new DerData(privateKeyData, false);
derData.ReadBigInteger();
Modulus = derData.ReadBigInteger();
Exponent = derData.ReadBigInteger();
D = derData.ReadBigInteger();
P = derData.ReadBigInteger();
Q = derData.ReadBigInteger();
DP = derData.ReadBigInteger();
DQ = derData.ReadBigInteger();
InverseQ = derData.ReadBigInteger();
if (!derData.IsEndOfData)
throw new InvalidOperationException("Invalid private key (expected EOF).");
RSA = RSA.Create();
RSA.ImportParameters(GetRSAParameters());
}
public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger p, BigInteger q, BigInteger inverseQ)
{
Modulus = modulus;
Exponent = exponent;
D = d;
P = p;
Q = q;
DP = PrimeExponent(d, p);
DQ = PrimeExponent(d, q);
InverseQ = inverseQ;
RSA = RSA.Create();
RSA.ImportParameters(GetRSAParameters());
}
internal RSAParameters GetRSAParameters()
{
RSAParameters result;
if (D.IsZero) {
result = default(RSAParameters);
result.Modulus = Modulus.ToByteArray(true, true);
result.Exponent = Exponent.ToByteArray(true, true);
return result;
}
byte[] array = Modulus.ToByteArray(true, true);
int length = (array.Length + 1) / 2;
result = default(RSAParameters);
result.Modulus = array;
result.Exponent = Exponent.ToByteArray(true, true);
result.D = D.ExportKeyParameter(array.Length);
result.P = P.ExportKeyParameter(length);
result.Q = Q.ExportKeyParameter(length);
result.DP = DP.ExportKeyParameter(length);
result.DQ = DQ.ExportKeyParameter(length);
result.InverseQ = InverseQ.ExportKeyParameter(length);
return result;
}
private static BigInteger PrimeExponent(BigInteger privateExponent, BigInteger prime)
{
BigInteger divisor = prime - BigInteger.One;
return privateExponent % divisor;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing) {
_digitalSignature?.Dispose();
RSA.Dispose();
}
}
}
}