using System;
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography;
namespace Renci.SshNet.Security
{
///
/// Contains RSA private and public key
///
public class RsaKey : Key, IDisposable
{
private bool _isDisposed;
///
/// Gets the Key String.
///
public override string ToString()
{
return "ssh-rsa";
}
///
/// Gets the modulus.
///
public BigInteger Modulus
{
get
{
return _privateKey[0];
}
}
///
/// Gets the exponent.
///
public BigInteger Exponent
{
get
{
return _privateKey[1];
}
}
///
/// Gets the D.
///
public BigInteger D
{
get
{
if (_privateKey.Length > 2)
{
return _privateKey[2];
}
return BigInteger.Zero;
}
}
///
/// Gets the P.
///
public BigInteger P
{
get
{
if (_privateKey.Length > 3)
{
return _privateKey[3];
}
return BigInteger.Zero;
}
}
///
/// Gets the Q.
///
public BigInteger Q
{
get
{
if (_privateKey.Length > 4)
{
return _privateKey[4];
}
return BigInteger.Zero;
}
}
///
/// Gets the DP.
///
public BigInteger DP
{
get
{
if (_privateKey.Length > 5)
{
return _privateKey[5];
}
return BigInteger.Zero;
}
}
///
/// Gets the DQ.
///
public BigInteger DQ
{
get
{
if (_privateKey.Length > 6)
{
return _privateKey[6];
}
return BigInteger.Zero;
}
}
///
/// Gets the inverse Q.
///
public BigInteger InverseQ
{
get
{
if (_privateKey.Length > 7)
{
return _privateKey[7];
}
return BigInteger.Zero;
}
}
///
/// Gets the length of the key.
///
///
/// The length of the key.
///
public override int KeyLength
{
get
{
return Modulus.BitLength;
}
}
private RsaDigitalSignature _digitalSignature;
///
/// Gets the digital signature.
///
protected override DigitalSignature DigitalSignature
{
get
{
_digitalSignature ??= new RsaDigitalSignature(this);
return _digitalSignature;
}
}
///
/// Gets or sets the public.
///
///
/// The public.
///
public override BigInteger[] Public
{
get
{
return new[] { Exponent, Modulus };
}
set
{
if (value.Length != 2)
{
throw new InvalidOperationException("Invalid private key.");
}
_privateKey = new[] { value[1], value[0] };
}
}
///
/// Initializes a new instance of the class.
///
public RsaKey()
{
}
///
/// Initializes a new instance of the class.
///
/// DER encoded private key data.
public RsaKey(byte[] data)
: base(data)
{
if (_privateKey.Length != 8)
{
throw new InvalidOperationException("Invalid private key.");
}
}
///
/// Initializes a new instance of the class.
///
/// The modulus.
/// The exponent.
/// The d.
/// The p.
/// The q.
/// The inverse Q.
public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger p, BigInteger q, BigInteger inverseQ)
{
_privateKey = new BigInteger[8]
{
modulus,
exponent,
d,
p,
q,
PrimeExponent(d, p),
PrimeExponent(d, q),
inverseQ
};
}
private static BigInteger PrimeExponent(BigInteger privateExponent, BigInteger prime)
{
var pe = prime - new BigInteger(1);
return privateExponent % pe;
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (_isDisposed)
{
return;
}
if (disposing)
{
var digitalSignature = _digitalSignature;
if (digitalSignature != null)
{
digitalSignature.Dispose();
_digitalSignature = null;
}
_isDisposed = true;
}
}
///
/// Releases unmanaged resources and performs other cleanup operations before the
/// is reclaimed by garbage collection.
///
~RsaKey()
{
Dispose(disposing: false);
}
}
}