资源中心网关加密解密加签验签介绍
您可以点击纯净版进行查看

加密和加签

在商户和芝麻信用开放平台网关交互的时,需要用到 RSA 的公私钥对。其中商户生成一对 RSA 公私钥,并将 RSA 公钥提供给芝麻信用。芝麻信用也会生成一对 RSA 公私钥,并将 RSA 公钥提供给商户。在一次同芝麻的交互过程中,商户的公私钥对和芝麻的公私钥对的作用如下:

商户端发起请求到芝麻信用时:

  1. 商户使用芝麻信用的 RSA 公钥对业务参数进行 RSA 加密,使用商户自己的 RSA 私钥对业务参数进行签名;
  2. 芝麻信用使用芝麻信用的 RSA 私钥进行业务参数的解密,使用商户的 RSA 公钥进行验签。

芝麻信用返回调用结果给商户时:

  1. 芝麻信用使用商户的 RSA 公钥对业务返回结果进行 RSA 加密,使用芝麻信用自己的 RSA 私钥对业务返回结果进行签名;
  2. 商户使用商户自己的 RSA 私钥对业务返回结果进行解密,使用芝麻的 RSA 公钥对业务返回结果进行验签。

加密过程

芝麻分的三个业务参数分别为 transaction_idproduct_codeopen_id。加密的过程分成以下三步:

1、对单个参数进行 URLEncode,并拼接在一起

transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496)

2、然后对拼接起来的业务参数使用芝麻信用提供给商户的公钥进行 RSA 加密,得到 byte 数组

RSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496))

3、然后对 byte 数组进行 Base64 的编码,得到一个字符串

Base64(RSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496)))

4、对得到的字符串进行 URLEncode

URLEncode(Base64(RSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496))))

经过了上述四步,我们便得到了加密后的业务参数,最后我们将这些加密后业务参数的值最后放入系统参数 params 中。

params=URLEncode(Base64(RSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496))))

加签过程

1、在加密过程的第一步,我们得到了拼接在一起的业务参数,同样以芝麻分为例,拼接的参数如下:

transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496)

2、使用 SHA1WithRSA 算法以及商户自己的私钥进行签名,得到 byte 数组

SHA1WithRSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496))

3、将 byte 数组进行 Base64 编码,得到一个签名的字符串

Base64(SHA1WithRSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496)))

经过了上述三步,我们便得到了业务参数的签名,最后我们将这个签名的值放入系统参数 sign 中:

sign=Base64(SHA1WithRSA(transaction_id=URLEncode(1234567)&product_code=URLEncode(w1010100100000000001)&open_id=URLEncode(268810000007909449496)))

解密和验签

系统调用类接口

在接口调用成功的情况下,开放平台对返回数据进行了加密,开放平台返回值的格式如下:

{
  "encrypted": true,
  "biz_response_sign": "业务数据签名",
  "biz_response": "业务密文数据"
}

这是一个 JSON 格式的数据,商户首先需要解析 encrypted 字段,判断是否需要解密,如果值为 true,那么需要解密,否则无需解密。在需要解密时,使用商户私钥解密 biz_response 字段的值,得到接口的业务返回数据。

在接口调用失败的情况下,开放平台不会对返回数据进行加密,开放平台返回值的格式如下:

{
  "encrypted": false,
  "biz_response": "{\"success\":false,\"error_code\":\"ZMOP.unknow_error\",\"error_message\":\"未知错误\"}"
}

在调用成功的情况下,需要对返回结果进行解密和验签。

解密过程

1、首先从 JSON 格式的返回结果中取出 biz_response 字段, biz_response 字段的值是使用了商户提供给芝麻的 RSA 的公钥进行加密的; 2、对 biz_response 字段的值使用商户自己的 RSA 私钥进行解密( RSA 算法),以芝麻分为例,解密的值为 JSON 格式所示:

{
  "biz_no": "123456",
  "zm_score": "700"
}

其中 zm_score 字段的值 700 为用户的芝麻分。

验签过程

1、在解密过程中,我们已经得到了业务参数解密后的值:

{
  "biz_no": "123456",
  "zm_score": "700"
}

2、取出签名字段 biz_response_sign 的值;

3、使用芝麻提供给商户的 RSA 公钥,利用 SHA1WithRSA 算法进行验签操作,验签算法需要传入签名后的值(biz_response_sign 的值)和签名的源字符串(解密后的 biz_response 的值);

