RSACryptoService.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. public class RSACryptoService
  6. {
  7. private RSACryptoServiceProvider _privateKeyRsaProvider;
  8. private RSACryptoServiceProvider _publicKeyRsaProvider;
  9. public RSACryptoService(string privateKey, string publicKey = null)
  10. {
  11. if (!string.IsNullOrEmpty(privateKey))
  12. {
  13. _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey);
  14. }
  15. if (!string.IsNullOrEmpty(publicKey))
  16. {
  17. _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey);
  18. }
  19. }
  20. public string Decrypt(string cipherText)
  21. {
  22. if (_privateKeyRsaProvider == null)
  23. {
  24. throw new Exception("_privateKeyRsaProvider is null");
  25. }
  26. return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(System.Convert.FromBase64String(cipherText), false));
  27. }
  28. public string Encrypt(string text)
  29. {
  30. if (_publicKeyRsaProvider == null)
  31. {
  32. throw new Exception("_publicKeyRsaProvider is null");
  33. }
  34. return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), false));
  35. }
  36. private RSACryptoServiceProvider CreateRsaProviderFromPrivateKey(string privateKey)
  37. {
  38. var privateKeyBits = System.Convert.FromBase64String(privateKey);
  39. var RSA = new RSACryptoServiceProvider();
  40. var RSAparams = new RSAParameters();
  41. using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
  42. {
  43. byte bt = 0;
  44. ushort twobytes = 0;
  45. twobytes = binr.ReadUInt16();
  46. if (twobytes == 0x8130)
  47. binr.ReadByte();
  48. else if (twobytes == 0x8230)
  49. binr.ReadInt16();
  50. else
  51. throw new Exception("Unexpected value read binr.ReadUInt16()");
  52. twobytes = binr.ReadUInt16();
  53. if (twobytes != 0x0102)
  54. throw new Exception("Unexpected version");
  55. bt = binr.ReadByte();
  56. if (bt != 0x00)
  57. throw new Exception("Unexpected value read binr.ReadByte()");
  58. RSAparams.Modulus = binr.ReadBytes(GetIntegerSize(binr));
  59. RSAparams.Exponent = binr.ReadBytes(GetIntegerSize(binr));
  60. RSAparams.D = binr.ReadBytes(GetIntegerSize(binr));
  61. RSAparams.P = binr.ReadBytes(GetIntegerSize(binr));
  62. RSAparams.Q = binr.ReadBytes(GetIntegerSize(binr));
  63. RSAparams.DP = binr.ReadBytes(GetIntegerSize(binr));
  64. RSAparams.DQ = binr.ReadBytes(GetIntegerSize(binr));
  65. RSAparams.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
  66. }
  67. RSA.ImportParameters(RSAparams);
  68. return RSA;
  69. }
  70. private int GetIntegerSize(BinaryReader binr)
  71. {
  72. byte bt = 0;
  73. byte lowbyte = 0x00;
  74. byte highbyte = 0x00;
  75. int count = 0;
  76. bt = binr.ReadByte();
  77. if (bt != 0x02)
  78. return 0;
  79. bt = binr.ReadByte();
  80. if (bt == 0x81)
  81. count = binr.ReadByte();
  82. else
  83. if (bt == 0x82)
  84. {
  85. highbyte = binr.ReadByte();
  86. lowbyte = binr.ReadByte();
  87. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  88. count = BitConverter.ToInt32(modint, 0);
  89. }
  90. else
  91. {
  92. count = bt;
  93. }
  94. while (binr.ReadByte() == 0x00)
  95. {
  96. count -= 1;
  97. }
  98. binr.BaseStream.Seek(-1, SeekOrigin.Current);
  99. return count;
  100. }
  101. private RSACryptoServiceProvider CreateRsaProviderFromPublicKey(string publicKeyString)
  102. {
  103. // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
  104. byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  105. byte[] x509key;
  106. byte[] seq = new byte[15];
  107. int x509size;
  108. x509key = Convert.FromBase64String(publicKeyString);
  109. x509size = x509key.Length;
  110. // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
  111. using (MemoryStream mem = new MemoryStream(x509key))
  112. {
  113. using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
  114. {
  115. byte bt = 0;
  116. ushort twobytes = 0;
  117. twobytes = binr.ReadUInt16();
  118. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  119. binr.ReadByte(); //advance 1 byte
  120. else if (twobytes == 0x8230)
  121. binr.ReadInt16(); //advance 2 bytes
  122. else
  123. return null;
  124. seq = binr.ReadBytes(15); //read the Sequence OID
  125. if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
  126. return null;
  127. twobytes = binr.ReadUInt16();
  128. if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
  129. binr.ReadByte(); //advance 1 byte
  130. else if (twobytes == 0x8203)
  131. binr.ReadInt16(); //advance 2 bytes
  132. else
  133. return null;
  134. bt = binr.ReadByte();
  135. if (bt != 0x00) //expect null byte next
  136. return null;
  137. twobytes = binr.ReadUInt16();
  138. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  139. binr.ReadByte(); //advance 1 byte
  140. else if (twobytes == 0x8230)
  141. binr.ReadInt16(); //advance 2 bytes
  142. else
  143. return null;
  144. twobytes = binr.ReadUInt16();
  145. byte lowbyte = 0x00;
  146. byte highbyte = 0x00;
  147. if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
  148. lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
  149. else if (twobytes == 0x8202)
  150. {
  151. highbyte = binr.ReadByte(); //advance 2 bytes
  152. lowbyte = binr.ReadByte();
  153. }
  154. else
  155. return null;
  156. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
  157. int modsize = BitConverter.ToInt32(modint, 0);
  158. int firstbyte = binr.PeekChar();
  159. if (firstbyte == 0x00)
  160. { //if first byte (highest order) of modulus is zero, don't include it
  161. binr.ReadByte(); //skip this null byte
  162. modsize -= 1; //reduce modulus buffer size by 1
  163. }
  164. byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
  165. if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
  166. return null;
  167. int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
  168. byte[] exponent = binr.ReadBytes(expbytes);
  169. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  170. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  171. RSAParameters RSAKeyInfo = new RSAParameters();
  172. RSAKeyInfo.Modulus = modulus;
  173. RSAKeyInfo.Exponent = exponent;
  174. RSA.ImportParameters(RSAKeyInfo);
  175. return RSA;
  176. }
  177. }
  178. }
  179. private bool CompareBytearrays(byte[] a, byte[] b)
  180. {
  181. if (a.Length != b.Length)
  182. return false;
  183. int i = 0;
  184. foreach (byte c in a)
  185. {
  186. if (c != b[i])
  187. return false;
  188. i++;
  189. }
  190. return true;
  191. }
  192. }