-
-
Notifications
You must be signed in to change notification settings - Fork 9.1k
feat(miniapp): 实现小程序加密网络通道服务端支持,修复 HMAC 签名与错误处理 Bug #3969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| import org.testng.annotations.*; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
|
||
| /** | ||
| * <pre> | ||
|
|
@@ -14,6 +15,11 @@ | |
| * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||
| */ | ||
| public class WxMaCryptUtilsTest { | ||
| // 模拟来自 getUserEncryptKey 接口返回的 encrypt_key(Base64,解码后 16 字节) | ||
| // 和 iv(Hex,32 位十六进制字符,解码后 16 字节,AES-128-CBC 要求) | ||
| private static final String ENCRYPT_KEY = "VI6BpyrK9XH4i4AIGe86tg=="; | ||
| private static final String HEX_IV = "6003f73ec441c3866003f73ec441c386"; | ||
|
|
||
| @Test | ||
| public void testDecrypt() { | ||
| String sessionKey = "7MG7jbTToVVRWRXVA885rg=="; | ||
|
|
@@ -32,4 +38,98 @@ public void testDecryptAnotherWay() { | |
| assertThat(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr)) | ||
| .isEqualTo(WxMaCryptUtils.decryptAnotherWay(sessionKey, encryptedData, ivStr)); | ||
| } | ||
|
|
||
| /** | ||
| * 测试使用用户加密 key(来自小程序加密网络通道)进行加密和解密的对称性. | ||
| * encrypt_key 为 Base64 编码的 16 字节 AES-128 密钥,iv 为 Hex 编码的 16 字节初始向量。 | ||
| */ | ||
| @Test | ||
| public void testEncryptAndDecryptWithEncryptKey() { | ||
| String plainText = "{\"userId\":\"12345\",\"amount\":100}"; | ||
|
|
||
| String encrypted = WxMaCryptUtils.encryptWithEncryptKey(ENCRYPT_KEY, HEX_IV, plainText); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests only assert encrypt/decrypt round-trip symmetry, so they can still pass even if the algorithm/encoding doesn’t match WeChat’s expected wire format (both sides could be consistently wrong). Consider adding at least one fixed test vector (known plaintext → expected ciphertext, or vice versa) from the official doc/examples to validate interoperability. Severity: medium 🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||
| assertThat(encrypted).isNotNull().isNotEmpty(); | ||
|
|
||
| String decrypted = WxMaCryptUtils.decryptWithEncryptKey(ENCRYPT_KEY, HEX_IV, encrypted); | ||
| assertThat(decrypted).isEqualTo(plainText); | ||
| } | ||
|
|
||
| /** | ||
| * 测试加密网络通道的加解密对称性(不同明文). | ||
| */ | ||
| @Test | ||
| public void testEncryptDecryptSymmetryWithEncryptKey() { | ||
| String plainText = "hello miniprogram"; | ||
|
|
||
| String encrypted = WxMaCryptUtils.encryptWithEncryptKey(ENCRYPT_KEY, HEX_IV, plainText); | ||
| String decrypted = WxMaCryptUtils.decryptWithEncryptKey(ENCRYPT_KEY, HEX_IV, encrypted); | ||
| assertThat(decrypted).isEqualTo(plainText); | ||
| } | ||
|
Comment on lines
+46
to
+67
|
||
|
|
||
| /** | ||
| * 测试 hexIv 为奇数长度时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testEncryptWithEncryptKeyInvalidHexIvOddLength() { | ||
| assertThatThrownBy(() -> WxMaCryptUtils.encryptWithEncryptKey(ENCRYPT_KEY, "abc", "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("长度必须为偶数"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试 hexIv 包含非十六进制字符时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testEncryptWithEncryptKeyInvalidHexIvNonHexChar() { | ||
| // 32 位但含非法字符 'z' | ||
| assertThatThrownBy(() -> WxMaCryptUtils.encryptWithEncryptKey( | ||
| ENCRYPT_KEY, "6003f73ec441c3866003f73ec441z386", "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("非法字符"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试 hexIv 解码后不足 16 字节(如仅 16 位 hex = 8 字节)时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testEncryptWithEncryptKeyShortHexIv() { | ||
| // 16 位 hex = 8 字节,不满足 AES-CBC 要求的 16 字节 | ||
| assertThatThrownBy(() -> WxMaCryptUtils.encryptWithEncryptKey( | ||
| ENCRYPT_KEY, "6003f73ec441c386", "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("hexIv 解码后必须为 16 字节"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试 encryptKey 解码后不足 16 字节时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testEncryptWithEncryptKeyShortKey() { | ||
| // Base64 编码的 8 字节 key(不符合 AES-128 要求) | ||
| String shortKey = java.util.Base64.getEncoder().encodeToString(new byte[8]); | ||
| assertThatThrownBy(() -> WxMaCryptUtils.encryptWithEncryptKey(shortKey, HEX_IV, "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("encryptKey 解码后必须为 16 字节"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试 decryptWithEncryptKey 使用非法 hexIv 时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testDecryptWithEncryptKeyInvalidHexIv() { | ||
| assertThatThrownBy(() -> WxMaCryptUtils.decryptWithEncryptKey(ENCRYPT_KEY, "abc", "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("长度必须为偶数"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试 decryptWithEncryptKey encryptKey 长度不合法时,应抛出 IllegalArgumentException. | ||
| */ | ||
| @Test | ||
| public void testDecryptWithEncryptKeyShortKey() { | ||
| String shortKey = java.util.Base64.getEncoder().encodeToString(new byte[8]); | ||
| assertThatThrownBy(() -> WxMaCryptUtils.decryptWithEncryptKey(shortKey, HEX_IV, "data")) | ||
| .isInstanceOf(IllegalArgumentException.class) | ||
| .hasMessageContaining("encryptKey 解码后必须为 16 字节"); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decryptWithEncryptKeycatches allExceptionand wraps it intoWxRuntimeException, which means invalidhexIv(fromhexToBytes’sIllegalArgumentException) won’t be observable asIllegalArgumentExceptionby callers and the specific validation message is lost; is that intended given the Javadoc contract onhexToBytes? Other locations where this applies: weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java:141.Severity: medium
Other Locations
weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/crypt/WxMaCryptUtils.java:141🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.