RSADigitalSignature.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Security.Cryptography;
  6. using Renci.SshNet.Common;
  7. namespace Renci.SshNet.Security.Cryptography
  8. {
  9. public class RSADigitalSignature : DigitalSignature
  10. {
  11. private HashAlgorithm _hash;
  12. private RSACipher _cipher;
  13. public RSADigitalSignature(RSAPublicKey key)
  14. {
  15. this._hash = new SHA1Hash();
  16. this._cipher = new RSACipher(this._hash, key);
  17. }
  18. public override bool VerifySignature(byte[] input, byte[] signature)
  19. {
  20. var sig = this._cipher.Transform(signature);
  21. // TODO: Ensure that only 1 or 2 types are supported
  22. var position = 1;
  23. while (position < sig.Length && sig[position] != 0)
  24. position++;
  25. position++;
  26. var sig1 = new byte[sig.Length - position];
  27. Array.Copy(sig, position, sig1, 0, sig1.Length);
  28. var hashData = this._hash.ComputeHash(input);
  29. var expected = DerEncode(hashData);
  30. if (expected.Count != sig1.Length)
  31. return false;
  32. for (int i = 0; i < expected.Count; i++)
  33. {
  34. if (expected[i] != sig1[i])
  35. return false;
  36. }
  37. return true;
  38. }
  39. public override byte[] CreateSignature(byte[] input)
  40. {
  41. // Calculate hash value
  42. var hashData = this._hash.ComputeHash(input);
  43. // Calculate DER string
  44. // Resolve algorithm identifier
  45. var dd = DerEncode(hashData);
  46. // Calculate signature
  47. var rsaInputBlockSize = new byte[255];
  48. rsaInputBlockSize[0] = 0x01;
  49. for (int i = 1; i < rsaInputBlockSize.Length - dd.Count - 1; i++)
  50. {
  51. rsaInputBlockSize[i] = 0xFF;
  52. }
  53. Array.Copy(dd.ToArray(), 0, rsaInputBlockSize, rsaInputBlockSize.Length - dd.Count, dd.Count);
  54. var input1 = new BigInteger(rsaInputBlockSize.Reverse().ToArray());
  55. return this._cipher.Transform(input1).ToByteArray().Reverse().TrimLeadingZero().ToArray();
  56. }
  57. private static List<byte> DerEncode(byte[] hashData)
  58. {
  59. // TODO: Replace with algorithm code
  60. var algorithm = new byte[] { 6, 5, 43, 14, 3, 2, 26 };
  61. var algorithmParams = new byte[] { 5, 0 };
  62. var dd = new List<byte>(algorithm);
  63. dd.AddRange(algorithmParams);
  64. dd.Insert(0, (byte)dd.Count);
  65. dd.Insert(0, 48);
  66. dd.Add(4);
  67. dd.Add((byte)hashData.Length);
  68. dd.AddRange(hashData);
  69. dd.Insert(0, (byte)dd.Count);
  70. dd.Insert(0, 48);
  71. return dd;
  72. }
  73. }
  74. }