SCFP外联平台对接技术说明书

SCFP外联平台对接技术说明书

1. 文档说明

1.1 阅读对象

1.2 修订记录

版本号修订时间更改内容描述修订人审核人
V1.020220103初稿***

2. 接口规范

2.1 协议规则

  • 传输方式:采用HTTPS传输
  • 提交方式:采用POST方法提交
  • 数据格式:提交和返回数据都为JSON格式
  • 字符编码:统一采用UTF-8字符编码
  • 签名算法:统一采用SM2摘要签名算法,具体为sm3withsm2
  • 加密算法:统一采用SM4国密算法对报文加解密

2.2 环境地址

2.3 系统对接

在这里插入图片描述

2.4 HTTP请求头

序号字段是否必输说明备注
1Content-Type内容类型application/json;charset=utf-8
2x-app-id对接方标识由供应链金融平台提供
3x-sign签名base64(sm3withsm2(报文明文))

2.5 请求样例

POST https://{环境地址}/{接口地址} HTTP/1.1
Content-Type: application/json;charset=utf-8
x-app-id: {请求方标识}
x-sign: {签名}

base64密文

2.6 响应样例

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8

base64密文

3. 签名验签

3.1 密钥生成

对接方需生成一对sm2密钥对,并将公钥发送供应链金融平台。

3.1.1 Maven依赖
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.69</version>
</dependency>
3.1.2 静态代码
// 使用BouncyCastle密码库
private static final BouncyCastleProvider bc = new BouncyCastleProvider();
3.1.3 示例代码
// 使用BouncyCastle密码库
BouncyCastleProvider bc = new BouncyCastleProvider();
// 获取SM2椭圆曲线的参数
final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
// 获取一个椭圆曲线类型的密钥对生成器
final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", bc);
// 使用SM2参数初始化生成器
kpg.initialize(sm2Spec);
// 使用SM2的算法区域初始化密钥生成器
kpg.initialize(sm2Spec, new SecureRandom());
// 获取密钥对
KeyPair keyPair = kpg.generateKeyPair();

byte[] pkcs8PriKeyBytes = keyPair.getPrivate().getEncoded();
byte[] x509PubKeyBytes = keyPair.getPublic().getEncoded();

System.out.println("\nBASE64编码(默认采用):");
System.out.println("SM2 PKCS#8私钥:" + BaseEncoding.base64().encode(pkcs8PriKeyBytes));
System.out.println("SM2 X.509 公钥:" + BaseEncoding.base64().encode(x509PubKeyBytes));

3.2 供应链金融平台公钥

供应链金融平台通知对接方,对于通知报文验签。

3.2.1 测试环境
# SM2公钥 X.509:
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEa3QD4dsDhscjeLhENFl4MoSx1zscuMbKkxrrfogYLgJPBBS6tdYbFmAeYIt39ZEiKZZoZNpjb6op5R7++XUE/w==
3.2.2 生产环境
# SM2公钥 X.509:
后续提供

3.3 签名示例

对发送的JSON报文,即HTTP body需要进行全文SM2签名,再对签名结果进行Base64编码。

方法声明

public static String sign(String base64PriKey, String data);

方法示例

KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
byte[] pkcs8PriKeyBytes = BaseEncoding.base64().decode(base64PriKey);
// 根据采用的编码结构反序列化公私钥
PrivateKey privateKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(pkcs8PriKeyBytes));
// 生成SM2sign with sm3签名验签算法实例
Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), bc);
// 签名需要使用私钥,使用私钥初始化签名实例
signature.initSign(privateKey);
// 写入签名原文到算法中
signature.update(data.getBytes(StandardCharsets.UTF_8));
// 计算签名值
byte[] signBytes = signature.sign();
// Base64编码
return Base64.getEncoder().encodeToString(signBytes);

3.4 验签示例

对接收的JSON报文进行验签。

方法声明


public static boolean verify(String base64PubKey, String data, String base64Sign);

方法示例

KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
byte[] x509PubKeyBytes = BaseEncoding.base64().decode(base64PubKey);
// 根据采用的编码结构反序列化公私钥
PublicKey publicKey = keyFact.generatePublic(new X509EncodedKeySpec(x509PubKeyBytes));
// 生成SM2sign with sm3签名验签算法实例
Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), bc);
// 签名需要使用公钥,使用公钥初始化签名实例
signature.initVerify(publicKey);
// 写入待验签的签名原文到算法中
signature.update(data.getBytes(StandardCharsets.UTF_8));
// 验签
return signature.verify(Base64.getDecoder().decode(base64Sign));

4. 加解密

对于请求和响应报文,即HTTP body全文均使用SM4国密算法加密,对加密后的密文字节数组再进行Base64编码后进行传输。

4.1 对称密钥

4.1.1 测试环境
wXZyNYMeHmoEMwJKR4h7YA==

4.2 IV计算

private byte[] getIv(String appId) {
    return (appId + "0000000000000000").substring(0, 16).getBytes(StandardCharsets.UTF_8);
}

4.3 报文加密

方法声明

public static String encrypt(String base64Sm4Key, String appId, String plaintext);

方法示例

SecretKeySpec spec = new SecretKeySpec(Base64.getDecoder().decode(base64Sm4Key), "SM4");
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding", bc);
IvParameterSpec ivParameterSpec = new IvParameterSpec(getIv(appId));
cipher.init(Cipher.ENCRYPT_MODE, spec, ivParameterSpec);
byte[] ciphertextBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
String ciphertext = Base64.getEncoder().encodeToString(ciphertextBytes);

4.4 报文解密

方法声明

public static String decrypt(String base64Sm4Key, String appId, String base64Ciphertext);

方法示例

SecretKeySpec spec = new SecretKeySpec(Base64.getDecoder().decode(base64Sm4Key), "SM4");
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS7Padding", bc);
IvParameterSpec ivParameterSpec = new IvParameterSpec(getIv(appId));
cipher.init(Cipher.DECRYPT_MODE, spec, ivParameterSpec);
byte[] ciphertextBytes = Base64.getDecoder().decode(base64Ciphertext);
byte[] plaintextBytes = cipher.doFinal(ciphertextBytes);
String plaintext = new String(plaintextBytes, StandardCharsets.UTF_8);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你不懂、、、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值