CryptoPublicKeyRsa.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 RSA public key
  11. /// </summary>
  12. internal class CryptoPublicKeyRsa : CryptoPublicKey
  13. {
  14. private byte[] _modulus;
  15. private byte[] _exponent;
  16. /// <summary>
  17. /// Gets key name.
  18. /// </summary>
  19. public override string Name
  20. {
  21. get { return "ssh-rsa"; }
  22. }
  23. /// <summary>
  24. /// Initializes a new instance of the <see cref="CryptoPublicKeyRsa"/> class.
  25. /// </summary>
  26. public CryptoPublicKeyRsa()
  27. {
  28. }
  29. /// <summary>
  30. /// Initializes a new instance of the <see cref="CryptoPublicKeyRsa"/> class.
  31. /// </summary>
  32. /// <param name="modulus">The modulus.</param>
  33. /// <param name="exponent">The exponent.</param>
  34. internal CryptoPublicKeyRsa(byte[] modulus, byte[] exponent)
  35. {
  36. this._modulus = modulus;
  37. this._exponent = exponent;
  38. }
  39. /// <summary>
  40. /// Loads key specific data.
  41. /// </summary>
  42. /// <param name="data">The data.</param>
  43. public override void Load(IEnumerable<byte> data)
  44. {
  45. MemoryStream ms = null;
  46. try
  47. {
  48. ms = new MemoryStream(data.ToArray());
  49. using (var br = new BinaryReader(ms))
  50. {
  51. var el = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  52. this._exponent = br.ReadBytes((int)el);
  53. var ml = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
  54. this._modulus = br.ReadBytes((int)ml);
  55. }
  56. }
  57. finally
  58. {
  59. if (ms != null)
  60. {
  61. ms.Dispose();
  62. ms = null;
  63. }
  64. }
  65. }
  66. /// <summary>
  67. /// Verifies the signature.
  68. /// </summary>
  69. /// <param name="hash">The hash.</param>
  70. /// <param name="signature">The signature.</param>
  71. /// <returns>
  72. /// true if signature verified; otherwise false.
  73. /// </returns>
  74. public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
  75. {
  76. using (var sha1 = new SHA1CryptoServiceProvider())
  77. {
  78. using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
  79. {
  80. var data = hash.ToArray();
  81. cs.Write(data, 0, data.Length);
  82. }
  83. using (var rsa = new RSACryptoServiceProvider())
  84. {
  85. rsa.ImportParameters(new RSAParameters
  86. {
  87. Exponent = this._exponent.TrimLeadingZero().ToArray(),
  88. Modulus = this._modulus.TrimLeadingZero().ToArray(),
  89. });
  90. var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
  91. rsaDeformatter.SetHashAlgorithm("SHA1");
  92. long i = 0;
  93. long j = 0;
  94. byte[] tmp;
  95. var sig = signature.ToArray();
  96. if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
  97. {
  98. long i1 = (sig[i++] << 24) & 0xff000000;
  99. long i2 = (sig[i++] << 16) & 0x00ff0000;
  100. long i3 = (sig[i++] << 8) & 0x0000ff00;
  101. long i4 = (sig[i++]) & 0x000000ff;
  102. j = i1 | i2 | i3 | i4;
  103. i += j;
  104. i1 = (sig[i++] << 24) & 0xff000000;
  105. i2 = (sig[i++] << 16) & 0x00ff0000;
  106. i3 = (sig[i++] << 8) & 0x0000ff00;
  107. i4 = (sig[i++]) & 0x000000ff;
  108. j = i1 | i2 | i3 | i4;
  109. tmp = new byte[j];
  110. Array.Copy(sig, (int)i, tmp, 0, (int)j);
  111. sig = tmp;
  112. }
  113. return rsaDeformatter.VerifySignature(sha1, sig);
  114. }
  115. }
  116. }
  117. /// <summary>
  118. /// Gets key data byte array.
  119. /// </summary>
  120. /// <returns>
  121. /// The data byte array.
  122. /// </returns>
  123. public override IEnumerable<byte> GetBytes()
  124. {
  125. return new RsaPublicKeyData
  126. {
  127. E = this._exponent,
  128. Modulus = this._modulus,
  129. }.GetBytes();
  130. }
  131. private class RsaPublicKeyData : SshData
  132. {
  133. public byte[] Modulus { get; set; }
  134. public byte[] E { get; set; }
  135. protected override void LoadData()
  136. {
  137. }
  138. protected override void SaveData()
  139. {
  140. this.Write("ssh-rsa");
  141. this.WriteBinaryString(this.E);
  142. this.WriteBinaryString(this.Modulus);
  143. }
  144. }
  145. }
  146. }