mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-10-31 18:46:10 +08:00 
			
		
		
		
	#788 批量修改所有使用字符串的getBytes方法的地方,显式使用utf-8编码,以免某些场景下出问题
This commit is contained in:
		| @ -1,12 +1,14 @@ | |||||||
| package me.chanjar.weixin.common.util; | package me.chanjar.weixin.common.util; | ||||||
|  |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import java.nio.charset.StandardCharsets; | ||||||
| import org.apache.commons.codec.binary.Hex; |  | ||||||
|  |  | ||||||
| import javax.crypto.Mac; |  | ||||||
| import javax.crypto.spec.SecretKeySpec; |  | ||||||
| import java.security.InvalidKeyException; | import java.security.InvalidKeyException; | ||||||
| import java.security.NoSuchAlgorithmException; | import java.security.NoSuchAlgorithmException; | ||||||
|  | import javax.crypto.Mac; | ||||||
|  | import javax.crypto.spec.SecretKeySpec; | ||||||
|  |  | ||||||
|  | import org.apache.commons.codec.binary.Hex; | ||||||
|  |  | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * <pre> |  * <pre> | ||||||
| @ -27,9 +29,9 @@ public class SignUtils { | |||||||
|   public static String createHmacSha256Sign(String message, String key) { |   public static String createHmacSha256Sign(String message, String key) { | ||||||
|     try { |     try { | ||||||
|       Mac sha256 = Mac.getInstance("HmacSHA256"); |       Mac sha256 = Mac.getInstance("HmacSHA256"); | ||||||
|       SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); |       SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); | ||||||
|       sha256.init(secretKeySpec); |       sha256.init(secretKeySpec); | ||||||
|       byte[] bytes = sha256.doFinal(message.getBytes()); |       byte[] bytes = sha256.doFinal(message.getBytes(StandardCharsets.UTF_8)); | ||||||
|       return Hex.encodeHexString(bytes).toUpperCase(); |       return Hex.encodeHexString(bytes).toUpperCase(); | ||||||
|     } catch (NoSuchAlgorithmException | InvalidKeyException e) { |     } catch (NoSuchAlgorithmException | InvalidKeyException e) { | ||||||
|       SignUtils.log.error(e.getMessage(), e); |       SignUtils.log.error(e.getMessage(), e); | ||||||
|  | |||||||
| @ -1,22 +1,22 @@ | |||||||
| /** | /* | ||||||
|  * 对公众平台发送给公众账号的消息加解密示例代码. |  * 对公众平台发送给公众账号的消息加解密示例代码. | ||||||
|  * |  * | ||||||
|  * @copyright Copyright (c) 1998-2014 Tencent Inc. |  * @copyright Copyright (c) 1998-2014 Tencent Inc. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| // ------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
| package me.chanjar.weixin.common.util.crypto; | package me.chanjar.weixin.common.util.crypto; | ||||||
|  |  | ||||||
| import java.nio.charset.Charset; | import java.nio.charset.Charset; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 提供基于PKCS7算法的加解 |  * 提供基于PKCS7算法的加解. | ||||||
|  |  * | ||||||
|  |  * @author tencent | ||||||
|  */ |  */ | ||||||
| public class PKCS7Encoder { | public class PKCS7Encoder { | ||||||
|  |   private static final Charset CHARSET = StandardCharsets.UTF_8; | ||||||
|   private static final Charset CHARSET = Charset.forName("utf-8"); |  | ||||||
|   private static final int BLOCK_SIZE = 32; |   private static final int BLOCK_SIZE = 32; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @ -28,20 +28,17 @@ public class PKCS7Encoder { | |||||||
|   public static byte[] encode(int count) { |   public static byte[] encode(int count) { | ||||||
|     // 计算需要填充的位数 |     // 计算需要填充的位数 | ||||||
|     int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); |     int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); | ||||||
|     if (amountToPad == 0) { |  | ||||||
|       amountToPad = BLOCK_SIZE; |  | ||||||
|     } |  | ||||||
|     // 获得补位所用的字符 |     // 获得补位所用的字符 | ||||||
|     char padChr = chr(amountToPad); |     char padChr = chr(amountToPad); | ||||||
|     String tmp = new String(); |     StringBuilder tmp = new StringBuilder(); | ||||||
|     for (int index = 0; index < amountToPad; index++) { |     for (int index = 0; index < amountToPad; index++) { | ||||||
|       tmp += padChr; |       tmp.append(padChr); | ||||||
|     } |     } | ||||||
|     return tmp.getBytes(CHARSET); |     return tmp.toString().getBytes(CHARSET); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * 删除解密后明文的补位字符 |    * 删除解密后明文的补位字符. | ||||||
|    * |    * | ||||||
|    * @param decrypted 解密后的明文 |    * @param decrypted 解密后的明文 | ||||||
|    * @return 删除补位字符后的明文 |    * @return 删除补位字符后的明文 | ||||||
| @ -55,12 +52,12 @@ public class PKCS7Encoder { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * 将数字转化成ASCII码对应的字符,用于对明文进行补码 |    * 将数字转化成ASCII码对应的字符,用于对明文进行补码. | ||||||
|    * |    * | ||||||
|    * @param a 需要转化的数字 |    * @param a 需要转化的数字 | ||||||
|    * @return 转化得到的字符 |    * @return 转化得到的字符 | ||||||
|    */ |    */ | ||||||
|   public static char chr(int a) { |   private static char chr(int a) { | ||||||
|     byte target = (byte) (a & 0xFF); |     byte target = (byte) (a & 0xFF); | ||||||
|     return (char) target; |     return (char) target; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,21 +1,21 @@ | |||||||
| package me.chanjar.weixin.common.util.crypto; | package me.chanjar.weixin.common.util.crypto; | ||||||
|  |  | ||||||
| import org.apache.commons.codec.binary.Base64; | import java.io.StringReader; | ||||||
| import org.w3c.dom.Document; | import java.nio.charset.Charset; | ||||||
| import org.w3c.dom.Element; | import java.nio.charset.StandardCharsets; | ||||||
| import org.xml.sax.InputSource; | import java.util.Arrays; | ||||||
|  | import java.util.Random; | ||||||
| import javax.crypto.Cipher; | import javax.crypto.Cipher; | ||||||
| import javax.crypto.spec.IvParameterSpec; | import javax.crypto.spec.IvParameterSpec; | ||||||
| import javax.crypto.spec.SecretKeySpec; | import javax.crypto.spec.SecretKeySpec; | ||||||
| import javax.xml.parsers.DocumentBuilder; | import javax.xml.parsers.DocumentBuilder; | ||||||
| import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||||
| import javax.xml.parsers.ParserConfigurationException; | import javax.xml.parsers.ParserConfigurationException; | ||||||
| import java.io.StringReader; |  | ||||||
| import java.nio.charset.Charset; | import org.apache.commons.codec.binary.Base64; | ||||||
| import java.nio.charset.StandardCharsets; | import org.w3c.dom.Document; | ||||||
| import java.util.Arrays; | import org.w3c.dom.Element; | ||||||
| import java.util.Random; | import org.xml.sax.InputSource; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * <pre> |  * <pre> | ||||||
| @ -25,6 +25,8 @@ import java.util.Random; | |||||||
|  * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本) |  * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本) | ||||||
|  * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi |  * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi | ||||||
|  * </pre> |  * </pre> | ||||||
|  |  * | ||||||
|  |  * @author Tencent | ||||||
|  */ |  */ | ||||||
| public class WxCryptUtil { | public class WxCryptUtil { | ||||||
|  |  | ||||||
| @ -164,8 +166,7 @@ public class WxCryptUtil { | |||||||
|     ByteGroup byteCollector = new ByteGroup(); |     ByteGroup byteCollector = new ByteGroup(); | ||||||
|     byte[] randomStringBytes = randomStr.getBytes(CHARSET); |     byte[] randomStringBytes = randomStr.getBytes(CHARSET); | ||||||
|     byte[] plainTextBytes = plainText.getBytes(CHARSET); |     byte[] plainTextBytes = plainText.getBytes(CHARSET); | ||||||
|     byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder( |     byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(plainTextBytes.length); | ||||||
|       plainTextBytes.length); |  | ||||||
|     byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET); |     byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET); | ||||||
|  |  | ||||||
|     // randomStr + networkBytesOrder + text + appid |     // randomStr + networkBytesOrder + text + appid | ||||||
| @ -252,7 +253,7 @@ public class WxCryptUtil { | |||||||
|       throw new RuntimeException(e); |       throw new RuntimeException(e); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     String xmlContent, from_appid; |     String xmlContent, fromAppid; | ||||||
|     try { |     try { | ||||||
|       // 去除补位字符 |       // 去除补位字符 | ||||||
|       byte[] bytes = PKCS7Encoder.decode(original); |       byte[] bytes = PKCS7Encoder.decode(original); | ||||||
| @ -264,14 +265,14 @@ public class WxCryptUtil { | |||||||
|  |  | ||||||
|       xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), |       xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), | ||||||
|         CHARSET); |         CHARSET); | ||||||
|       from_appid = new String( |       fromAppid = new String( | ||||||
|         Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); |         Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); | ||||||
|     } catch (Exception e) { |     } catch (Exception e) { | ||||||
|       throw new RuntimeException(e); |       throw new RuntimeException(e); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // appid不相同的情况 |     // appid不相同的情况 | ||||||
|     if (!from_appid.equals(this.appidOrCorpid)) { |     if (!fromAppid.equals(this.appidOrCorpid)) { | ||||||
|       throw new RuntimeException("AppID不正确"); |       throw new RuntimeException("AppID不正确"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| package me.chanjar.weixin.common.util.http; | package me.chanjar.weixin.common.util.http; | ||||||
|  |  | ||||||
|  |  | ||||||
| import org.apache.commons.lang3.StringUtils; | import java.nio.charset.StandardCharsets; | ||||||
|  |  | ||||||
| import java.io.UnsupportedEncodingException; | import org.apache.commons.lang3.StringUtils; | ||||||
|  |  | ||||||
| public class URIUtil { | public class URIUtil { | ||||||
|  |  | ||||||
| @ -16,27 +16,22 @@ public class URIUtil { | |||||||
|  |  | ||||||
|     int l = input.length(); |     int l = input.length(); | ||||||
|     StringBuilder o = new StringBuilder(l * 3); |     StringBuilder o = new StringBuilder(l * 3); | ||||||
|     try { |     for (int i = 0; i < l; i++) { | ||||||
|       for (int i = 0; i < l; i++) { |       String e = input.substring(i, i + 1); | ||||||
|         String e = input.substring(i, i + 1); |       if (!ALLOWED_CHARS.contains(e)) { | ||||||
|         if (ALLOWED_CHARS.indexOf(e) == -1) { |         byte[] b = e.getBytes(StandardCharsets.UTF_8); | ||||||
|           byte[] b = e.getBytes("utf-8"); |         o.append(getHex(b)); | ||||||
|           o.append(getHex(b)); |         continue; | ||||||
|           continue; |  | ||||||
|         } |  | ||||||
|         o.append(e); |  | ||||||
|       } |       } | ||||||
|       return o.toString(); |       o.append(e); | ||||||
|     } catch (UnsupportedEncodingException e) { |  | ||||||
|       e.printStackTrace(); |  | ||||||
|     } |     } | ||||||
|     return input; |     return o.toString(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private static String getHex(byte buf[]) { |   private static String getHex(byte[] buf) { | ||||||
|     StringBuilder o = new StringBuilder(buf.length * 3); |     StringBuilder o = new StringBuilder(buf.length * 3); | ||||||
|     for (int i = 0; i < buf.length; i++) { |     for (byte aBuf : buf) { | ||||||
|       int n = buf[i] & 0xff; |       int n = aBuf & 0xff; | ||||||
|       o.append("%"); |       o.append("%"); | ||||||
|       if (n < 0x10) { |       if (n < 0x10) { | ||||||
|         o.append("0"); |         o.append("0"); | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package com.github.binarywang.wxpay.bean.notify; | package com.github.binarywang.wxpay.bean.notify; | ||||||
|  |  | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| import javax.crypto.Cipher; | import javax.crypto.Cipher; | ||||||
| import javax.crypto.spec.SecretKeySpec; | import javax.crypto.spec.SecretKeySpec; | ||||||
|  |  | ||||||
| @ -48,7 +49,7 @@ public class WxPayRefundNotifyResult extends BaseWxPayResult implements Serializ | |||||||
|     String reqInfoString = result.getReqInfoString(); |     String reqInfoString = result.getReqInfoString(); | ||||||
|     try { |     try { | ||||||
|       final String keyMd5String = DigestUtils.md5Hex(mchKey).toLowerCase(); |       final String keyMd5String = DigestUtils.md5Hex(mchKey).toLowerCase(); | ||||||
|       SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(), "AES"); |       SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(StandardCharsets.UTF_8), "AES"); | ||||||
|  |  | ||||||
|       Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); |       Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); | ||||||
|       cipher.init(Cipher.DECRYPT_MODE, key); |       cipher.init(Cipher.DECRYPT_MODE, key); | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import java.io.ByteArrayInputStream; | |||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||||
| @ -192,7 +193,7 @@ public abstract class BaseWxPayResult implements Serializable { | |||||||
|       this.xmlDoc = DocumentBuilderFactory |       this.xmlDoc = DocumentBuilderFactory | ||||||
|         .newInstance() |         .newInstance() | ||||||
|         .newDocumentBuilder() |         .newDocumentBuilder() | ||||||
|         .parse(new ByteArrayInputStream(this.xmlString.getBytes("UTF-8"))); |         .parse(new ByteArrayInputStream(this.xmlString.getBytes(StandardCharsets.UTF_8))); | ||||||
|       return xmlDoc; |       return xmlDoc; | ||||||
|     } catch (SAXException | IOException | ParserConfigurationException e) { |     } catch (SAXException | IOException | ParserConfigurationException e) { | ||||||
|       throw new RuntimeException("非法的xml文本内容:" + this.xmlString); |       throw new RuntimeException("非法的xml文本内容:" + this.xmlString); | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package com.github.binarywang.wxpay.service.impl; | |||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileReader; | import java.io.FileReader; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.security.PublicKey; | import java.security.PublicKey; | ||||||
| @ -126,7 +127,7 @@ public class EntPayServiceImpl implements EntPayService { | |||||||
|           .getPublicKey((SubjectPublicKeyInfo) reader.readObject()); |           .getPublicKey((SubjectPublicKeyInfo) reader.readObject()); | ||||||
|  |  | ||||||
|         cipher.init(Cipher.ENCRYPT_MODE, publicKey); |         cipher.init(Cipher.ENCRYPT_MODE, publicKey); | ||||||
|         byte[] encrypt = cipher.doFinal(srcString.getBytes()); |         byte[] encrypt = cipher.doFinal(srcString.getBytes(StandardCharsets.UTF_8)); | ||||||
|         return Base64.encodeBase64String(encrypt); |         return Base64.encodeBase64String(encrypt); | ||||||
|       } |       } | ||||||
|     } catch (Exception e) { |     } catch (Exception e) { | ||||||
| @ -138,7 +139,7 @@ public class EntPayServiceImpl implements EntPayService { | |||||||
|     try { |     try { | ||||||
|       String publicKeyStr = this.getPublicKey(); |       String publicKeyStr = this.getPublicKey(); | ||||||
|       Path tmpFile = Files.createTempFile("payToBank", ".pem"); |       Path tmpFile = Files.createTempFile("payToBank", ".pem"); | ||||||
|       Files.write(tmpFile, publicKeyStr.getBytes()); |       Files.write(tmpFile, publicKeyStr.getBytes(StandardCharsets.UTF_8)); | ||||||
|       return tmpFile.toFile(); |       return tmpFile.toFile(); | ||||||
|     } catch (Exception e) { |     } catch (Exception e) { | ||||||
|       throw new WxPayException("生成加密公钥文件时发生异常", e); |       throw new WxPayException("生成加密公钥文件时发生异常", e); | ||||||
| @ -162,7 +163,7 @@ public class EntPayServiceImpl implements EntPayService { | |||||||
|       "p7kM7BoaY2goFgYAe4DsI8Fh33dCOiKyVwIDAQAB\n" + |       "p7kM7BoaY2goFgYAe4DsI8Fh33dCOiKyVwIDAQAB\n" + | ||||||
|       "-----END RSA PUBLIC KEY-----"; |       "-----END RSA PUBLIC KEY-----"; | ||||||
|     Path tmpFile = Files.createTempFile("payToBank", ".pem"); |     Path tmpFile = Files.createTempFile("payToBank", ".pem"); | ||||||
|     Files.write(tmpFile, key.getBytes()); |     Files.write(tmpFile, key.getBytes(StandardCharsets.UTF_8)); | ||||||
|     System.out.println(new EntPayServiceImpl(null).encryptRSA(tmpFile.toFile(), "111111")); |     System.out.println(new EntPayServiceImpl(null).encryptRSA(tmpFile.toFile(), "111111")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,19 +1,20 @@ | |||||||
| package com.github.binarywang.wxpay.bean.notify; | package com.github.binarywang.wxpay.bean.notify; | ||||||
|  |  | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.security.MessageDigest; | ||||||
|  | import javax.crypto.Cipher; | ||||||
|  | import javax.crypto.spec.SecretKeySpec; | ||||||
|  | import javax.inject.Inject; | ||||||
|  |  | ||||||
|  | import org.apache.commons.codec.binary.Base64; | ||||||
|  | import org.testng.annotations.*; | ||||||
|  |  | ||||||
| import com.github.binarywang.wxpay.config.WxPayConfig; | import com.github.binarywang.wxpay.config.WxPayConfig; | ||||||
| import com.github.binarywang.wxpay.exception.WxPayException; | import com.github.binarywang.wxpay.exception.WxPayException; | ||||||
| import com.github.binarywang.wxpay.testbase.ApiTestModule; | import com.github.binarywang.wxpay.testbase.ApiTestModule; | ||||||
| import org.apache.commons.codec.binary.Base64; |  | ||||||
| import org.testng.annotations.Guice; |  | ||||||
| import org.testng.annotations.Test; |  | ||||||
|  |  | ||||||
| import javax.crypto.Cipher; | import static org.testng.Assert.*; | ||||||
| import javax.crypto.spec.SecretKeySpec; |  | ||||||
| import javax.inject.Inject; |  | ||||||
| import java.math.BigInteger; |  | ||||||
| import java.security.MessageDigest; |  | ||||||
|  |  | ||||||
| import static org.testng.Assert.assertNotNull; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * <pre> |  * <pre> | ||||||
| @ -71,10 +72,10 @@ public class WxPayRefundNotifyResultTest { | |||||||
|  |  | ||||||
|     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); |     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); | ||||||
|     final MessageDigest md5 = MessageDigest.getInstance("MD5"); |     final MessageDigest md5 = MessageDigest.getInstance("MD5"); | ||||||
|     md5.update(this.wxPayConfig.getMchKey().getBytes()); |     md5.update(this.wxPayConfig.getMchKey().getBytes(StandardCharsets.UTF_8)); | ||||||
|     final String keyMd5String = new BigInteger(1, md5.digest()).toString(16).toLowerCase(); |     final String keyMd5String = new BigInteger(1, md5.digest()).toString(16).toLowerCase(); | ||||||
|     SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(), "AES"); |     SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(StandardCharsets.UTF_8), "AES"); | ||||||
|     cipher.init(Cipher.ENCRYPT_MODE, key); |     cipher.init(Cipher.ENCRYPT_MODE, key); | ||||||
|     System.out.println(Base64.encodeBase64String(cipher.doFinal(xml.getBytes()))); |     System.out.println(Base64.encodeBase64String(cipher.doFinal(xml.getBytes(StandardCharsets.UTF_8)))); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Binary Wang
					Binary Wang