麒麟云服开放平台

麒麟云服开放平台接口


数据签名

<h3>申请公私钥</h3> <p>说明:一共两对公私钥,平台公私钥(由平台生成)、企业公私钥(由企业生成)。 用途:企业私钥用于企业发送请求时参数加签,企业公钥用于平台接受企业的请求后的参数验签;平台私钥用于平台回调企业时的参数加密,平台公钥用于企业接受到平台信息后的参数验签。<br /> 公私钥生成步骤:<br /> 1、通过客服人员给到的账号登录企业端,<a href="https://b.kylin-task.com">https://b.kylin-task.com</a><br /> 2、点击企业管理-开放平台,然后点击右上角的新增按钮 <img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=1249a605d22f4f6a008978fc2fbf6b8b&amp;amp;file=file.png" alt="" /> 3、可以使用平台提供的密钥生成工具来生成一对公私钥(平台不会保存企业私钥,请企业妥善保管),也可以企业自己生成后上传企业公钥,然后点击保存即可 <img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=472120ba69478778fb1b464023adccc0&amp;amp;file=file.png" alt="" /></p> <h3>签名</h3> <p>企业发送请求时使用企业私钥进行加签,平台接收到请求后使用企业上传的企业公钥进行验签。</p> <ol> <li>不包括字节类型参数,如文件、字节流,剔除 sign 字段,剔除值为空的参数;</li> <li>按照第一个字符的键值 ASCII 码递增排序(字母升序排序),如果遇到相同字符则按照第二个字符的键值 ASCII 码递增排序,以此类推;</li> <li>将排序后的参数与其对应值,组合成 参数=参数值 的格式,并且把这些参数用 &amp; 字符连接起来,此时生成的字符串为待签名字符串。</li> </ol> <p>例:bizContent={&quot;outBizNo&quot;:&quot;2023100080808&quot;,&quot;accountType&quot;:&quot;ALI_ACCOUNT&quot;,&quot;name&quot;:&quot;张三&quot;,&quot;accountNumber&quot;:&quot;testaccount@alipay.com&quot;,&quot;phone&quot;:&quot;13100000000&quot;,&quot;idCardNumber&quot;:&quot;33010120231001111&quot;,&quot;transAmount&quot;:10.01}&amp;charset=utf-8&amp;companyId=1&amp;signType=RSA2&amp;timestamp=2023-10-01 08:08:08</p> <h3>验签</h3> <p>平台回调时使用平台私钥进行加签,企业接收到回调请求后使用平台公钥进行验签。</p> <p>加签、验签代码示例</p> <pre><code>import javax.crypto.Cipher; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.*; public class RSAUtil { //签名算法名称 private static final String RSA_KEY_ALGORITHM = &amp;quot;RSA&amp;quot;; //标准签名算法名称 private static final String RSA_SIGNATURE_ALGORITHM = &amp;quot;SHA1withRSA&amp;quot;; private static final String RSA2_SIGNATURE_ALGORITHM = &amp;quot;SHA256withRSA&amp;quot;; /** * RSA签名(私钥) * @param data 待签名数据 * @param privateKeyStr 私钥 * @param signType RSA或RSA2 * @param charset 编码格式 * @return 签名 * @throws Exception */ public static String sign(String data, String privateKeyStr, String signType, String charset) throws Exception { //创建PKCS8编码密钥规范 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(decode(privateKeyStr)); //返回转换指定算法的KeyFactory对象 KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); //根据PKCS8编码密钥规范产生私钥对象 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); //标准签名算法名称(RSA还是RSA2) String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM; //用指定算法产生签名对象Signature Signature signature = Signature.getInstance(algorithm); //用私钥初始化签名对象Signature signature.initSign(privateKey); //将待签名的数据传送给签名对象(须在初始化之后) signature.update(data.getBytes(charset)); //返回签名结果字节数组 byte[] sign = signature.sign(); //返回Base64编码后的字符串 return encode(sign); } /** * RSA校验数字签名(公钥) * @param data 待校验数据 * @param sign 数字签名 * @param publicKeyStr 公钥 * @param signType RSA或RSA2 * @param charset 编码格式 * @return boolean 校验成功返回true,失败返回false */ public static boolean verify(String data, String sign, String publicKeyStr, String signType, String charset) throws Exception { //返回转换指定算法的KeyFactory对象 KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM); //创建X509编码密钥规范 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(decode(publicKeyStr)); //根据X509编码密钥规范产生公钥对象 PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); //标准签名算法名称(RSA还是RSA2) String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM; //用指定算法产生签名对象Signature Signature signature = Signature.getInstance(algorithm); //用公钥初始化签名对象,用于验证签名 signature.initVerify(publicKey); //更新签名内容 signature.update(data.getBytes(charset)); //得到验证结果 return signature.verify(decode(sign)); } /** * 编码 * @param bytes byte字节数组 * @return encode Base64编码 */ private static String encode(byte[] bytes){ return Base64.getEncoder().encodeToString(bytes); } /** * 解码 * @param str 编码后的byte * @return decode Base64解码 */ private static byte[] decode(String str){ return Base64.getDecoder().decode(str); } /*** * 获取排序后的待签名字符串 * @param sortedParams * @return */ public static String getSignContent(Map&amp;lt;String, String&amp;gt; sortedParams) { StringBuilder content = new StringBuilder(); List&amp;lt;String&amp;gt; keys = new ArrayList&amp;lt;String&amp;gt;(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (int i = 0; i &amp;lt; keys.size(); i++) { String key = keys.get(i); String value = sortedParams.get(key); if (areNotEmpty(key, value)) { content.append(index == 0 ? &amp;quot;&amp;quot; : &amp;quot;&amp;amp;&amp;quot;).append(key).append(&amp;quot;=&amp;quot;).append(value); index++; } } return content.toString(); } /** * 检查指定的字符串列表是否不为空。 */ public static boolean areNotEmpty(String... values) { boolean result = true; if (values == null || values.length == 0) { result = false; } else { for (String value : values) { result &amp;amp;= !isEmpty(value); } } return result; } /** * 检查指定的字符串是否为空。 * &amp;lt;ul&amp;gt; * &amp;lt;li&amp;gt;SysUtils.isEmpty(null) = true&amp;lt;/li&amp;gt; * &amp;lt;li&amp;gt;SysUtils.isEmpty(&amp;quot;&amp;quot;) = true&amp;lt;/li&amp;gt; * &amp;lt;li&amp;gt;SysUtils.isEmpty(&amp;quot; &amp;quot;) = true&amp;lt;/li&amp;gt; * &amp;lt;li&amp;gt;SysUtils.isEmpty(&amp;quot;abc&amp;quot;) = false&amp;lt;/li&amp;gt; * &amp;lt;/ul&amp;gt; * * @param value 待检查的字符串 * @return true/false */ public static boolean isEmpty(String value) { int strLen; if (value == null || (strLen = value.length()) == 0) { return true; } for (int i = 0; i &amp;lt; strLen; i++) { if ((Character.isWhitespace(value.charAt(i)) == false)) { return false; } } return true; } }</code></pre>

页面列表

ITEM_HTML