java rsa 117_Java和C# RSA加密密钥互通以及密文字节信息大于117位或128位的终极解决办法 Java和C# RSA加密密钥互通以及密文字节信息大于117位或128...

目前在做RSA解密的过程中,发现C#和java的加密解密过程要想十分顺畅的实现确实有点困难,而且在网上看到大把大把的帖子致力于解决这个神一般的问题,但是别人能解决,到你这可能就不适用了。究其原因,是因为在实现这个问题的过程中,会有各种各样的小错误,就这么一个错误,葬送了你大把的时间和精力。

1、错误列举如下,不能详尽:

A) 密钥不同。这个是最难最繁琐的问题。java中密钥通常是封装在Key里面的,比如PublicKey,PrivateKey,将其转化为string后,会发现这些key是有不同的大整数(BigInteger)组成的;C#中密钥的导入其实普遍就一种情况,FromXmlString(),也就是说在C#中的,你的值是以xml的形式存在的。那么这个时候怎样保证一堆大整数和一个xml组成的key值相同,是很关键的,一旦不能保证,也许就会在c#中出现--“不正确的数据”这种恶心的错误。

B) 编码有误。这个问题很好解决,但是也容易忽略。因为在加密解密过程中你要乐此不疲的编码解码(encode,decode)。要编成什么样的码呢?Base64.用公钥加密后,在返回一个加密的String之前,你得首先将其encode成Base64编码,然后再用私钥解密时,你同样得将这个Base64编码的密文转化回来。估计这个问题很少有人会为此烦恼。

C) 加密密文不能保证正确。 也就是说,你在java端将信息加密后,也许你的密文在C#端不能被正确解密。这个时候就可能是加密密文不正确导致的错误。这个时候你得看看你在加密时,有没有用一种C#里面没用到的东西,我一开始的时候,使用了BouncyCastleProvider()来初始化cipher,结果密文始终不能成功解密。另外值得一提的是,你为了让密文在加密端和解密端是一致的,你反复查看了密文的字节信息,发现他们始终不一样。这个时候不要慌,这里有个很重要的只是点,在java中Base64的String的字节数组是支持有符号的字节的,然而在C#中的就是无符号的了,因此你如果对比出来的结果是下面这个样子的,就不必惊慌了,你传值很正确。

java:[12,23,-1,-2....]

C#:[12,23,255,254.....]

发现没,其实java中负数的字节加上C#中的正数正好是256,所以不要慌了,在内存中他们都是一样一样的。

D) 密文超过117位。似乎当你加密超过117位以后,不管是C#还是java都会出现错误,说你不该加密这么多信息。这个问题不难解决。

E)解密密文超过128位。当你解密超过128位以后,你同样会得到相同的待遇,你不能一次解决太多信息。这个问题应该也很好解决。

2、那么下面我们就来一步一步的解决以上这些恶心的问题。

A) 首先我们生成密钥,一定得保证密钥能过互通。

a)在java端生成KeyPair:

/**

* 生成RSA密钥对

*

* @param keyLength

* 密钥长度,范围:512~2048

* @author wenfengzhuo

*/

publicstaticKeyPair generateRSAKeyPair(intkeyLength) {

try{

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

kpg.initialize(keyLength);

returnkpg.genKeyPair();

} catch(NoSuchAlgorithmException e) {

returnnull;

}

}

b)得到xml形式的密钥,扔给你两个函数,这两个函数是所有网上提供的最精华的,如果出错而且你解决不了,只能说你人品有问题。

/**

* 将私钥转化为xml格式

*

* @param encodedPrivkey=privateKey.getEncoded()

*

* @author wenfengzhuo

*/

