微信退款通知解密错误pad block corrupted 或者pad block corrupted

有些朋友可能遇到了下面的错误:
pad block corrupted
或者
last block incomplete in decryption
这很有可能是编码错误导致的
微信支付将req_info进行base64编码时,用的字符集不是UTF-8, 而是ISO-8859-1
如果你用UTF-8进行解码, 就一定会报错.

原因是:
将一个byte[]转换成String, 然后再从String转换为byte[]时,
第一个byte[]的值和第二个byte[]的值是不同的,
除非你指定字符集为ISO-8859-1, 或者默认字符集为ISO-8859-1.

由于UTF-8是多字节编码,需要用多个字节来表示一个字符的编码,所以也就出现了在转换之后byte[]数组长度、内容不一致的情况。
而ISO-8859-1编码是单字节编码,所以使用该编码就不会出现上面的问题

详情见下贴:
https://blog.csdn.net/qq_27760433/article/details/78327328

怎样解决这个问题呢?
方法有两种:
(1),
如果你使用java 8 自带的java.util.Base64类,
例如:
Base64.Decoder decoder = Base64.getDecoder();

那么解密方法这么写:

public static String decryptData(final String base64Data) throws Exception
{
	final Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
	cipher.init(Cipher.DECRYPT_MODE, key);
	return new String(cipher.doFinal(CyptoUtil.base64_decode_8859(base64Data).getBytes("ISO-8859-1")), "utf-8");
	//注意:第一个是ISO-8859-1,第二个是utf-8
}

上面的CyptoUtil.base64_decode_8859的定义如下:

public static String base64_decode_8859(final String source)
{
	String result = "";


	final Base64.Decoder decoder = Base64.getDecoder();
	try
	{
		result = new String(decoder.decode(source), "ISO-8859-1");
		//此处的字符集是ISO-8859-1
	}
	catch (final UnsupportedEncodingException e)
	{
		e.printStackTrace();
	}


	return result;
}

对应地, 加密的方法这么写:

public static String encryptData(final String data) throws Exception
{
	// 创建密码器
	final Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
	// 初始化
	cipher.init(Cipher.ENCRYPT_MODE, key);
	return CyptoUtil.base64_encode_8859(new String(cipher.doFinal(data.getBytes()), "ISO-8859-1"));
}

上面的CyptoUtil.base64_encode_8859()定义如下:

public static String base64_encode_8859(final String source)
{
	String result = "";

	final Base64.Encoder encoder = Base64.getEncoder();
	byte[] textByte = null;
	try
	{
		textByte = source.getBytes("ISO-8859-1");
                //注意此处的编码是ISO-8859-1
	}
	catch (final UnsupportedEncodingException e)
	{
		e.printStackTrace();
	}
	result = encoder.encodeToString(textByte);
	return result;
}

(2),

第二种方法是: 不要用java 8 自带的java.util.Base64类, 而找一个其他人写好的Base64Util工具类
例如这个:
https://blog.csdn.net/m0_37218608/article/details/79505068

两种方法我个人推荐第一种, 毕竟是JAVA官方提供的,值得信赖!

本文主要想强调编码错误, 其余代码请参考:

https://blog.csdn.net/u010660575/article/details/76672402


你可能感兴趣的:(微信支付)