RSA加密解密(二)——用shell加密后java无法解密的问题

我们需要用shell生成加密原文数据,存入mysql中,然后用java取出mysql中的加密数据并解密出原文。

这个任务中遇到的最大问题是,用shell进行base64编码后的加密数据,无法被java的解密程序解密,会报错。

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:370)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:282)
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:370)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:404)
    at javax.crypto.Cipher.doFinal(Cipher.java:2226)
    at cn.chinaunicom.paas.management.utils.RSAHelper.decryptByPrivateKey(RSAHelper.java:107)
    at cn.chinaunicom.paas.management.utils.解密云池密码.main(解密云池密码.java:55)

深入到代码里面看,实际上是由于解密程序运行到unpadV15这个函数里面时,它的第一个字节是2,而不是0,导致了bp返回true,程序就报错终止。

众所周知,第一个字节是有代表意义的,它必须是特定值,不同的填充方式有不同的值。默认是填充0。

究其原因,还是使用shell输出被base64编码的数据的方式不对,没有用对语句消除换行符的影响。

正确的加密解密过程如下,为了方便理解,省略链接mysql的过程。

shell端

首先生成公钥私钥

(1)进入opensll交互

opensll

(2)生成私钥,1024为私钥长度

genrsa -out private_key.pem 1024

(3)将私钥以pkcs8的格式存储

pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt -out pkcs8

(4)生成公钥

rsa -in private_key.pem -pubout -out public_key.pem

(5)编写shell加密脚本

# 初始化原始需要加密数据
data_string="1q2w3e4r5t"
# 把数据保存到文件中。openssl似乎只能从文件中读取数据
echo $data_string > data_string
# 对数据进行base64编码
#data_base64=$(echo -n "$data_string" | base64)
# 把数据保存到文件中,方便openssl进行读取。
#echo $data_base64 > data_base64
# 使用openssl rsautl加密,保存数据到encrypted_data文件
openssl rsautl -encrypt -in data_string -inkey public_key.pem -pubin -out encrypted_data


#正确的输出方式
echo -n $(<encrypted_data) |base64
#错误的输出方式
echo $(<encrypted_data) |base64

 #后面假设将加密后的数据存入了数据库,代码省略

很明显,输出的结果里是不同的。

编写java解密脚本。

public class 解密云池密码
{
    public static void main(String[] args) throws Exception {
        #假设已经从数据库里获取到了base64数据data
        data="JgEbpDVWGgjeXHFGryRTmCvopamerBXQHCOiyD+JrrTTHXBzRRxFqfYZbkIqWqF+5R7weFhPpidL" +
        "qpJ5dL9HXZQ8gqN9SGKwP0QorVGX6n+0Z/nM7RmjN4Hb4bEQ//Eu9vqwLVS5TEB7Zz13zb0I8CyK" +
        "ErXkvb5I+AzCZaW+41U=";
        String strPrivKey = ""//过长,省略。这里填写是pkcs8
        String s = RSAHelper.decryptByPrivateKey(data,strPrivKey);
        System.out.println(s);
    }
}
    //下面是RSAHelper中的decryptByPrivateKey函数的代码
    public static String decryptByPrivateKey(String encryptedDataString, String privateKey)
        throws Exception {
            byte[] encryptedData = Base64Utils.decode(encryptedDataString.getBytes());
            byte[] keyBytes = Base64Utils.decode(privateKey.getBytes());
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORM);
            cipher.init(Cipher.DECRYPT_MODE, privateK);
            int inputLen = encryptedData.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            return new String(decryptedData);
}

输出结果就是我们加密的数据:1q2w3e4r5t

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值