RsaKey
Contains the RSA private and public key.
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography;
using System;
using System.Formats.Asn1;
using System.Numerics;
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 => (int)Extensions.GetBitLength(Modulus);
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)
{
ThrowHelper.ThrowIfNull(publicKeyData, "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)
{
ThrowHelper.ThrowIfNull(privateKeyData, "privateKeyData");
AsnReader asnReader = new AsnReader(privateKeyData, AsnEncodingRules.DER, default(AsnReaderOptions)).ReadSequence(null);
asnReader.ReadInteger(null);
Modulus = asnReader.ReadInteger(null);
Exponent = asnReader.ReadInteger(null);
D = asnReader.ReadInteger(null);
P = asnReader.ReadInteger(null);
Q = asnReader.ReadInteger(null);
DP = asnReader.ReadInteger(null);
DQ = asnReader.ReadInteger(null);
InverseQ = asnReader.ReadInteger(null);
asnReader.ThrowIfNotEmpty();
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 = Extensions.ToByteArray(Modulus, true, true);
result.Exponent = Extensions.ToByteArray(Exponent, true, true);
return result;
}
byte[] array = Extensions.ToByteArray(Modulus, true, true);
int length = (array.Length + 1) / 2;
result = default(RSAParameters);
result.Modulus = array;
result.Exponent = Extensions.ToByteArray(Exponent, 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();
}
}
}
}