做一电影网站怎么赚钱吗,怎样自己做网页设计网站,2345网址导航手机,专业团队图片素材这里#xff0c;讲一下RSA算法加解密在C#和Java之间交互的问题#xff0c;这两天纠结了很久#xff0c;也看了很多其他人写的文章#xff0c;颇受裨益#xff0c;但没能解决我的实际问题#xff0c;终于#xff0c;还是被我捣鼓出来了。
首先#xff0c;介绍一下写这代…这里讲一下RSA算法加解密在C#和Java之间交互的问题这两天纠结了很久也看了很多其他人写的文章颇受裨益但没能解决我的实际问题终于还是被我捣鼓出来了。
首先介绍一下写这代码的目的完成webService验证问题服务器端采用C#开发客户端采用Java开发。服务器端给客户端提供公钥已进行数据加密客户端加密后提数据提交给服务器服务器用私钥对数据解密进行验证。
这里遇到的主要问题是C# RSACryptoServiceProvider类产生的公钥、私钥都是xml字符串数据而java RSA算法要求的 Modulus、Exponent都是BigInteger类型两者间的转换才是问题所在。
关于Java 和 C#各自独立的进行RSA加密解密大家可以看整两篇文章java RSA加密解密实现 和 C#中RSA加密解密和签名与验证的实现。
接下来讲一下实现步骤
首先由C# RSACryptoServiceProvider类生成公钥、私钥[csharp] view plaincopy/// summary /// 生成公钥、私钥 /// /summary /// returns公钥、私钥公钥键PUBLIC,私钥键PRIVATE/returns public Dictionarystring, string createKeyPair() { Dictionarystring, string keyPair new Dictionarystring, string(); RSACryptoServiceProvider provider new RSACryptoServiceProvider(1024); keyPair.Add(PUBLIC, provider.ToXmlString(false)); keyPair.Add(PRIVATE, provider.ToXmlString(true)); return keyPair; } [csharp] view plain copy/// summary /// 生成公钥、私钥 /// /summary /// returns公钥、私钥公钥键PUBLIC,私钥键PRIVATE/returns public Dictionarystring, string createKeyPair() { Dictionarystring, string keyPair new Dictionarystring, string(); RSACryptoServiceProvider provider new RSACryptoServiceProvider(1024); keyPair.Add(PUBLIC, provider.ToXmlString(false)); keyPair.Add(PRIVATE, provider.ToXmlString(true)); return keyPair; } 如此处生成的公钥为
[html] view plaincopyRSAKeyValue Modulust56m5jXXonAJAKC7mgkhAZX5gWJTZojbSloLpLBGEWiebFaMaUUKALfRx83/HaUV79ZiR3zuLJOLBdALx1cmcPk/b9fdNblLmzqi4cfSnfmMLWh05xfZS1pKHSKQtui3dfuu3XH6AkS38dpIZUj/hihQQuKysN6GJ9hc8 /Modulus ExponentAQAB/Exponent /RSAKeyValue [html] view plain copyRSAKeyValue Modulust56m5jXXonAJAKC7mgkhAZX5gWJTZojbSloLpLBGEWiebFaMaUUKALfRx83/HaUV79ZiR3zuLJOLBdALx1cmcPk/b9fdNblLmzqi4cfSnfmMLWh05xfZS1pKHSKQtui3dfuu3XH6AkS38dpIZUj/hihQQuKysN6GJ9hc8 /Modulus ExponentAQAB/Exponent /RSAKeyValue 在客户端(Java)对C#提供的公钥提取Modulus和Exponent[java] view plaincopy/** * 返回包含模数modulus和指数exponent的haspMap * return * throws MalformedURLException * throws DocumentException */ public static HashMapString,String rsaParameters(String xmlPublicKey) throws MalformedURLException, DocumentException{ HashMapString ,String map new HashMapString, String(); Document doc DocumentHelper.parseText(xmlPublicKey); String mudulus (String) doc.getRootElement().element(Modulus).getData(); String exponent (String) doc.getRootElement().element(Exponent).getData(); map.put(mudulus, mudulus); map.put(exponent, exponent); return map; } [java] view plain copy/** * 返回包含模数modulus和指数exponent的haspMap * return * throws MalformedURLException * throws DocumentException */ public static HashMapString,String rsaParameters(String xmlPublicKey) throws MalformedURLException, DocumentException{ HashMapString ,String map new HashMapString, String(); Document doc DocumentHelper.parseText(xmlPublicKey); String mudulus (String) doc.getRootElement().element(Modulus).getData(); String exponent (String) doc.getRootElement().element(Exponent).getData(); map.put(mudulus, mudulus); map.put(exponent, exponent); return map; } 用Modulus和Exponent产生公钥RSAPublicKeyjava
这里有个关键步骤先对Mudolus和Exponent进行Base64解码这个是由于C#生成的密钥对其参数已经过Base64编码成String类型而java RSA参数是未经base64编码的byte[]类型。
至于Base64编码、解码方法参考这篇文章java 编码和解码想详细。
[java] view plaincopypublic static byte[] decodeBase64(String input) throws Exception{ Class clazzClass.forName(com.sun.org.apache.xerces.internal.impl.dv.util.Base64); Method mainMethod clazz.getMethod(decode, String.class); mainMethod.setAccessible(true); Object retObjmainMethod.invoke(null, input); return (byte[])retObj; } /** * 返回RSA公钥 * param modules * param exponent * return */ public static PublicKey getPublicKey(String modulus, String exponent){ try { byte[] m decodeBase64(modulus); byte[] e decodeBase64(exponent); BigInteger b1 new BigInteger(1,m); BigInteger b2 new BigInteger(1,e); KeyFactory keyFactory KeyFactory.getInstance(RSA); RSAPublicKeySpec keySpec new RSAPublicKeySpec(b1, b2); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (Exception e) { e.printStackTrace(); return null; } } [java] view plain copypublic static byte[] decodeBase64(String input) throws Exception{ Class clazzClass.forName(com.sun.org.apache.xerces.internal.impl.dv.util.Base64); Method mainMethod clazz.getMethod(decode, String.class); mainMethod.setAccessible(true); Object retObjmainMethod.invoke(null, input); return (byte[])retObj; } /** * 返回RSA公钥 * param modules * param exponent * return */ public static PublicKey getPublicKey(String modulus, String exponent){ try { byte[] m decodeBase64(modulus); byte[] e decodeBase64(exponent); BigInteger b1 new BigInteger(1,m); BigInteger b2 new BigInteger(1,e); KeyFactory keyFactory KeyFactory.getInstance(RSA); RSAPublicKeySpec keySpec new RSAPublicKeySpec(b1, b2); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (Exception e) { e.printStackTrace(); return null; } } 获得公钥后就可以进行RSA加密处理了这里还有一点需要提的是RSA加密解密都有最大长度限制加密最大长度为117字节解密最大长度是128字节此外此处加密得到的数据是经过Base64编码处理的
[java] view plaincopypublic static String encrypt(byte[] source, PublicKey publicKey) throws Exception { String encryptData ; try { Cipher cipher Cipher.getInstance(RSA); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int length source.length; int offset 0; byte[] cache; ByteArrayOutputStream outStream new ByteArrayOutputStream(); int i 0; while(length - offset 0){ if(length - offset MAXENCRYPTSIZE){ cache cipher.doFinal(source, offset, MAXENCRYPTSIZE); }else{ cache cipher.doFinal(source, offset, length - offset); } outStream.write(cache, 0, cache.length); i; offset i * MAXENCRYPTSIZE; } return encodeBase64(outStream.toByteArray()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return encryptData; } [java] view plain copypublic static String encrypt(byte[] source, PublicKey publicKey) throws Exception { String encryptData ; try { Cipher cipher Cipher.getInstance(RSA); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int length source.length; int offset 0; byte[] cache; ByteArrayOutputStream outStream new ByteArrayOutputStream(); int i 0; while(length - offset 0){ if(length - offset MAXENCRYPTSIZE){ cache cipher.doFinal(source, offset, MAXENCRYPTSIZE); }else{ cache cipher.doFinal(source, offset, length - offset); } outStream.write(cache, 0, cache.length); i; offset i * MAXENCRYPTSIZE; } return encodeBase64(outStream.toByteArray()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return encryptData; } 加密后的数据提交给C#服务器端进行解密当然这里也要注意最大长度限制问题
[csharp] view plaincopy/// summary /// RSA解密 /// /summary /// param nameencryptData经过Base64编码的密文/param /// param nameprivateKey私钥/param /// returnsRSA解密后的数据/returns public static string decrypt(string encryptData, string privateKey) { string decryptData ; try { RSACryptoServiceProvider provider new RSACryptoServiceProvider(); provider.FromXmlString(privateKey); byte[] bEncrypt Convert.FromBase64String(encryptData); int length bEncrypt.Length; int offset 0; string cache ; int i 0; while (length - offset 0) { if (length - offset MAXDECRYPTSIZE) { cache Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, MAXDECRYPTSIZE), false)); } else { cache Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, length - offset), false)); } decryptData cache; i; offset i*MAXDECRYPTSIZE; } } catch(Exception e) { throw e; } return decryptData; } /// summary /// 截取字节数组部分字节 /// /summary /// param nameinput/param /// param nameoffset起始偏移位/param /// param namelength截取长度/param /// returns/returns private static byte[] getSplit(byte[] input, int offset, int length) { byte[] output new byte[length]; for (int i offset; i offset length; i) { output[i - offset] input[i]; } return output; } [csharp] view plain copy/// summary /// RSA解密 /// /summary /// param nameencryptData经过Base64编码的密文/param /// param nameprivateKey私钥/param /// returnsRSA解密后的数据/returns public static string decrypt(string encryptData, string privateKey) { string decryptData ; try { RSACryptoServiceProvider provider new RSACryptoServiceProvider(); provider.FromXmlString(privateKey); byte[] bEncrypt Convert.FromBase64String(encryptData); int length bEncrypt.Length; int offset 0; string cache ; int i 0; while (length - offset 0) { if (length - offset MAXDECRYPTSIZE) { cache Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, MAXDECRYPTSIZE), false)); } else { cache Encoding.UTF8.GetString(provider.Decrypt(getSplit(bEncrypt, offset, length - offset), false)); } decryptData cache; i; offset i*MAXDECRYPTSIZE; } } catch(Exception e) { throw e; } return decryptData; } /// summary /// 截取字节数组部分字节 /// /summary /// param nameinput/param /// param nameoffset起始偏移位/param /// param namelength截取长度/param /// returns/returns private static byte[] getSplit(byte[] input, int offset, int length) { byte[] output new byte[length]; for (int i offset; i offset length; i) { output[i - offset] input[i]; } return output; } 这样就顺利完成了。经过测试这样做的确得到了正确的结果。
若是有什么地方有问题还望大家指正
----------------------------------------------------------------------------------------
C# Java间进行RSA加密解密交互二
C# Java间进行RSA加密解密交互三转自http://blog.csdn.net/dslinmy/article/details/37362661