Base64解决3DES解码报错:javax.crypto.BadPaddingException: Given final block not properly padded

在进行3DES加密时当最后一位不足64时会自动补上,导致解密时报错

javax.crypto.BadPaddingException:   Given   final   block   not   properly   padded 

 

大致逻辑:对原文进行3DES加密,由于存在最后一位不足64位时会自动填充,导致解密时会报错,所以对可能进行了填充(也可能没填充,看最后一位)的3DES密文进行Base64编码,这时可以直接把Base64编码结果转为String进行传输,在其它地方接收到该String,利用getBytes("UTF-8"),得到byte[],进行Base64解码,对解码得到的byte数组进行3DES解密就可以得到原文了。

 

package com.server.model;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.*;
public class SecretTools {

	//3DES
	private static final String algorithm = "DESede";
	private static final String pass_secretkey = "ThisIsAnExampleSecretKeyTest";
	
	//Base64
	private static final Base64.Decoder decoder = Base64.getDecoder();
	private static final Base64.Encoder encoder = Base64.getEncoder();
	
	//Test
	public static void main(String[] args){
		//待加密密文
		String data = "ddbfdskfdsfslksjkffj";
		System.out.println("原始报文内容:"+data);
		
        //加密结果
        //加密结果转为了String进行传输,
        //调用加密的方法,得到了String形式的Base64密文
        //此处Encryption方法中对3DES结果进行了Base64编码
		String b = SecretTools.Encryption(data.getBytes());
		
        //测试点,测试转为String是否导致byte填补丢失
		
        //传输结果转为byte[]进行解密
        //Decrypt方法中先进行了Base64解码
        //再进行了3DES解密
        //doFinal最终得到一个byte[],转为String输出即可得知与原文相同
		byte[] c = SecretTools.Decrypt(b);
		try {
			System.out.println("最终解密报文:"+new String(c,"UTF-8"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//加密算法
	public static String Encryption(byte[] data){
		try {
			SecretKey deskey = new SecretKeySpec(creatdeskey(pass_secretkey),algorithm);
			Cipher ch = Cipher.getInstance(algorithm);
			ch.init(Cipher.ENCRYPT_MODE, deskey);
			byte[] result = ch.doFinal(data);
			System.out.println("3DES对原报文进行加密加密报文:"+new String(result));
			//返回报文经过base64编码
			return SecretTools.aBase64_encript(result);
		} catch (NoSuchAlgorithmException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NoSuchPaddingException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}catch(Exception e3){
			e3.printStackTrace();
		}
		return null;
	}
	//解密算法
	public static byte[] Decrypt(String data){
		try {
			//先进行base64解码
			byte[] da = SecretTools.aBase64_decritp(data);
			SecretKey deskey = new SecretKeySpec(creatdeskey(pass_secretkey),algorithm);
			Cipher ch = Cipher.getInstance(algorithm);
			ch.init(Cipher.DECRYPT_MODE, deskey);
			byte[] des = ch.doFinal(da);
			System.out.println("3DES解密获得原报文:"+new String(des));
			return des;
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (NoSuchPaddingException e2) {
			e2.printStackTrace();
		}catch (Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}
	
    //Base64解码方法
	public static byte[] aBase64_decritp(String encodedText){
		//Base64解碼
		try {
			byte[] textByte = encodedText.getBytes("UTF-8");
			byte[] str = decoder.decode(encodedText);
			System.out.println("Base64解码,得到原始的3DES编码结果:"+new String(str));
			//返回解码结果用于3DES解码
			return str;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//返回解码结果
		return null;
		
	}
	
	//Base64编码方法
	public static String aBase64_encript(byte[] textByte){
			String encodedText = encoder.encodeToString(textByte);
			//输出对应编码结果
			System.out.println("Base64编码用于传输,编码结果:"+encodedText);
			
			//把编码结果返回
			//此编码结果已经转化为string型
			return encodedText;
	}
	
	
	
	//把密钥约定为24位
	public static byte[] creatdeskey(String passkey)throws UnsupportedEncodingException{
		byte[] temp = passkey.getBytes();
		byte[] truekey = new byte[24];
		if(temp.length < truekey.length){
			System.arraycopy(temp, 0, truekey, 0, temp.length);
		}
		else{
			System.arraycopy(temp, 0, truekey, 0, truekey.length);
		}
		return truekey;
	}
}
原始报文内容:ddbfdskfdsfslksjkffj
3DES对原报文进行加密加密报文:夁匽啸qb塟昩&u駄c7猔蝴
Base64编码用于传输,编码结果:id+FXdClcWKJWpViJhwPdfFqYzeqYLr7
Base64解码,得到原始的3DES编码结果:夁匽啸qb塟昩&u駄c7猔蝴
3DES解密获得原报文:ddbfdskfdsfslksjkffj
最终解密报文:ddbfdskfdsfslksjkffj

 


可能会存在因为版本问题导致java.util.Base64不能使用,这种情况你可以使用Apache Commons Codec进行base64编码

	<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

总结:3DES加密报文进行Base64编码,然后转为String传输,接收到的Sring转为byte[],先进行Base64解码,再进行3DES解码,就可以解决这个问题了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值