cipher java 长度不变_RSA加解密的java实现(及中途的各种异常情况分析)

RSA加密算法是一种非对称的加密算法,主要包括以下知识点:

1、密钥对的获取:主要涉及到两个参数:秘钥格式、秘钥长度

(1)常见秘钥格式:PKCS8(java适用)、PKCS1(其他),如果不是java平台生成的秘钥,有可能报以下错误:

java.security.InvalidKeyException: invalid key format //秘钥格式不合法

(2)秘钥长度:1024、2048(越长越安全,效率越低),详细介绍可以参考 :https://blog.csdn.net/luoluo_onion/article/details/78354799

注意:分段加解密时:1024的秘钥每次加密最大长度为117(128-11),长度为2048秘钥每次加解密长度为256,如果加密时设置的长度不匹配,可能会报以下错误:

javax.crypto.BadPaddingException : Decryption error //解码失败

秘钥获取的代码实现:java.security.KeyPairGenerator提供了生成秘钥的API,只需要调用即可。

public static Map genKeyPair() throwsException {

KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance(KEY_ALGORITHM);

keyPairGen.initialize(1024);//2048

KeyPair keyPair =keyPairGen.generateKeyPair();

RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();

RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();

Map keyMap = new HashMap(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);returnkeyMap;

}

2、keyMap总的秘钥都是java.security.Key类型的,如要传递或者显示,可以转码为Base64,

public static String getPrivateKey(Map keyMap) throwsException {

Key key=(Key) keyMap.get(PRIVATE_KEY);returnBase64.encodeBase64String(key.getEncoded());

}

3、加密实现(公钥加密)

(1)获取Cipher需要的java.security.Key类型公钥;

(2)调用getInstance()方法获取cipher实例,参数为填充方式(加密和解密的填充方式要统一,否则解密失败!)

(3)使用公钥初始化cipher实例,同时设置加解密类型

(4)对数据进行分段加密,得到字节数组。

private static byte[] encryptByPublicKey(byte[] data, String publicKey) throwsException {byte[] keyBytes =Base64.decodeBase64(publicKey);

X509EncodedKeySpec x509KeySpec= newX509EncodedKeySpec(keyBytes);

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

Key publicK=keyFactory.generatePublic(x509KeySpec);//对数据加密

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.ENCRYPT_MODE, publicK);int inputLen =data.length;

ByteArrayOutputStream out= newByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;//对数据分段加密

while (inputLen - offSet > 0) {if (inputLen - offSet > 256) {

cache= cipher.doFinal(data, offSet, 256);

}else{

cache= cipher.doFinal(data, offSet, inputLen -offSet);

}

out.write(cache,0, cache.length);

i++;

offSet= i * 256;

}byte[] encryptedData =out.toByteArray();

out.close();returnencryptedData;

}

4、解密实现

(1)获取Cipher需要的java.security.Key类型私钥;

(2)调用getInstance()方法获取cipher实例,参数为填充方式(加密和解密的填充方式要统一,否则解密失败!)

(3)使用私钥初始化cipher实例,同时设置类型为解密类型

(4)分段解密,得到字节数组。

private static byte[] decryptByPrivateKey(byte[] data, String privateKey) throwsException {//得到私钥

byte[] keyBytes =Base64.decodeBase64(privateKey.getBytes());

PKCS8EncodedKeySpec pKCS8EncodedKeySpec= newPKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);

Key key=keyFactory.generatePrivate(pKCS8EncodedKeySpec);//解密数据

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

cipher.init(Cipher.DECRYPT_MODE, key);//SealedObject obj = new SealedObject(data, cipher);

int inputLen =data.length;

System.out.println(data);

System.out.println(inputLen);

ByteArrayOutputStream out= newByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;//对数据分段解�?

while (inputLen - offSet > 0) {if (inputLen - offSet >MAX_DECRYPT_BLOCK) {

cache=cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);

}else{

cache= cipher.doFinal(data, offSet, inputLen -offSet);

}

out.write(cache,0, cache.length);

i++;

offSet= i *MAX_DECRYPT_BLOCK;

}byte[] decryptedData =out.toByteArray();

out.close();//byte[] messageBytes = (byte[]) obj.getObject(cipher);

returndecryptedData;

}

5由于本人是首次接触RSA,并且对加密算法一片空白,所以过程中几乎把能遇见的错误碰了个遍,总结以下几个常见错误,引以为戒:

(1)java.security.InvalidKeyException: invalid key format

秘钥格式不合法,或者是秘钥被修改了。

(2)java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big.

秘钥字符串主体前后有空格,或者是换行,或者有多余字段,如(-----BEGIN RSA PRIVATE KEY-----)(秘钥格式不正确)

(3)java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

原因可能是没有使用 PKCS8(java适用)

(4)javax.crypto.BadPaddingException : Decryption error

解密时报这个错误,很可能是填充格式不匹配,请确认加密时使用的填充格式,解密时保持统一即可,我这里使用功能的是RSA/ECB/PKCS1Padding

(5)javax.crypto.BadPaddingException: Message is larger than modulus

解密时出现这个错误(这个错误我是羞于启齿的),可能是因为要解密的字符串中混入了什么奇怪的东西,你可以在解密前打印下要解密的字符串,再打印下转为base64后的字节数组长度(正常应该为128的倍数),否则应该是手残多加了什么东西呢。

备注:以上内容是个人见解,疏漏之处,望各位不吝赐教!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中可以通过使用Java Cryptography Architecture(JCA)提供的RSA类来实现RSA加密解密。首先,您需要生成一对RSA密钥,其中一个是公钥,另一个是私钥。然后,您可以使用公钥对数据进行加密,使用私钥对加密后的数据进行解密。 下面是一个简单的示例代码,展示了如何使用Java实现RSA加密解密: ```java import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import javax.crypto.Cipher; public class RSAExample { public static void main(String[] args) throws Exception { // 生成RSA密钥对 KeyPair keyPair = generateKeyPair(); // 待加密的明文 String plaintext = "Hello, RSA!"; // 使用公钥加密明文 byte[] encryptedData = encrypt(plaintext, keyPair.getPublic()); // 使用私钥解密密文 String decryptedText = decrypt(encryptedData, keyPair.getPrivate()); System.out.println("明文: " + plaintext); System.out.println("加密后的密文: " + new String(encryptedData)); System.out.println("解密后的明文: " + decryptedText); } // 生成RSA密钥对 public static KeyPair generateKeyPair() throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); keyPairGenerator.initialize(2048); return keyPairGenerator.generateKeyPair(); } // 使用公钥加密 public static byte[] encrypt(String plaintext, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(plaintext.getBytes()); } // 使用私钥解密 public static String decrypt(byte[] encryptedData, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedData = cipher.doFinal(encryptedData); return new String(decryptedData); } } ``` 请注意,上述示例使用了Bouncy Castle加密库,您需要在项目中添加Bouncy Castle的相关依赖。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值