4、如果验签算法返回 true,那么验签成功,否则验签失败。

页面跳转类接口

前面提到在用户页面操作完成后,系统会重定向到商户提供的一个 callback URL 上, 并把业务的返回结果带在 callback URL 里面。格式如下:

http://abc.ab.com/ex/zmxy/auth/callback?params=A4bWiqR%2B1CM1FFOhMbXciqfhWyQSV5TvL5Af4Hhxbx%2BzJilU15oVb7eqRJcgM9HY35cF%2BvAUEKk37rdjtOVUBWZ%2B97yivajLMEqnFrZVWEGgL%2F%2BlnfYX60amZzOk3lu%2FF7LflGwR%2B9uxkoY9PJsqJxihQBiAlK3L%2F%2FgHNIxEiOY%3D&sign=jqOPvDR2dNDF4Jeyle0K6i9sRemTOinCgz9l1NANeFNBT2WvSO72Um3LqAnG2LgrTHf4GfAN2cS4UCHL3Uyet8lyvHQ5hxHNNTQyFfH45FoHv7VecFgROMAFG7fhUgd7jSAuqfnCH31iR8sv%2FGL5IHr9%2B8JXmaObIVs716jm4kY%3D

其中 params 里面是加密后的业务返回结果,sign 是对业务结果加密前的签名;

这两个参数都会在 URLEncode 之后添加在商户提供的 callback URL 后面。

同时,解密验签后得到 resultstate 字段。result=T 代表调用成功,result=F 代表调用失败;state 参数是把商户在调用页面接口时传入的 state 数据原封不动的返回。

解密过程

1、取出 url 中的 params 参数的值;

2、对 params 字段的值使用商户自己的 RSA 私钥进行解密( RSA 算法),得到业务参数值。

验签过程

1、在解密过程中,已经得到了解密后的业务参数值;

2、取出 url 参数中 sign 字段对应的签名值;

3、使用芝麻提供给商户的 RSA 公钥,利用 SHA1WithRSA 算法进行验签操作,验算法需要传入签名后的值(biz_response_sign 的值)和签名的源字符串(解密后的 biz_response 的值);

4、如果验签算法返回 true,那么验签成功,否则验签失败。

授权回调解密验签

Java PHP .NET Python


public void getResult() {
    String params = "Srnlsy8O0SRZ1wYkFBQQPwLh66o0tscIsL7tAEQz%2Fk%2BNW7QeMSKzDFNmh2B%2Fbaq6GnBEXkQTj4PZqLYBQjBvlCRkgRkSx4g%2FP4lJ6JW2UjAQWTN0djSi28NDyQQSP772YZiLtcw%2Fp%2FHmDb2Uhr24Jp2gPxfdzV9gGDl0uY1gNmYxqfG9tsqlNhnL%2FqTZU4KB%2FHt%2Fz3vaogxAZzo3YiB%2Fj47t97%2FUkoNzk2bWvtV12d275dwgYg31MVMKOUc%2BG%2ByRQsZMsDBKoZfhqFoADnuD0i0a%2FguFZcppxxZKCVIpveT29JtkHFXfYC8F2jZaRH5zXQa1odi%2BRv%2Bt%2BF08O1NrnA%3D%3D";
    //从回调URL中获取params参数,此处为示例值
    String sign = "BvAYHmZ29xkuIJoNPomGJCUWUDuSufHOPTTlXpzYtY4e3i9mL6QpwPUDuK0d0F9yPxaHBAVq8YEveNoBPnsryFPE1rL3810a5pcHb8WZb02RVqCbc5j5La3SBdHY1fZRUlQYKPY0KwkipkTZmOXZAHIPU3hgynt1m%2BsAscxonIk%3D";
    //从回调URL中获取sign参数,此处为示例值
    //判断串中是否有%,有则需要decode
    if(params.indexOf("%") != -1) {
        params = URLDecoder.decode(params, charset);
    }
    if(sign.indexOf("%") != -1) {
        sign = URLDecoder.decode(sign, charset);
    }
    DefaultZhimaClient client = new DefaultZhimaClient(gatewayUrl, appId, privateKey, zhimaPublicKey);
    try {
        String result = client.decryptAndVerifySign(params, sign);
        System.out.println(result);
    } catch (ZhimaApiException e) {
        e.printStackTrace();
    }
}
  1. 加密和加签
  2. 解密和验签
  3. 授权回调解密验签
onlineServer