支付宝和微信接口加密规范调研

支付宝(ISV)

参考文档:https://docs.open.alipay.com/291/106115

签名方式:RSA2

具体实现

初始化 AlipayClient

1
AlipayClient alipayClient = new DefaultAlipayClient(gateway,app_id,private_key,"json",charset,alipay_public_key,sign_type);

具体签名过程

  1. 获取encryptor,加密关键参数部分

    1
    2
    String encryptContent = getEncryptor().encrypt(
    appParams.get(AlipayConstants.BIZ_CONTENT_KEY), this.encryptType, this.charset)

    加密算法

    1
    2
    3
    4
    5
    6
    7
    8
    Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG);

    IvParameterSpec iv = new IvParameterSpec(AES_IV);
    cipher.init(Cipher.ENCRYPT_MODE,
    new SecretKeySpec(Base64.decodeBase64(aesKey.getBytes()), AES_ALG), iv);

    byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
    return new String(Base64.encodeBase64(encryptBytes));
  2. 签名

    1
    2
    3
    String signContent = AlipaySignature.getSignatureContent(requestHolder);
    protocalMustParams.put(AlipayConstants.SIGN,
    getSigner().sign(signContent, this.signType, charset));

    签名算法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
    new ByteArrayInputStream(privateKey.getBytes()));

    java.security.Signature signature = java.security.Signature
    .getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);

    signature.initSign(priKey);

    if (StringUtils.isEmpty(charset)) {
    signature.update(content.getBytes());
    } else {
    signature.update(content.getBytes(charset));
    }

    byte[] signed = signature.sign();

    return new String(Base64.encodeBase64(signed));
  3. 增加accessToken等参数发起访问

微信(ISV)

主要依靠token机制,支持post,get,消息体明文传输

消息内返回需要加密:

加密机制:aes

主要加密逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public String encrypt(String plainText) {
String encryptedXml = this.encrypt(genRandomStr(), plainText);
String timeStamp = Long.toString(System.currentTimeMillis() / 1000L);
String nonce = genRandomStr();
String signature = SHA1.gen(new String[]{this.token, timeStamp, nonce, encryptedXml});
return generateXml(encryptedXml, signature, timeStamp, nonce);
}
protected String encrypt(String randomStr, String plainText) {
ByteGroup byteCollector = new ByteGroup();
byte[]a randomStringBytes = randomStr.getBytes(CHARSET);
byte[] plainTextBytes = plainText.getBytes(CHARSET);
byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(plainTextBytes.length);
byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET);
byteCollector.addBytes(randomStringBytes);
byteCollector.addBytes(bytesOfSizeInNetworkOrder);
byteCollector.addBytes(plainTextBytes);
byteCollector.addBytes(appIdBytes);
byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
byteCollector.addBytes(padBytes);
byte[] unencrypted = byteCollector.toBytes();

try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(this.aesKey, 0, 16);
cipher.init(1, keySpec, iv);
byte[] encrypted = cipher.doFinal(unencrypted);
return BASE64.encodeToString(encrypted);
} catch (Exception var14) {
throw new RuntimeException(var14);
}
}