Repalce PrivateKey and Signature classes with CryptoKey classes

This commit is contained in:
olegkap_cp
2010-08-16 18:12:21 +00:00
parent d8795e852e
commit 97ab16e013
13 changed files with 360 additions and 373 deletions
+12 -5
View File
@@ -14,13 +14,15 @@ namespace Renci.SshClient
private Regex _headerLineContinue = new Regex(@"(?<headerValue>[^:]+(?<continue>\\)?)");
private Regex _endKeyLine = new Regex(@"----[ ]*END (?<keyName>.+) PRIVATE KEY[ ]*----");
private PrivateKey _key;
//private PrivateKey _key;
private CryptoPrivateKey _key;
public string AlgorithmName
{
get
{
return this._key.AlgorithmName;
return this._key.Name;
//return this._key.AlgorithmName;
}
}
@@ -28,7 +30,8 @@ namespace Renci.SshClient
{
get
{
return this._key.PublicKey;
return this._key.GetPublicKey().GetBytes();
//return this._key.PublicKey;
}
}
@@ -119,15 +122,19 @@ namespace Renci.SshClient
switch (keyName)
{
case "RSA":
this._key = new PrivateKeyRsa(System.Convert.FromBase64String(data.ToString()));
//this._key = new PrivateKeyRsa(System.Convert.FromBase64String(data.ToString()));
this._key = new CryptoPrivateKeyRsa();
break;
case "DSA":
this._key = new PrivateKeyDsa(System.Convert.FromBase64String(data.ToString()));
//this._key = new PrivateKeyDsa(System.Convert.FromBase64String(data.ToString()));
this._key = new CryptoPrivateKeyDss();
break;
default:
throw new NotSupportedException(string.Format("Key '{0}' is not supported.", keyName));
}
this._key.Load(System.Convert.FromBase64String(data.ToString()));
}
}
@@ -106,17 +106,18 @@
<Compile Include="Messages\Sftp\StatusMessage.cs" />
<Compile Include="Messages\Sftp\VersionMessage.cs" />
<Compile Include="Messages\Sftp\WriteMessage.cs" />
<Compile Include="Security\PrivateKey.cs" />
<Compile Include="Security\CryptoKey.cs" />
<Compile Include="Security\CryptoPrivateKey.cs" />
<Compile Include="Security\CryptoPrivateKeyDss.cs" />
<Compile Include="Security\CryptoPrivateKeyRsa.cs" />
<Compile Include="Security\CryptoPublicKey.cs" />
<Compile Include="Security\CryptoPublicKeyDss.cs" />
<Compile Include="Security\CryptoPublicKeyRsa.cs" />
<Compile Include="Security\KeyExchange.cs" />
<Compile Include="Security\KeyExchangeCompletedEventArgs.cs" />
<Compile Include="Security\KeyExchangeDiffieHellman.cs" />
<Compile Include="Security\KeyExchangeFailedEventArgs.cs" />
<Compile Include="Security\KeyExchangeSendMessageEventArgs.cs" />
<Compile Include="Security\PrivateKeyDsa.cs" />
<Compile Include="Security\PrivateKeyRsa.cs" />
<Compile Include="Security\Signature.cs" />
<Compile Include="Security\SignatureDss.cs" />
<Compile Include="Security\SignatureRsa.cs" />
<Compile Include="KeyFile.cs" />
<Compile Include="Messages\Connection\ChannelMessage.cs" />
<Compile Include="Messages\Connection\RequestNames.cs" />
@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Renci.SshClient.Security
{
public abstract class CryptoKey
{
public abstract string Name { get; }
public abstract void Load(IEnumerable<byte> data);
public abstract bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature);
public abstract IEnumerable<byte> GetBytes();
}
}
@@ -3,20 +3,11 @@ using Renci.SshClient.Common;
namespace Renci.SshClient.Security
{
internal abstract class PrivateKey
public abstract class CryptoPrivateKey : CryptoKey
{
public abstract string AlgorithmName { get; }
public abstract CryptoPublicKey GetPublicKey();
protected IEnumerable<byte> Data { get; private set; }
public abstract IEnumerable<byte> PublicKey { get; }
public PrivateKey(IEnumerable<byte> data)
{
this.Data = data;
}
public abstract IEnumerable<byte> GetSignature(IEnumerable<byte> sessionId);
public abstract IEnumerable<byte> GetSignature(IEnumerable<byte> key);
protected class SignatureKeyData : SshData
{
@@ -34,6 +25,5 @@ namespace Renci.SshClient.Security
this.Write(this.Signature.GetSshString());
}
}
}
}
@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
namespace Renci.SshClient.Security
{
public class CryptoPrivateKeyDss : CryptoPrivateKey
{
private byte[] _p;
private byte[] _q;
private byte[] _g;
private byte[] _x;
private byte[] _publicKey;
public override string Name
{
get { return "ssh-dss"; }
}
public override void Load(IEnumerable<byte> data)
{
using (var ms = new MemoryStream(data.ToArray()))
using (var binr = new BinaryReader(ms)) //wrap Memory Stream with BinaryReader for easy reading
{
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
throw new InvalidOperationException("Not valid DSS Key.");
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
throw new NotSupportedException("Not supported DSS Key version.");
bt = binr.ReadByte();
if (bt != 0x00)
throw new InvalidOperationException("Not valid DSS Key.");
//------ all private key components are Integer sequences ----
elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
this._p = binr.ReadBytes(elems);
elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
this._q = binr.ReadBytes(elems);
elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
this._g = binr.ReadBytes(elems);
elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
this._publicKey = binr.ReadBytes(elems);
elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
this._x = binr.ReadBytes(elems);
}
}
public override CryptoPublicKey GetPublicKey()
{
return new CryptoPublicKeyDss();
}
public override IEnumerable<byte> GetSignature(IEnumerable<byte> key)
{
var data = key.ToArray();
using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
{
DSAParameters DSAKeyInfo = new DSAParameters();
DSAKeyInfo.X = this._x.TrimLeadinZero().ToArray();
DSAKeyInfo.P = this._p.TrimLeadinZero().ToArray();
DSAKeyInfo.Q = this._q.TrimLeadinZero().ToArray();
DSAKeyInfo.G = this._g.TrimLeadinZero().ToArray();
cs.Write(data, 0, data.Length);
cs.Close();
var DSA = new System.Security.Cryptography.DSACryptoServiceProvider();
DSA.ImportParameters(DSAKeyInfo);
var DSAFormatter = new RSAPKCS1SignatureFormatter(DSA);
DSAFormatter.SetHashAlgorithm("SHA1");
var signature = DSAFormatter.CreateSignature(sha1);
return new SignatureKeyData
{
AlgorithmName = this.Name,
Signature = signature,
}.GetBytes();
}
}
public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
{
throw new NotImplementedException();
}
public override IEnumerable<byte> GetBytes()
{
throw new NotImplementedException();
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
return count;
}
}
}
@@ -3,74 +3,99 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Renci.SshClient.Common;
namespace Renci.SshClient.Security
{
internal class PrivateKeyRsa : PrivateKey
public class CryptoPrivateKeyRsa : CryptoPrivateKey
{
private byte[] _modulus;
private byte[] _eValue;
private byte[] _exponent;
private byte[] _dValue;
private byte[] _pValue;
private byte[] _qValue;
private byte[] _dpValue;
private byte[] _dqValue;
private byte[] _iqValue;
private byte[] _inverseQ;
private IEnumerable<byte> _publicKey;
/// <summary>
/// Gets the public key.
/// </summary>
/// <value>The public key.</value>
public override IEnumerable<byte> PublicKey
{
get
{
if (this._publicKey == null)
{
this._publicKey = new RsaPublicKeyData
{
E = this._eValue,
Modulus = this._modulus,
}.GetBytes();
}
return this._publicKey;
}
}
public override string AlgorithmName
public override string Name
{
get { return "ssh-rsa"; }
}
public PrivateKeyRsa(IEnumerable<byte> data)
: base(data)
public override void Load(IEnumerable<byte> data)
{
if (!this.ParseRSAPrivateKey())
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
using (var ms = new MemoryStream(data.ToArray()))
using (var binr = new BinaryReader(ms)) //wrap Memory Stream with BinaryReader for easy reading
{
throw new InvalidDataException("RSA Key is not valid");
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
throw new InvalidOperationException("Not valid RSA Key.");
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
throw new NotSupportedException("Not supported RSA Key version.");
bt = binr.ReadByte();
if (bt != 0x00)
throw new InvalidOperationException("Not valid RSA Key.");
//------ all private key components are Integer sequences ----
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._modulus = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._exponent = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._dValue = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._pValue = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._qValue = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._dpValue = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._dqValue = binr.ReadBytes(elems);
elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
this._inverseQ = binr.ReadBytes(elems);
}
}
public override IEnumerable<byte> GetSignature(IEnumerable<byte> sessionId)
public override CryptoPublicKey GetPublicKey()
{
var data = sessionId.ToArray();
return new CryptoPublicKeyRsa(this._modulus, this._exponent);
}
public override IEnumerable<byte> GetSignature(IEnumerable<byte> key)
{
var data = key.ToArray();
using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
{
RSAParameters RSAKeyInfo = new RSAParameters();
RSAKeyInfo.Exponent = _eValue.TrimLeadinZero().ToArray();
RSAKeyInfo.Exponent = _exponent.TrimLeadinZero().ToArray();
RSAKeyInfo.D = _dValue.TrimLeadinZero().ToArray();
RSAKeyInfo.Modulus = _modulus.TrimLeadinZero().ToArray();
RSAKeyInfo.P = _pValue.TrimLeadinZero().ToArray();
RSAKeyInfo.Q = _qValue.TrimLeadinZero().ToArray();
RSAKeyInfo.DP = _dpValue.TrimLeadinZero().ToArray();
RSAKeyInfo.DQ = _dqValue.TrimLeadinZero().ToArray();
RSAKeyInfo.InverseQ = _iqValue.TrimLeadinZero().ToArray();
RSAKeyInfo.InverseQ = _inverseQ.TrimLeadinZero().ToArray();
cs.Write(data, 0, data.Length);
@@ -85,66 +110,20 @@ namespace Renci.SshClient.Security
return new SignatureKeyData
{
AlgorithmName = this.AlgorithmName,
AlgorithmName = this.Name,
Signature = signature,
}.GetBytes();
}
}
private bool ParseRSAPrivateKey()
public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
{
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
using (var ms = new MemoryStream(this.Data.ToArray()))
using (var binr = new BinaryReader(ms)) //wrap Memory Stream with BinaryReader for easy reading
{
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
throw new NotImplementedException();
}
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return false;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return false;
bt = binr.ReadByte();
if (bt != 0x00)
return false;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
this._modulus = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._eValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._dValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._pValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._qValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._dpValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._dqValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._iqValue = binr.ReadBytes(elems);
return true;
}
public override IEnumerable<byte> GetBytes()
{
throw new NotImplementedException();
}
private static int GetIntegerSize(BinaryReader binr)
@@ -175,23 +154,5 @@ namespace Renci.SshClient.Security
return count;
}
private class RsaPublicKeyData : SshData
{
public IEnumerable<byte> Modulus { get; set; }
public IEnumerable<byte> E { get; set; }
protected override void LoadData()
{
}
protected override void SaveData()
{
this.Write("ssh-rsa");
this.Write(this.E.GetSshString());
this.Write(this.Modulus.GetSshString());
}
}
}
}
@@ -0,0 +1,6 @@
namespace Renci.SshClient.Security
{
public abstract class CryptoPublicKey : CryptoKey
{
}
}
@@ -1,41 +1,62 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
namespace Renci.SshClient.Security
{
internal class SignatureDss : Signature
public class CryptoPublicKeyDss : CryptoPublicKey
{
private IEnumerable<byte> _p;
private IEnumerable<byte> _q;
private IEnumerable<byte> _g;
private IEnumerable<byte> _x;
public override string Name
{
get { return "ssh-dss"; }
get { throw new NotImplementedException(); }
}
public SignatureDss(IEnumerable<byte> data)
: base(data)
public CryptoPublicKeyDss()
{
}
public override bool ValidateSignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
public CryptoPublicKeyDss(IEnumerable<byte> p, IEnumerable<byte> q, IEnumerable<byte> g, IEnumerable<byte> x)
{
var pLength = BitConverter.ToUInt32(this.Data.Take(4).Reverse().ToArray(), 0);
this._p = p;
this._q = q;
this._g = g;
this._x = x;
}
var pData = this.Data.Skip(4).Take((int)pLength).ToArray();
public override void Load(IEnumerable<byte> data)
{
using (var ms = new MemoryStream(data.ToArray()))
using (var br = new BinaryReader(ms))
{
var qLength = BitConverter.ToUInt32(this.Data.Skip(4 + (int)pLength).Take(4).Reverse().ToArray(), 0);
var pl = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
var qData = this.Data.Skip(4 + (int)pLength + 4).Take((int)qLength).ToArray();
_p = br.ReadBytes((int)pl);
var gLength = BitConverter.ToUInt32(this.Data.Skip(4 + (int)pLength + 4 + (int)qLength).Take(4).Reverse().ToArray(), 0);
var ql = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
var gData = this.Data.Skip(4 + (int)pLength + 4 + (int)qLength + 4).Take((int)gLength).ToArray();
_q = br.ReadBytes((int)ql);
var xLength = BitConverter.ToUInt32(this.Data.Skip(4 + (int)pLength + 4 + (int)qLength + 4 + (int)gLength).Take(4).Reverse().ToArray(), 0);
var gl = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
var xData = this.Data.Skip(4 + (int)pLength + 4 + (int)qLength + 4 + (int)xLength + 4).Take((int)xLength).ToArray();
_g = br.ReadBytes((int)gl);
var xl = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
_x = br.ReadBytes((int)xl);
}
}
public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
{
using (var sha1 = new SHA1CryptoServiceProvider())
{
using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
@@ -49,10 +70,10 @@ namespace Renci.SshClient.Security
{
dsa.ImportParameters(new DSAParameters
{
X = xData.TrimLeadinZero().ToArray(),
P = pData.TrimLeadinZero().ToArray(),
Q = qData.TrimLeadinZero().ToArray(),
G = gData.TrimLeadinZero().ToArray(),
X = _x.TrimLeadinZero().ToArray(),
P = _p.TrimLeadinZero().ToArray(),
Q = _q.TrimLeadinZero().ToArray(),
G = _g.TrimLeadinZero().ToArray(),
});
var dsaDeformatter = new DSASignatureDeformatter(dsa);
dsaDeformatter.SetHashAlgorithm("SHA1");
@@ -87,5 +108,10 @@ namespace Renci.SshClient.Security
}
}
}
public override IEnumerable<byte> GetBytes()
{
throw new NotImplementedException();
}
}
}
@@ -1,33 +1,51 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Renci.SshClient.Common;
namespace Renci.SshClient.Security
{
internal class SignatureRsa : Signature
public class CryptoPublicKeyRsa : CryptoPublicKey
{
private IEnumerable<byte> _modulus;
private IEnumerable<byte> _exponent;
public override string Name
{
get { return "ssh-rsa"; }
}
public SignatureRsa(IEnumerable<byte> data)
: base(data)
public CryptoPublicKeyRsa()
{
}
public override bool ValidateSignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
internal CryptoPublicKeyRsa(IEnumerable<byte> modulus, IEnumerable<byte> exponent)
{
var exponentLength = BitConverter.ToUInt32(this.Data.Take(4).Reverse().ToArray(), 0);
this._modulus = modulus;
this._exponent = exponent;
}
var exponentData = this.Data.Skip(4).Take((int)exponentLength).ToArray();
public override void Load(IEnumerable<byte> data)
{
using (var ms = new MemoryStream(data.ToArray()))
using (var br = new BinaryReader(ms))
{
var modulusLength = BitConverter.ToUInt32(this.Data.Skip(4 + (int)exponentLength).Take(4).Reverse().ToArray(), 0);
var el = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
var modulusData = this.Data.Skip(4 + (int)exponentLength + 4).Take((int)modulusLength).ToArray();
this._exponent = br.ReadBytes((int)el);
var ml = BitConverter.ToUInt32(br.ReadBytes(4).Reverse().ToArray(), 0);
this._modulus = br.ReadBytes((int)ml);
}
}
public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
{
using (var sha1 = new SHA1CryptoServiceProvider())
{
using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
@@ -41,9 +59,10 @@ namespace Renci.SshClient.Security
{
rsa.ImportParameters(new RSAParameters
{
Exponent = exponentData,
Modulus = modulusData.TrimLeadinZero().ToArray(),
Exponent = this._exponent.TrimLeadinZero().ToArray(),
Modulus = this._modulus.TrimLeadinZero().ToArray(),
});
var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
rsaDeformatter.SetHashAlgorithm("SHA1");
@@ -77,5 +96,33 @@ namespace Renci.SshClient.Security
}
}
}
public override IEnumerable<byte> GetBytes()
{
return new RsaPublicKeyData
{
E = this._exponent,
Modulus = this._modulus,
}.GetBytes();
}
private class RsaPublicKeyData : SshData
{
public IEnumerable<byte> Modulus { get; set; }
public IEnumerable<byte> E { get; set; }
protected override void LoadData()
{
}
protected override void SaveData()
{
this.Write("ssh-rsa");
this.Write(this.E.GetSshString());
this.Write(this.Modulus.GetSshString());
}
}
}
}
@@ -296,9 +296,11 @@ namespace Renci.SshClient.Security
var data = bytes.Skip(4 + algorithmName.Length);
var signature = Settings.HostKeyAlgorithms[algorithmName](data);
CryptoPublicKey key = Settings.HostKeyAlgorithms[algorithmName]();
return signature.ValidateSignature(this.ExchangeHash, this.Signature.GetSshBytes());
key.Load(data);
return key.VerifySignature(this.ExchangeHash, this.Signature.GetSshBytes());
}
protected void SendMessage(Message message)
@@ -1,192 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using Renci.SshClient.Common;
namespace Renci.SshClient.Security
{
internal class PrivateKeyDsa : PrivateKey
{
private byte[] _pValue;
private byte[] _qValue;
private byte[] _gValue;
private byte[] _publicKeyValue;
private byte[] _privateKeyValue;
private IEnumerable<byte> _publicKey;
/// <summary>
/// Gets the public key.
/// </summary>
/// <value>The public key.</value>
public override IEnumerable<byte> PublicKey
{
get
{
if (this._publicKey == null)
{
this._publicKey = new DsaPublicKeyData
{
P = this._pValue,
Q = this._qValue,
G = this._gValue,
Public = this._publicKeyValue,
}.GetBytes();
}
return this._publicKey;
}
}
public override string AlgorithmName
{
get { return "ssh-dss"; }
}
public PrivateKeyDsa(IEnumerable<byte> data)
: base(data)
{
if (!this.ParseDSAPrivateKey())
{
throw new InvalidDataException("DSA Key is not valid");
}
}
public override IEnumerable<byte> GetSignature(IEnumerable<byte> sessionId)
{
var data = sessionId.ToArray();
using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
{
DSAParameters DSAKeyInfo = new DSAParameters();
DSAKeyInfo.X = this._privateKeyValue.TrimLeadinZero().ToArray();
DSAKeyInfo.P = this._pValue.TrimLeadinZero().ToArray();
DSAKeyInfo.Q = this._qValue.TrimLeadinZero().ToArray();
DSAKeyInfo.G = this._gValue.TrimLeadinZero().ToArray();
cs.Write(data, 0, data.Length);
cs.Close();
var DSA = new System.Security.Cryptography.DSACryptoServiceProvider();
DSA.ImportParameters(DSAKeyInfo);
var DSAFormatter = new RSAPKCS1SignatureFormatter(DSA);
DSAFormatter.SetHashAlgorithm("SHA1");
var signature = DSAFormatter.CreateSignature(sha1);
return new SignatureKeyData
{
AlgorithmName = this.AlgorithmName,
Signature = signature,
}.GetBytes();
}
}
private bool ParseDSAPrivateKey()
{
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
using (var ms = new MemoryStream(this.Data.ToArray()))
using (var binr = new BinaryReader(ms)) //wrap Memory Stream with BinaryReader for easy reading
{
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return false;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return false;
bt = binr.ReadByte();
if (bt != 0x00)
return false;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
this._pValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._qValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._gValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._publicKeyValue = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
this._privateKeyValue = binr.ReadBytes(elems);
}
return true;
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
return count;
}
private class DsaPublicKeyData : SshData
{
public IEnumerable<byte> P { get; set; }
public IEnumerable<byte> Q { get; set; }
public IEnumerable<byte> G { get; set; }
public IEnumerable<byte> Public { get; set; }
protected override void LoadData()
{
}
protected override void SaveData()
{
this.Write("ssh-dss");
this.Write(this.P.GetSshString());
this.Write(this.Q.GetSshString());
this.Write(this.G.GetSshString());
this.Write(this.Public.GetSshString());
}
}
}
}
@@ -1,16 +0,0 @@
using System.Collections.Generic;
namespace Renci.SshClient.Security
{
internal abstract class Signature : Algorithm
{
protected IEnumerable<byte> Data { get; private set; }
public Signature(IEnumerable<byte> data)
{
this.Data = data;
}
public abstract bool ValidateSignature(IEnumerable<byte> hash, IEnumerable<byte> signature);
}
}
+4 -5
View File
@@ -14,8 +14,7 @@ namespace Renci.SshClient
public static IDictionary<string, Func<IEnumerable<byte>, HMAC>> HmacAlgorithms { get; private set; }
public static IDictionary<string, Func<IEnumerable<byte>, Signature>> HostKeyAlgorithms { get; private set; }
public static IDictionary<string, Func<CryptoPublicKey>> HostKeyAlgorithms { get; private set; }
static Settings()
{
@@ -39,10 +38,10 @@ namespace Renci.SshClient
{"hmac-sha1", (key) => { return new System.Security.Cryptography.HMACSHA1(key.Take(20).ToArray());}},
};
Settings.HostKeyAlgorithms = new Dictionary<string, Func<IEnumerable<byte>, Signature>>()
Settings.HostKeyAlgorithms = new Dictionary<string, Func<CryptoPublicKey>>()
{
{"ssh-rsa", (hostKeyData) => { return new SignatureRsa(hostKeyData);}},
{"ssh-dsa", (hostKeyData) => { return new SignatureDss(hostKeyData);;}}, // TODO: Need to be tested
{"ssh-rsa", () => { return new CryptoPublicKeyRsa();}},
{"ssh-dsa", () => { return new CryptoPublicKeyDss();}}, // TODO: Need to be tested
};
}
}