C# Java RSA互通
Java代码
package com.pkuhit.mobile.pay.alipay.api.sign; import com.founder.smc.util.Base64Util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; public class RSA{ public static final String SIGN_ALGORITHMS = "SHA1WithRSA"; /** * RSA签名 * @param content 待签名数据 * @param privateKey 商户私钥 * @param input_charset 编码格式 * @return 签名值 */ public static String sign(String content, String privateKey, String input_charset) { try { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec( Base64.decode(privateKey) ); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyf.generatePrivate(priPKCS8); java.security.Signature signature = java.security.Signature .getInstance(SIGN_ALGORITHMS); signature.initSign(priKey); signature.update( content.getBytes(input_charset) ); byte[] signed = signature.sign(); return Base64.encode(signed); } catch (Exception e) { e.printStackTrace(); } return null; } /** * RSA验签名检查 * @param content 待签名数据 * @param sign 签名值 * @param ali_public_key 支付宝公钥 * @param input_charset 编码格式 * @return 布尔值 */ public static boolean verify(String content, String sign, String ali_public_key, String input_charset) { try { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); byte[] encodedKey = Base64.decode(ali_public_key); PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); java.security.Signature signature = java.security.Signature .getInstance(SIGN_ALGORITHMS); signature.initVerify(pubKey); signature.update( content.getBytes(input_charset) ); boolean bverify = signature.verify( Base64.decode(sign) ); return bverify; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 解密 * @param content 密文 * @param private_key 商户私钥 * @param input_charset 编码格式 * @return 解密后的字符串 */ public static String decrypt(String content, String private_key, String input_charset) throws Exception { PrivateKey prikey = getPrivateKey(private_key); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, prikey); InputStream ins = new ByteArrayInputStream(Base64.decode(content)); ByteArrayOutputStream writer = new ByteArrayOutputStream(); //rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密 byte[] buf = new byte[128]; int bufl; while ((bufl = ins.read(buf)) != -1) { byte[] block = null; if (buf.length == bufl) { block = buf; } else { block = new byte[bufl]; for (int i = 0; i < bufl; i++) { block[i] = buf[i]; } } writer.write(cipher.doFinal(block)); } return new String(writer.toByteArray(), input_charset); } /** * 得到私钥 * @param key 密钥字符串(经过base64编码) * @throws Exception */ public static PrivateKey getPrivateKey(String key) throws Exception { byte[] keyBytes; keyBytes = Base64.decode(key); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** *加密 * @param content 明文 * @param public_key 公钥 * @param input_charset 编码格式(UTF-8) * @return 加密后的字符串 * @throws Exception */ public static String encrypt(String content,String public_key, String input_charset) throws Exception { PublicKey publicKey = getPublicKey(public_key); Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE,publicKey); ByteArrayOutputStream writer = new ByteArrayOutputStream(); //加密最大长度为117b(密钥长度为1024时),超过该长度的进行分块处理 byte[] encryptData = null; byte[] con = content.getBytes("UTF-8"); byte[] cache; int offSet = 0,i=0; int dataLength = con.length; while(dataLength - offSet > 0){ if (dataLength - offSet > 117){ cache = cipher.doFinal(con,offSet,117); }else { cache = cipher.doFinal(con,offSet,dataLength-offSet); } writer.write(cache,0,cache.length); i++; offSet = i*117; } encryptData = writer.toByteArray(); writer.close(); //先用RSA加密再用base64加密 return Base64Util.encode(encryptData); } /** * 公钥字符串转PublicKey实例 * @param publicKey * @return * @throws Exception */ public static PublicKey getPublicKey(String publicKey) throws Exception { byte[] publicKeyBytes = Base64Util.decode(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } public static void main(String[] args)throws Exception { String clientPrivateKey=""; String clientPublicKey=""; String context = "老铁"; String encryptData = encrypt(context,clientPublicKey,"UTF-8"); System.out.println("encryptData=>"+encryptData); String decryptData = decrypt(encryptData,clientPrivateKey,"UTF-8"); System.out.println("decryptData=>"+decryptData); } }
C# 代码
public partial class RSAHelper { #region 私钥加密 /// <summary> /// 基于Portable.BouncyCastle的RSA私钥加密 /// </summary> /// <param name="privateKeyJava"></param> /// <param name="data"></param> /// <returns></returns> public static string EncryptPrivateKeyJava(string privateKeyJava, string data, string encoding = "UTF-8") { RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyJava)); byte[] cipherbytes = Encoding.GetEncoding(encoding).GetBytes(data); RsaEngine rsa = new RsaEngine(); rsa.Init(true, privateKeyParam);//参数true表示加密/false表示解密。 cipherbytes = rsa.ProcessBlock(cipherbytes, 0, cipherbytes.Length); return Convert.ToBase64String(cipherbytes); } #endregion #region 公钥解密 /// <summary> /// 基于Portable.BouncyCastle的RSA公钥解密 /// </summary> /// <param name="publicKeyJava"></param> /// <param name="data"></param> /// <param name="encoding"></param> /// <returns></returns> public static string DecryptPublicKeyJava(string publicKeyJava, string data, string encoding = "UTF-8") { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKeyJava)); byte[] cipherbytes = Convert.FromBase64String(data); RsaEngine rsa = new RsaEngine(); rsa.Init(false, publicKeyParam);//参数true表示加密/false表示解密。 cipherbytes = rsa.ProcessBlock(cipherbytes, 0, cipherbytes.Length); return Encoding.GetEncoding(encoding).GetString(cipherbytes); } #endregion #region 加签 /// <summary> /// 基于Portable.BouncyCastle的RSA签名 /// </summary> /// <param name="data"></param> /// <param name="privateKeyJava"></param> /// <param name="hashAlgorithm">JAVA的和.NET的不一样,如:MD5(.NET)等同于MD5withRSA(JAVA)</param> /// <param name="encoding"></param> /// <returns></returns> public static string RSASignJavaBouncyCastle(string data, string privateKeyJava, string hashAlgorithm = "SHA1WITHRSA", string encoding = "UTF-8") { RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyJava)); ISigner signer = SignerUtilities.GetSigner(hashAlgorithm); signer.Init(true, privateKeyParam);//参数为true验签,参数为false加签 var dataByte = Encoding.GetEncoding(encoding).GetBytes(data); signer.BlockUpdate(dataByte, 0, dataByte.Length); //return Encoding.GetEncoding(encoding).GetString(signer.GenerateSignature()); //签名结果 非Base64String return Convert.ToBase64String(signer.GenerateSignature()); } #endregion #region 验签 /// <summary> /// 基于Portable.BouncyCastle的RSA签名 /// </summary> /// <param name="data">源数据</param> /// <param name="publicKeyJava"></param> /// <param name="signature">base64签名</param> /// <param name="hashAlgorithm">JAVA的和.NET的不一样,如:MD5(.NET)等同于MD5withRSA(JAVA)</param> /// <param name="encoding"></param> /// <returns></returns> public static bool VerifyJavaBouncyCastle(string data, string publicKeyJava, string signature, string hashAlgorithm = "SHA1WITHRSA", string encoding = "UTF-8") { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKeyJava)); ISigner signer = SignerUtilities.GetSigner(hashAlgorithm); signer.Init(false, publicKeyParam); byte[] dataByte = Encoding.GetEncoding(encoding).GetBytes(data); signer.BlockUpdate(dataByte, 0, dataByte.Length); //byte[] signatureByte = Encoding.GetEncoding(encoding).GetBytes(signature);// 非Base64String byte[] signatureByte = Convert.FromBase64String(signature); return signer.VerifySignature(signatureByte); } #endregion /// <summary> /// RSA公钥加密 /// </summary> /// <param name="data"></param> /// <returns></returns> private static string RSAEncrypt(string data) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(RSAPublicKeyJava2DotNet(PublicKey)); byte[] cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(data), RSAEncryptionPadding.OaepSHA1); return Convert.ToBase64String(cipherbytes); } } /// <summary> /// RSA私钥解密 /// </summary> /// <param name="data"></param> /// <returns></returns> private static string RSADecrypt(string data) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) { rsa.FromXmlString(RSAPrivateKeyJava2DotNet(PrivateKey)); byte[] cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), RSAEncryptionPadding.OaepSHA1); return Encoding.UTF8.GetString(cipherbytes); } } /// <summary> /// RSA公钥格式转换,java->.net /// </summary> /// <param name="publicKey">java生成的公钥</param> /// <returns></returns> private static string RSAPublicKeyJava2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); } /// <summary> /// RSA私钥格式转换,java->.net /// </summary> /// <param name="privateKey">java生成的RSA私钥</param> /// <returns></returns> public static string RSAPrivateKeyJava2DotNet(string privateKey) { RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); } #region 登录密钥 /* * 密钥对生成地址:http://web.chacuo.net/netrsakeypair 位数:2048 密钥格式:PKCS#8 输出格式:PEM/Base64 */ private static readonly string PublicKey = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0/ViBSWEZQv6N3wGqNoW Dw6hw1e+iFyrg2aoL7sFb67KEx6qJuWFQEwSjtv+aprEGmR3q35U9t0Z3dQzstSf 0nZ9Xq4GqDsq4bhBiBDhoKXJf0G4d4R7LeHXb95Z3Cu1IGtpATiC1nu/k5LbvSks WaqpNPTqW0E6stUqijYq/dloAXGcyW1j5zWlK92RXTtEi/Rh35VqKqwI+zNsRoai zV2HABPxmSLJ7cPUB9qNdvxX9amaKW/e7jfwhnokVQ+SvUiZqiOb77JEsdhyHyHm +N3Pq7AsqI1V6/Z2aBv4i9aVXDml1yYtGk0ZfpUPkSOPaTsUoY09MFVFazGfUl+F TQIDAQAB"; private static readonly string PrivateKey = @"MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDT9WIFJYRlC/o3 fAao2hYPDqHDV76IXKuDZqgvuwVvrsoTHqom5YVATBKO2/5qmsQaZHerflT23Rnd 1DOy1J/Sdn1ergaoOyrhuEGIEOGgpcl/Qbh3hHst4ddv3lncK7Uga2kBOILWe7+T ktu9KSxZqqk09OpbQTqy1SqKNir92WgBcZzJbWPnNaUr3ZFdO0SL9GHflWoqrAj7 M2xGhqLNXYcAE/GZIsntw9QH2o12/Ff1qZopb97uN/CGeiRVD5K9SJmqI5vvskSx 2HIfIeb43c+rsCyojVXr9nZoG/iL1pVcOaXXJi0aTRl+lQ+RI49pOxShjT0wVUVr MZ9SX4VNAgMBAAECggEAfCTf6WXE+q4eOrsw51r8yormYhSVaybj6g2JepNOptA4 WSR/wlJyTmt//x6JEAVf0JmBofdXalOr38p3EUoJ5eoyme7RxV0KS7Rw5XIFxOL1 dsyWb6Ivx3rchRA1j4gmCTv//5AKyfcnCRdeDpf7+vTDMFo2nYZCDBZgWR1K5uyL CZw8d+ha6sVcN5ScusIwD0fu77ReDIaY1X0ekhaqrk7Ddnt16x7rO9C70HWWp2q3 iloeANxtyfvtUQtxzgBkch48/EztJX3rxFtdyYao9DkFeGOMu7gcVzNkFkzXPcBd kt219eJctx56tE6G0uCXxON9XZtdQG/oTJlGtcqsHQKBgQD1Y3IdQCxnFtFqPsDm TbAZ4eBeQtGiPtqFA7jfi0dSMe/qjQvB0k20ELrmW3pDBapYmajAUAEItTzSc85p PZJ4PDFOvgOonaJkyE1bBlJHOaW6yKntZVMOGL0dtPEmM9Ova+Owxckzxc96H3wW tUimBFQTwuKnCm/BX5zn2TJcQwKBgQDdH9qF8cF/uW1oPNZs5NqqZCGC4m4RsNFW 9j7FzIu7oQ3Xh+FxMRMv8t7LXzrgG5WXQh2RBWMicxlOqKTy/Zjl6C/LfS6bRtZR Lmw0MGJI5oVwxfdcSRWV+ToxCi6GsmwvDyVaURX+3MGHvmFAt69UkqN0j54FxeDD KqEUV65HLwKBgQCP1CsVxACCqBg0yvVrx8tZUFCfT1DqZSbV4hmhRVSXc9eoxeVH RMnwqgGydZnS4OY4qlAD8KC6huhQfjpU6xcHzFgmTC9+zG5b3h+hI7JkNwDR2z3m fIZS8+MdH2pdNvFzl6xMd5F3/BChBwVHlhgv3sedEZShzfc1A6LHLkJbWwKBgQDX SLH6gps/fQrV15V0Q4PZLM+rnERJmPrXTbtj3HeW34CYfMSy7XKe1jivjDHIC1Mj Bs2+aZ5Q5fqXqH2fzeNUwy/1UBVWPCtgsm/Kh+jIzRbR6wufn9ASSamsIRuXLJND Zd2aByQBFHCfdm09ExjyoCnfzAuv1y2zFgfpxEv7JQKBgQCw7rPsOlh3EyUpYTeW AOdPedHr8Xi1/ulnVPVVg2zXTSYoeiW+MwyY9B0Y0PvNtHzm3GURPya9IPKg/Wjo 57MbZFtIaOSBXBDCJZeeXVnthOVSYgjkRE6hU91t7sTqrzUrIZ21NTPjp2G1W2X2 QBJoRL5WTt04yIF6Hlkr3L+lww=="; #endregion }