private static String  privatekeyinfoToXMLRSAPriKey(byte[] encodedPrivkey) {

try{

StringBuffer buff=newStringBuffer(1024);

PKCS8EncodedKeySpec pvkKeySpec=newPKCS8EncodedKeySpec(encodedPrivkey);

KeyFactory keyFactory=KeyFactory.getInstance("RSA");

RSAPrivateCrtKey pvkKey= (RSAPrivateCrtKey)keyFactory.generatePrivate(pvkKeySpec);

buff.append("") ;

buff.append("" + b64encode(removeMSZero(pvkKey.getModulus().toByteArray())) + "");

buff.append("" + b64encode(removeMSZero(pvkKey.getPublicExponent().toByteArray())) + "");

buff.append("

" + b64encode(removeMSZero(pvkKey.getPrimeP().toByteArray())) + "

");

buff.append("" + b64encode(removeMSZero(pvkKey.getPrimeQ().toByteArray())) + "");

buff.append("" +b64encode(removeMSZero(pvkKey.getPrimeExponentP().toByteArray())) + "");

buff.append("" + b64encode(removeMSZero(pvkKey.getPrimeExponentQ().toByteArray())) + "");

buff.append("" + b64encode(removeMSZero(pvkKey.getCrtCoefficient().toByteArray())) + "");

buff.append("" + b64encode(removeMSZero(pvkKey.getPrivateExponent().toByteArray())) + "");

buff.append("") ;

return buff.toString();

}

catch(Exception e)

{System.err.println(e);

return null ;

}

}

其实公钥也是从私钥中获取的,你熟悉C#中RSA的公私钥的xml格式你就会明白这个函数的意图。

/**

* 将公钥转化为xml格式

*

* @param encodedPrivkey=privateKey.getEncoded()

*

* @author wenfengzhuo

*/

privatestaticString  privatekeyinfoToXMLRSAPubKey(byte[] encodedPrivkey) {

try{

StringBuffer buff = newStringBuffer(1024);

PKCS8EncodedKeySpec pvkKeySpec = newPKCS8EncodedKeySpec(encodedPrivkey);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey)keyFactory.generatePrivate(pvkKeySpec);

buff.append("") ;

buff.append(""+ b64encode(removeMSZero(pvkKey.getModulus().toByteArray())) +"");

buff.append(""+ b64encode(removeMSZero(pvkKey.getPublicExponent().toByteArray())) +"");

buff.append("") ;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RSA是一种非对称加密算法,它可以用于对文件进行加密和解。在Java中,可以使用Java加密库来实现RSA加密和解。下面是一个简单的示例代码: ```java import java.io.*; import java.security.*; import javax.crypto.*; public class RSAEncryption { private static final String PUBLIC_KEY_FILE = "public.key"; private static final String PRIVATE_KEY_FILE = "private.key"; public static void main(String[] args) throws Exception { // 生成对 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); SecureRandom random = new SecureRandom(); keyGen.initialize(1024, random); KeyPair keyPair = keyGen.generateKeyPair(); // 保存公和私到文件 saveKeyToFile(keyPair.getPublic(), PUBLIC_KEY_FILE); saveKeyToFile(keyPair.getPrivate(), PRIVATE_KEY_FILE); // 加密文件 encryptFile("plaintext.txt", "ciphertext.txt", keyPair.getPublic()); // 解文件 decryptFile("ciphertext.txt", "decrypted.txt", keyPair.getPrivate()); } private static void saveKeyToFile(Key key, String fileName) throws IOException { byte[] keyBytes = key.getEncoded(); FileOutputStream fos = new FileOutputStream(fileName); fos.write(keyBytes); fos.close(); } private static void encryptFile(String inputFile, String outputFile, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); byte[] buffer = new byte[100]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, bytesRead); if (output != null) { fos.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { fos.write(output); } fis.close(); fos.flush(); fos.close(); } private static void decryptFile(String inputFile, String outputFile, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); byte[] buffer = new byte[128]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { byte[] output = cipher.update(buffer, 0, bytesRead); if (output != null) { fos.write(output); } } byte[] output = cipher.doFinal(); if (output != null) { fos.write(output); } fis.close(); fos.flush(); fos.close(); } } ``` 上面的代码中,首先生成对,然后保存公和私到文件中。接着,使用公对明文文件进行加密,将文保存到文件中。最后,使用私文文件进行解,将明文保存到文件中。 需要注意的是,RSA算法只能加密长度小的数据,因此在加密大文件时,需要将文件分块加密,并将每个加密块保存到文件中。在解时,将每个加密块读取出来,进行解,然后将解结果拼接起来即可。 另外,由于RSA算法的加密速度比较慢,因此在加密大文件时,可能需要使用其他加密算法,如AES算法,来加密文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值