1 /// <summary> 2 /// 类名:RSAFromPkcs8 3 /// 功能:RSA加密、解密、签名、验签 4 /// 详细:该类对Java生成的密钥进行解密和签名以及验签专用类,不需要修改 5 /// 版本:3.0 6 /// 日期:2013-07-08 7 /// 说明: 8 /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 9 /// </summary> 10 public sealed class RSAFromPkcs8 11 { 12 /// <summary> 13 /// 签名 14 /// </summary> 15 /// <param name="content">待签名字符串</param> 16 /// <param name="privateKey">私钥</param> 17 /// <param name="input_charset">编码格式</param> 18 /// <returns>签名后字符串</returns> 19 public static string sign(string content, string privateKey, string input_charset) 20 { 21 byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content); 22 RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey); 23 SHA256 sh = new SHA256CryptoServiceProvider(); 24 //SHA1 sh = new SHA1CryptoServiceProvider(); 25 byte[] signData = rsa.SignData(Data, sh); 26 return Convert.ToBase64String(signData); 27 } 28 29 /// <summary> 30 /// 验签 31 /// </summary> 32 /// <param name="content">待验签字符串</param> 33 /// <param name="signedString">签名</param> 34 /// <param name="publicKey">公钥</param> 35 /// <param name="input_charset">编码格式</param> 36 /// <returns>true(通过),false(不通过)</returns> 37 public static bool verify(string content, string signedString, string publicKey, string input_charset) 38 { 39 bool result = false; 40 byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content); 41 byte[] data = Convert.FromBase64String(signedString); 42 RSAParameters paraPub = ConvertFromPublicKey(publicKey); 43 RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider(); 44 rsaPub.ImportParameters(paraPub); 45 //SHA1 sh = new SHA1CryptoServiceProvider(); 46 SHA256 sh = new SHA256CryptoServiceProvider(); 47 result = rsaPub.VerifyData(Data, sh, data); 48 return result; 49 } 50 51 /// <summary> 52 /// 加密 53 /// </summary> 54 /// <param name="resData">需要加密的字符串</param> 55 /// <param name="publicKey">公钥</param> 56 /// <param name="input_charset">编码格式</param> 57 /// <returns>明文</returns> 58 public static string encryptData(string resData, string publicKey, string input_charset) 59 { 60 byte[] DataToEncrypt = Encoding.ASCII.GetBytes(resData); 61 string result = encrypt(DataToEncrypt, publicKey, input_charset); 62 return result; 63 } 64 65 66 /// <summary> 67 /// 解密 68 /// </summary> 69 /// <param name="resData">加密字符串</param> 70 /// <param name="privateKey">私钥</param> 71 /// <param name="input_charset">编码格式</param> 72 /// <returns>明文</returns> 73 public static string decryptData(string resData, string privateKey, string input_charset) 74 { 75 byte[] DataToDecrypt = Convert.FromBase64String(resData); 76 string result = ""; 77 for (int j = 0; j < DataToDecrypt.Length / 128; j++) 78 { 79 byte[] buf = new byte[128]; 80 for (int i = 0; i < 128; i++) 81 { 82 83 buf[i] = DataToDecrypt[i + 128 * j]; 84 } 85 result += decrypt(buf, privateKey, input_charset); 86 } 87 return result; 88 } 89 90 #region 内部方法 91 92 private static string encrypt(byte[] data, string publicKey, string input_charset) 93 { 94 RSACryptoServiceProvider rsa = DecodePemPublicKey(publicKey); 95 SHA1 sh = new SHA1CryptoServiceProvider(); 96 byte[] result = rsa.Encrypt(data, false); 97 98 return Convert.ToBase64String(result); 99 } 100 101 private static string decrypt(byte[] data, string privateKey, string input_charset) 102 { 103 string result = ""; 104 RSACryptoServiceProvider rsa = DecodePemPrivateKey(privateKey); 105 SHA1 sh = new SHA1CryptoServiceProvider(); 106 byte[] source = rsa.Decrypt(data, false); 107 char[] asciiChars = new char[Encoding.GetEncoding(input_charset).GetCharCount(source, 0, source.Length)]; 108 Encoding.GetEncoding(input_charset).GetChars(source, 0, source.Length, asciiChars, 0); 109 result = new string(asciiChars); 110 //result = ASCIIEncoding.ASCII.GetString(source); 111 return result; 112 } 113 114 private static RSACryptoServiceProvider DecodePemPublicKey(String pemstr) 115 { 116 byte[] pkcs8publickkey; 117 pkcs8publickkey = Convert.FromBase64String(pemstr); 118 if (pkcs8publickkey != null) 119 { 120 RSACryptoServiceProvider rsa = DecodeRSAPublicKey(pkcs8publickkey); 121 return rsa; 122 } 123 else 124 return null; 125 } 126 127 private static RSACryptoServiceProvider DecodePemPrivateKey(String pemstr) 128 { 129 byte[] pkcs8privatekey; 130 pkcs8privatekey = Convert.FromBase64String(pemstr); 131 if (pkcs8privatekey != null) 132 { 133 RSACryptoServiceProvider rsa = DecodePrivateKeyInfo(pkcs8privatekey); 134 return rsa; 135 } 136 else 137 return null; 138 } 139 140 private static RSACryptoServiceProvider DecodePrivateKeyInfo(byte[] pkcs8) 141 { 142 byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; 143 byte[] seq = new byte[15]; 144 145 MemoryStream mem = new MemoryStream(pkcs8); 146 int lenstream = (int)mem.Length; 147 BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading 148 byte bt = 0; 149 ushort twobytes = 0; 150 151 try 152 { 153 twobytes = binr.ReadUInt16(); 154 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) 155 binr.ReadByte(); //advance 1 byte 156 else if (twobytes == 0x8230) 157 binr.ReadInt16(); //advance 2 bytes 158 else 159 return null; 160 161 bt = binr.ReadByte(); 162 if (bt != 0x02) 163 return null; 164 165 twobytes = binr.ReadUInt16(); 166 167 if (twobytes != 0x0001) 168 return null; 169 170 seq = binr.ReadBytes(15); //read the Sequence OID 171 if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct 172 return null; 173 174 bt = binr.ReadByte(); 175 if (bt != 0x04) //expect an Octet string 176 return null; 177 178 bt = binr.ReadByte(); //read next byte, or next 2 bytes is 0x81 or 0x82; otherwise bt is the byte count 179 if (bt == 0x81) 180 binr.ReadByte(); 181 else 182 if (bt == 0x82) 183 binr.ReadUInt16(); 184 //------ at this stage, the remaining sequence should be the RSA private key 185 186 byte[] rsaprivkey = binr.ReadBytes((int)(lenstream - mem.Position)); 187 RSACryptoServiceProvider rsacsp = DecodeRSAPrivateKey(rsaprivkey); 188 return rsacsp; 189 } 190 191 catch (Exception) 192 { 193 return null; 194 } 195 196 finally { binr.Close(); } 197 198 } 199 200 private static bool CompareBytearrays(byte[] a, byte[] b) 201 { 202 if (a.Length != b.Length) 203 return false; 204 int i = 0; 205 foreach (byte c in a) 206 { 207 if (c != b[i]) 208 return false; 209 i++; 210 } 211 return true; 212 } 213 214 private static RSACryptoServiceProvider DecodeRSAPublicKey(byte[] publickey) 215 { 216 // encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1" 217 byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 }; 218 byte[] seq = new byte[15]; 219 // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------ 220 MemoryStream mem = new MemoryStream(publickey); 221 BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading 222 byte bt = 0; 223 ushort twobytes = 0; 224 225 try 226 { 227 228 twobytes = binr.ReadUInt16(); 229 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) 230 binr.ReadByte(); //advance 1 byte 231 else if (twobytes == 0x8230) 232 binr.ReadInt16(); //advance 2 bytes 233 else 234 return null; 235 236 seq = binr.ReadBytes(15); //read the Sequence OID 237 if (!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct 238 return null; 239 240 twobytes = binr.ReadUInt16(); 241 if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81) 242 binr.ReadByte(); //advance 1 byte 243 else if (twobytes == 0x8203) 244 binr.ReadInt16(); //advance 2 bytes 245 else 246 return null; 247 248 bt = binr.ReadByte(); 249 if (bt != 0x00) //expect null byte next 250 return null; 251 252 twobytes = binr.ReadUInt16(); 253 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) 254 binr.ReadByte(); //advance 1 byte 255 else if (twobytes == 0x8230) 256 binr.ReadInt16(); //advance 2 bytes 257 else 258 return null; 259 260 twobytes = binr.ReadUInt16(); 261 byte lowbyte = 0x00; 262 byte highbyte = 0x00; 263 264 if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81) 265 lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus 266 else if (twobytes == 0x8202) 267 { 268 highbyte = binr.ReadByte(); //advance 2 bytes 269 lowbyte = binr.ReadByte(); 270 } 271 else 272 return null; 273 byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order 274 int modsize = BitConverter.ToInt32(modint, 0); 275 276 byte firstbyte = binr.ReadByte(); 277 binr.BaseStream.Seek(-1, SeekOrigin.Current); 278 279 if (firstbyte == 0x00) 280 { //if first byte (highest order) of modulus is zero, don't include it 281 binr.ReadByte(); //skip this null byte 282 modsize -= 1; //reduce modulus buffer size by 1 283 } 284 285 byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes 286 287 if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data 288 return null; 289 int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values) 290 byte[] exponent = binr.ReadBytes(expbytes); 291 292 // ------- create RSACryptoServiceProvider instance and initialize with public key ----- 293 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 294 RSAParameters RSAKeyInfo = new RSAParameters(); 295 RSAKeyInfo.Modulus = modulus; 296 RSAKeyInfo.Exponent = exponent; 297 RSA.ImportParameters(RSAKeyInfo); 298 return RSA; 299 } 300 catch (Exception) 301 { 302 return null; 303 } 304 305 finally { binr.Close(); } 306 307 } 308 309 private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) 310 { 311 byte[] MODULUS, E, D, P, Q, DP, DQ, IQ; 312 313 // --------- Set up stream to decode the asn.1 encoded RSA private key ------ 314 MemoryStream mem = new MemoryStream(privkey); 315 BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading 316 byte bt = 0; 317 ushort twobytes = 0; 318 int elems = 0; 319 try 320 { 321 twobytes = binr.ReadUInt16(); 322 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81) 323 binr.ReadByte(); //advance 1 byte 324 else if (twobytes == 0x8230) 325 binr.ReadInt16(); //advance 2 bytes 326 else 327 return null; 328 329 twobytes = binr.ReadUInt16(); 330 if (twobytes != 0x0102) //version number 331 return null; 332 bt = binr.ReadByte(); 333 if (bt != 0x00) 334 return null; 335 336 337 //------ all private key components are Integer sequences ---- 338 elems = GetIntegerSize(binr); 339 MODULUS = binr.ReadBytes(elems); 340 341 elems = GetIntegerSize(binr); 342 E = binr.ReadBytes(elems); 343 344 elems = GetIntegerSize(binr); 345 D = binr.ReadBytes(elems); 346 347 elems = GetIntegerSize(binr); 348 P = binr.ReadBytes(elems); 349 350 elems = GetIntegerSize(binr); 351 Q = binr.ReadBytes(elems); 352 353 elems = GetIntegerSize(binr); 354 DP = binr.ReadBytes(elems); 355 356 elems = GetIntegerSize(binr); 357 DQ = binr.ReadBytes(elems); 358 359 elems = GetIntegerSize(binr); 360 IQ = binr.ReadBytes(elems); 361 362 // ------- create RSACryptoServiceProvider instance and initialize with public key ----- 363 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 364 RSAParameters RSAparams = new RSAParameters(); 365 RSAparams.Modulus = MODULUS; 366 RSAparams.Exponent = E; 367 RSAparams.D = D; 368 RSAparams.P = P; 369 RSAparams.Q = Q; 370 RSAparams.DP = DP; 371 RSAparams.DQ = DQ; 372 RSAparams.InverseQ = IQ; 373 RSA.ImportParameters(RSAparams); 374 return RSA; 375 } 376 catch (Exception) 377 { 378 return null; 379 } 380 finally { binr.Close(); } 381 } 382 383 private static int GetIntegerSize(BinaryReader binr) 384 { 385 byte bt = 0; 386 byte lowbyte = 0x00; 387 byte highbyte = 0x00; 388 int count = 0; 389 bt = binr.ReadByte(); 390 if (bt != 0x02) //expect integer 391 return 0; 392 bt = binr.ReadByte(); 393 394 if (bt == 0x81) 395 count = binr.ReadByte(); // data size in next byte 396 else 397 if (bt == 0x82) 398 { 399 highbyte = binr.ReadByte(); // data size in next 2 bytes 400 lowbyte = binr.ReadByte(); 401 byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; 402 count = BitConverter.ToInt32(modint, 0); 403 } 404 else 405 { 406 count = bt; // we already have the data size 407 } 408 409 410 411 while (binr.ReadByte() == 0x00) 412 { //remove high order zeros in data 413 count -= 1; 414 } 415 binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte 416 return count; 417 } 418 419 #endregion 420 421 #region 解析.net 生成的Pem 422 private static RSAParameters ConvertFromPublicKey(string pemFileConent) 423 { 424 425 byte[] keyData = Convert.FromBase64String(pemFileConent); 426 if (keyData.Length < 162) 427 { 428 throw new ArgumentException("pem file content is incorrect."); 429 } 430 byte[] pemModulus = new byte[128]; 431 byte[] pemPublicExponent = new byte[3]; 432 Array.Copy(keyData, 29, pemModulus, 0, 128); 433 Array.Copy(keyData, 159, pemPublicExponent, 0, 3); 434 RSAParameters para = new RSAParameters(); 435 para.Modulus = pemModulus; 436 para.Exponent = pemPublicExponent; 437 return para; 438 } 439 440 private static RSAParameters ConvertFromPrivateKey(string pemFileConent) 441 { 442 byte[] keyData = Convert.FromBase64String(pemFileConent); 443 if (keyData.Length < 609) 444 { 445 throw new ArgumentException("pem file content is incorrect."); 446 } 447 448 int index = 11; 449 byte[] pemModulus = new byte[128]; 450 Array.Copy(keyData, index, pemModulus, 0, 128); 451 452 index += 128; 453 index += 2;//141 454 byte[] pemPublicExponent = new byte[3]; 455 Array.Copy(keyData, index, pemPublicExponent, 0, 3); 456 457 index += 3; 458 index += 4;//148 459 byte[] pemPrivateExponent = new byte[128]; 460 Array.Copy(keyData, index, pemPrivateExponent, 0, 128); 461 462 index += 128; 463 index += ((int)keyData[index + 1] == 64 ? 2 : 3);//279 464 byte[] pemPrime1 = new byte[64]; 465 Array.Copy(keyData, index, pemPrime1, 0, 64); 466 467 index += 64; 468 index += ((int)keyData[index + 1] == 64 ? 2 : 3);//346 469 byte[] pemPrime2 = new byte[64]; 470 Array.Copy(keyData, index, pemPrime2, 0, 64); 471 472 index += 64; 473 index += ((int)keyData[index + 1] == 64 ? 2 : 3);//412/413 474 byte[] pemExponent1 = new byte[64]; 475 Array.Copy(keyData, index, pemExponent1, 0, 64); 476 477 index += 64; 478 index += ((int)keyData[index + 1] == 64 ? 2 : 3);//479/480 479 byte[] pemExponent2 = new byte[64]; 480 Array.Copy(keyData, index, pemExponent2, 0, 64); 481 482 index += 64; 483 index += ((int)keyData[index + 1] == 64 ? 2 : 3);//545/546 484 byte[] pemCoefficient = new byte[64]; 485 Array.Copy(keyData, index, pemCoefficient, 0, 64); 486 487 RSAParameters para = new RSAParameters(); 488 para.Modulus = pemModulus; 489 para.Exponent = pemPublicExponent; 490 para.D = pemPrivateExponent; 491 para.P = pemPrime1; 492 para.Q = pemPrime2; 493 para.DP = pemExponent1; 494 para.DQ = pemExponent2; 495 para.InverseQ = pemCoefficient; 496 return para; 497 } 498 #endregion 499 500 }
调用代码
using System; using System.Collections.Generic; using System.Text; using RSA.Class; namespace payapi_demo.RSA { class TestRSA { static void Main(string[] arg) { /**RSA加密测试,RSA中的密钥对通过SSL工具生成,生成命令如下: * 1 生成RSA私钥: * openssl genrsa -out rsa_private_key.pem 1024 *2 生成RSA公钥 * openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem * * 3 将RSA私钥转换成PKCS8格式 * openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_pub_pk8.pem * * 直接打开rsa_private_key.pem和rsa_pub_pk8.pem文件就可以获取密钥对内容,获取密钥对内容组成字符串时,注意将换行符删除 * */ string publickey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzOqfNunFxFtCZPlq7fO/jWwjqmTvAooVBB4y87BizSZ9dl/F7FpAxYc6MmX2TqivCvvORXgdlYdFWAhzXOnIUv9OGG///WPLe9TMs9kIwAZ/APUXauvC01oFLnYkzwPlAh0tQ1Au9arTE/OG1V1dKgf8BXHLPhKL4BmGBEUZBtQIDAQAB"; string privatekey = "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAPM6p826cXEW0Jk+Wrt87+NbCOqZO8CihUEHjLzsGLNJn12X8XsWkDFhzoyZfZOqK8K+85FeB2Vh0VYCHNc6chS/04Yb//9Y8t71Myz2QjABn8A9Rdq68LTWgUudiTPA+UCHS1DUC71qtMT84bVXV0qB/wFccs+EovgGYYERRkG1AgMBAAECgYEA2PmnPdgnYKnolfvQ9tXiLaBFGPpvGk4grz0r6FB5TF7N4rErwxECunq0xioaowK4HPc40qHd2SvkkWQ7FCjYIDsnMk1oOhxNKn0J3FG0n5Cg1/dFai4eoXHs/nKn3SVZ8YZC1T2cMtN2srectLqNqhB8aQEe8xmykyUlUpg/qmECQQD9vkwjUotG5oUUrOj6etcB4WcdyyH0FtThKgyoJUDwgBv6lGGzWyFJEREvp47IgV+FgC7zeP2mL4MhgnD3tNCZAkEA9WRrjOLBNc379XZpoDsH7rZjobVvhnTrEuRDx/whqZ+vk64EPrEW81XYh647bAbJlFn2jPhY+IUHkrxFEFT/fQJBAMoLNOULXQtfkqgb5odMONeue0Ul8itB4tBHgzyALW1TFPQ6InGGJsLfbCfd67uMCFts7fXAaXhibK/KBdm3iEECQQChwVAjzlUN4nnzk9qMhFz2PcPvFGovd2J9UXpcmRaXeWuDLXIe4Rz/ydaxmWgSDWdTIvoicpIzP31+fBwKZ/0BAkEAy0bh4weKmYF29//rK0sxmY8RtqkQeFrwWbqx1daa1w0DfWlNSvy47zyW1G5/AdZU6JSpXxlxdlM/HSDw+v7kcA=="; //加密字符串 string data = "yibao"; Console.WriteLine("加密前字符串内容:"+data); //加密 string encrypteddata = RSAFromPkcs8.encryptData(data, publickey, "UTF-8"); Console.WriteLine("加密后的字符串为:" + encrypteddata); Console.WriteLine("解密后的字符串内容:" + RSAFromPkcs8.decryptData(encrypteddata, privatekey, "UTF-8")); Console.WriteLine("***********"); //解密 string endata = "LpnnvnfA72VnyjboX/OsCPO6FOFXeEnnsKkI7aAEQyVAPfCTfQ43ZYVZVqnADDPMW7VhBXJWyQMAGw2Fh9sS/XLHmO5XW94Yehci6JrJMynePgtIiDysjNA+UlgSTC/MlResNrBm/4MMSPvq0qLwScgpZDynhLsVZk+EQ6G8wgA="; string datamw = RSAFromPkcs8.decryptData(endata, privatekey, "UTF-8"); Console.WriteLine("静态加密后的字符串为:" + endata); Console.WriteLine("解密后的字符串内容:" + datamw); //签名 string signdata = "YB010000001441234567286038508081299"; Console.WriteLine("签名前的字符串内容:" + signdata); string sign = RSAFromPkcs8.sign(signdata, privatekey, "UTF-8"); Console.WriteLine("签名后的字符串:" + sign); Console.ReadLine(); } } }
转载自 http://blog.csdn.net/hjqqingqing/article/details/9272103