CryptoPublicKeyDss.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using Renci.SshNet.Common;
  7. namespace Renci.SshNet.Security
  8. {
  9. /// <summary>
  10. /// Represents DSS public key
  11. /// </summary>
  12. internal class CryptoPublicKeyDss : CryptoPublicKey
  13. {
  14. private byte[] _p;
  15. private byte[] _q;
  16. private byte[] _g;
  17. private byte[] _publicKey;
  18. /// <summary>
  19. /// Gets key name.
  20. /// </summary>
  21. public override string Name
  22. {
  23. get { return "ssh-dss"; }
  24. }
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="CryptoPublicKeyDss"/> class.
  27. /// </summary>
  28. public CryptoPublicKeyDss()
  29. {
  30. }
  31. /// <summary>
  32. /// Initializes a new instance of the <see cref="CryptoPublicKeyDss"/> class.
  33. /// </summary>
  34. /// <param name="p">The p value.</param>
  35. /// <param name="q">The q value.</param>
  36. /// <param name="g">The g value.</param>
  37. /// <param name="publicKey">The public key value.</param>
  38. public CryptoPublicKeyDss(byte[] p, byte[] q, byte[] g, byte[] publicKey)
  39. {
  40. this._p = p;
  41. this._q = q;
  42. this._g = g;
  43. this._publicKey = publicKey;
  44. }
  45. /// <summary>
  46. /// Loads key specific data.
  47. /// </summary>
  48. /// <param name="data">The data.</param>
  49. public override void Load(IEnumerable<byte> data)
  50. {
  51. MemoryStream ms = null;
  52. try
  53. {
  54. ms = new MemoryStream(data.ToArray());
  55. using (var br = new BinaryReader(ms))
  56. {
  57. var pl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  58. _p = br.ReadBytes((int)pl);
  59. var ql = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  60. _q = br.ReadBytes((int)ql);
  61. var gl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  62. _g = br.ReadBytes((int)gl);
  63. var xl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  64. _publicKey = br.ReadBytes((int)xl);
  65. }
  66. }
  67. finally
  68. {
  69. if (ms != null)
  70. {
  71. ms.Dispose();
  72. ms = null;
  73. }
  74. }
  75. }
  76. /// <summary>
  77. /// Verifies the signature.
  78. /// </summary>
  79. /// <param name="hash">The hash.</param>
  80. /// <param name="signature">The signature.</param>
  81. /// <returns>
  82. /// true if signature verified; otherwise false.
  83. /// </returns>
  84. public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
  85. {
  86. using (var sha1 = new SHA1CryptoServiceProvider())
  87. {
  88. using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
  89. {
  90. var data = hash.ToArray();
  91. cs.Write(data, 0, data.Length);
  92. }
  93. using (var dsa = new DSACryptoServiceProvider())
  94. {
  95. dsa.ImportParameters(new DSAParameters
  96. {
  97. Y = _publicKey.TrimLeadingZero().ToArray(),
  98. P = _p.TrimLeadingZero().ToArray(),
  99. Q = _q.TrimLeadingZero().ToArray(),
  100. G = _g.TrimLeadingZero().ToArray(),
  101. });
  102. var dsaDeformatter = new DSASignatureDeformatter(dsa);
  103. dsaDeformatter.SetHashAlgorithm("SHA1");
  104. long i = 0;
  105. long j = 0;
  106. byte[] tmp;
  107. var sig = signature.ToArray();
  108. if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
  109. {
  110. long i1 = (sig[i++] << 24) & 0xff000000;
  111. long i2 = (sig[i++] << 16) & 0x00ff0000;
  112. long i3 = (sig[i++] << 8) & 0x0000ff00;
  113. long i4 = (sig[i++]) & 0x000000ff;
  114. j = i1 | i2 | i3 | i4;
  115. i += j;
  116. i1 = (sig[i++] << 24) & 0xff000000;
  117. i2 = (sig[i++] << 16) & 0x00ff0000;
  118. i3 = (sig[i++] << 8) & 0x0000ff00;
  119. i4 = (sig[i++]) & 0x000000ff;
  120. j = i1 | i2 | i3 | i4;
  121. tmp = new byte[j];
  122. Array.Copy(sig, (int)i, tmp, 0, (int)j);
  123. sig = tmp;
  124. }
  125. return dsaDeformatter.VerifySignature(sha1, sig);
  126. }
  127. }
  128. }
  129. /// <summary>
  130. /// Gets key data byte array.
  131. /// </summary>
  132. /// <returns>
  133. /// The data byte array.
  134. /// </returns>
  135. public override IEnumerable<byte> GetBytes()
  136. {
  137. return new DsaPublicKeyData
  138. {
  139. P = this._p,
  140. Q = this._q,
  141. G = this._g,
  142. Public = this._publicKey,
  143. }.GetBytes();
  144. }
  145. private class DsaPublicKeyData : SshData
  146. {
  147. public byte[] P { get; set; }
  148. public byte[] Q { get; set; }
  149. public byte[] G { get; set; }
  150. public byte[] Public { get; set; }
  151. protected override void LoadData()
  152. {
  153. }
  154. protected override void SaveData()
  155. {
  156. this.Write("ssh-dss");
  157. this.WriteBinaryString(this.P);
  158. this.WriteBinaryString(this.Q);
  159. this.WriteBinaryString(this.G);
  160. this.WriteBinaryString(this.Public);
  161. }
  162. }
  163. }
  164. }