{"id":1504,"date":"2025-09-23T14:30:21","date_gmt":"2025-09-23T06:30:21","guid":{"rendered":"https:\/\/open-doc.jkos.com\/?post_type=docs&#038;p=1504"},"modified":"2025-10-02T17:52:40","modified_gmt":"2025-10-02T09:52:40","slug":"%e5%8a%a0%e7%b0%bd%e5%8a%a0%e5%af%86%e8%aa%aa%e6%98%8e-signature-generation-rule","status":"publish","type":"docs","link":"https:\/\/open-doc.jkos.com\/?docs=%e8%a1%97%e5%8f%a3%e5%b9%a3%e7%99%bc%e6%94%be-issue-jkoscoin\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/%e5%8a%a0%e7%b0%bd%e5%8a%a0%e5%af%86%e8%aa%aa%e6%98%8e-signature-generation-rule","title":{"rendered":"\u52a0\u7c3d\u52a0\u5bc6\u8aaa\u660e (Signature Generation Rule)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">\u898f\u5247\u8aaa\u660e (Description)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u7c3d\u7ae0\u898f\u5247<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Request Payload \u7de8\u78bc<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u5c07\u5b57\u4e32\u5f62\u5f0f\u7684 <code>request payload<\/code> \u4ee5 <strong>UTF-8<\/strong> \u7de8\u78bc\uff0c\u751f\u6210 <strong><code>input byte<\/code>\u3002<\/strong><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Secret Key \u7de8\u78bc<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u5c07\u8857\u53e3\u63d0\u4f9b\u7684 <code>Secret Key<\/code> \u4ee5 <strong>UTF-8<\/strong> \u7de8\u78bc\uff0c\u751f\u6210 <strong><code>secret key byte<\/code><\/strong>\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>HMAC-SHA256 \u904b\u7b97<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u4f7f\u7528 <strong>HMAC-SHA256<\/strong> \u6f14\u7b97\u6cd5\uff0c\u5c07 <strong><code>input byte<\/code><\/strong> \u8207 <strong><code>secret key byte<\/code><\/strong> \u8a08\u7b97\u96dc\u6e4a\u503c\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Digest \u8f49\u63db<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u5c07\u96dc\u6e4a\u7d50\u679c\u8f49\u63db\u70ba <strong>\u5341\u516d\u9032\u4f4d\u5b57\u4e32 (hexadecimal string)<\/strong>\uff0c\u4f5c\u70ba <strong><code>digest<\/code><\/strong>\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Signature Generation Rule<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Request Payload Encoding<\/strong>\n<ul class=\"wp-block-list\">\n<li>Encode the request payload string into bytes using <strong>UTF-8<\/strong>, referred to as <strong><code>input byte<\/code><\/strong>.\n<ul class=\"wp-block-list\">\n<li>Example: Request payload: <code>{\"a\":1, \"b\":\"13\"}<\/code><\/li>\n\n\n\n<li>UTF-8 bytes (hex representation): <code>7b2261223a312c202262223a223133227d<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Secret Key Encoding<\/strong>\n<ul class=\"wp-block-list\">\n<li>Encode the provided <strong>Secret Key<\/strong> into bytes using <strong>UTF-8<\/strong>, referred to as <strong><code>secret key byte<\/code><\/strong>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>HMAC-SHA256 Hashing<\/strong>\n<ul class=\"wp-block-list\">\n<li>Apply <strong>HMAC-SHA256<\/strong> with <strong><code>secret key byte<\/code><\/strong> as the key and <strong><code>input byte<\/code><\/strong> as the message.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Digest Conversion<\/strong>\n<ul class=\"wp-block-list\">\n<li>Convert the resulting hash into a <strong>hexadecimal string<\/strong>, referred to as <strong><code>digest<\/code><\/strong>.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">\u7bc4\u4f8b (Example)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u767c\u653e\u8857\u53e3\u5e63 API (Method=Post)<\/h3>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e00\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u5b57\u4e32\u7684 request payload\u4ee5 UTF-8 \u7de8\u78bc\uff0crequest body \u7bc4\u4f8b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">{\"exchangeId\":\"testunique1758786827\",\"amount\":10,\"jkosId\": \"user123\",\"clientId\": \"310886000\"}<\/code><\/pre>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e8c\uff1a<\/strong><\/p>\n\n\n\n<p>\u9808\u8207\u8857\u53e3\u652f\u4ed8\u7533\u8acb\u5e73\u53f0 secret key\uff0c\u91d1\u9470\u7bc4\u4f8b\u70ba secret key = <code>r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ<\/code>\uff0c\u4e26\u5c07 secret key \u4ee5UTF-8 \u7de8\u78bc<\/p>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e09\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u6b65\u9a5f\u4e00\u7522\u751f\u7684\u5b57\u7bc0\u900f\u904e HMAC-SHA256 \u6f14\u7b97\u6cd5\uff0c\u4ee5\u6b65\u9a5f\u4e8c\u7684\u5b57\u7bc0\u4f5c\u70ba\u79d8\u5bc6\u9470\u5319\u9032\u884c\u52a0\u7c3d\uff0c\u5373\u7522\u751f hexdigest \u4f5c\u70ba digest\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">{\"exchangeId\":\"testunique1758786827\",\"amount\":10,\"jkosId\":\"user123\",\"clientId\":\"310886000\"}<br>\/*<br>Secret key='r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ'<br>*\/<br>DIGEST: a001fe1b11464109037473e9a0a53f8887d352bdd7dbd5ea699951e7dbeff31a<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">\u67e5\u8a62 API (Method=Get) <\/h3>\n\n\n\n<p><code>\u76ee\u524d\u5c1a\u672a\u63d0\u4f9b\uff0c\u4f46\u5efa\u8b70\u5148\u5c07 GET parameters \u8655\u7406\u597d\u672a\u4f86\u65b9\u4fbf\u4ecb\u63a5<\/code><\/p>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e00\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u5b57\u4e32\u7684 request payload\u4ee5 UTF-8 \u7de8\u78bc\uff0crequest parameter \u7bc4\u4f8b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">clientId=310886000,exchangeId=testunique1758786827<\/code><\/pre>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e8c\uff1a<\/strong><\/p>\n\n\n\n<p>\u9808\u8207\u8857\u53e3\u652f\u4ed8\u7533\u8acb\u5e73\u53f0 secret key\uff0c\u91d1\u9470\u7bc4\u4f8b\u70ba secret key = <code>r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ<\/code>\uff0c\u4e26\u5c07 secret key \u4ee5 UTF-8 \u7de8\u78bc<\/p>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e09\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u6b65\u9a5f\u4e00\u7522\u751f\u7684\u5b57\u7bc0\u900f\u904e HMAC-SHA256 \u6f14\u7b97\u6cd5\uff0c\u4ee5\u6b65\u9a5f\u4e8c\u7684\u5b57\u7bc0\u4f5c\u70ba\u79d8\u5bc6\u9470\u5319\u9032\u884c\u52a0\u7c3d\uff0c\u5373\u7522\u751f hexdigest \u4f5c\u70ba digest\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">DIGEST: 5b2202771834fd7d0cfd30c58132804ce1d5c2bc04cbae86c6a58e4b93d9ab95<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u7c3d\u7ae0\u9a57\u8b49\u5de5\u5177<\/h2>\n\n\n\n<script type=\"text\/javascript\" src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/crypto-js\/3.1.2\/rollups\/hmac-sha256.js\"><\/script>\n\n<script>\n  function generateSignature() {\n    let requestType = document.getElementById(\"requestType\").value;\n    let requestData = document.getElementById(\"requestData\").value.trim();\n    let secretKey = document.getElementById(\"secretKey\").value.trim();\n    let errorDiv = document.getElementById(\"error\");\n    let output = document.getElementById(\"output\");\n    \n    errorDiv.innerHTML = \"\";\n    output.value = \"\";\n    \n    if (!secretKey) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165 Secret Key\";\n      return;\n    }\n    \n    if (!requestData) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165\u8acb\u6c42\u5167\u5bb9\";\n      return;\n    }\n    \n    try {\n      let inputData;\n      \n      if (requestType === \"GET\") {\n        \/\/ GET \u8acb\u6c42: \u76f4\u63a5\u4f7f\u7528 Query String\n        inputData = requestData;\n      } else {\n        \/\/ \u5176\u4ed6\u8acb\u6c42 (POST \/ PUT \/ PATCH): JSON \u683c\u5f0f\u5316\u8655\u7406\n        inputData = requestData;\n      }\n      \n      \/\/ \u7522\u751f HMAC-SHA256 \u7c3d\u540d\n      let signature = CryptoJS.HmacSHA256(inputData, secretKey);\n      \n      \/\/ \u8f49\u63db\u70ba 16 \u9032\u4f4d\u683c\u5f0f (\u5c0f\u5beb)\n      let digest = signature.toString(CryptoJS.enc.Hex);\n      \n      output.value = digest;\n    } catch (e) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165\u6b63\u78ba\u7684\u8acb\u6c42\u5167\u5bb9 (GET Query String \u6216 JSON Body)\";\n    }\n  }\n<\/script>\n\n<div class=\"w-75\">\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u8acb\u6c42\u985e\u578b\uff1a<\/div>\n    <select id=\"requestType\" class=\"form-control\">\n      <option value=\"GET\">GET<\/option>\n      <option value=\"POST\">POST \/ PUT \/ PATCH<\/option>\n    <\/select>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u8acb\u6c42\u5167\u5bb9\uff1a(input byte)<\/div>\n    <textarea id=\"requestData\" class=\"form-control\" rows=\"5\" placeholder='GET: clientId=310886000&#038;exchangeId=testunique1758786827\nPOST: {\"exchangeId\":\"testunique1758786827\",\"amount\":10,\"jkosId\":\"user123\",\"clientId\":\"310886000\"}'><\/textarea>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">Secret Key\uff1a<\/div>\n    <input id=\"secretKey\" type=\"text\" class=\"form-control\" placeholder=\"\u8f38\u5165 Secret Key\">\n  <\/div>\n\n  <button type=\"button\" class=\"btn btn-info mb-2 p-2\" onclick=\"generateSignature()\">\n    \u8a08\u7b97\u7c3d\u540d\n  <\/button>\n\n  <div class=\"mb-3\">\n    <div id=\"error\" style=\"color: red;\"><\/div>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u7c3d\u540d\u7d50\u679c\uff1a<\/div>\n    <textarea id=\"output\" class=\"form-control\" rows=\"3\" readonly><\/textarea>\n  <\/div>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">sample code<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">PHP<\/h4>\n\n\n\n<p>\u53c3\u8003\u5de5\u5177\uff1a<a href=\"https:\/\/www.tehplayground.com\/uEl6FSUO5YaJHHVH\">https:\/\/www.tehplayground.com\/uEl6FSUO5YaJHHVH<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">$sig = hash_hmac('sha256', $string, $secret)\n\nsecretkey\uff1a\nr0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ\n\ninput:\nplatform_order_ids=test123,demo-order-001\n\nresult:\n7778b95890af17c5b41e8cef957f4769e7bfecc79e9f9ee555923293ebd8e880<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Python<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import hashlib<br>import hmac<br>import logging<br><br>class SignatureLogic:<br>    @staticmethod<br>    def generate_digest(secret_key, content):<br>        secret_key = secret_key.encode() if isinstance(secret_key, str) else secret_key<br>        content = content.encode() if isinstance(content, str) else content<br>    <br>        result = hmac.new(<br>            secret_key,<br>            msg=content,<br>            digestmod=hashlib.sha256<br>        ).hexdigest()<br>        return result<br>        <br><br>json_str = '{\"exchangeId\":\"testunique1758786827\",\"amount\":10,\"jkosId\": \"user123\",\"clientId\":\"310886000\"}'<br><br># Key<br>secret_key = 'input-your-key'<br><br># \u751f\u6210\u7c3d\u540d<br>signature = SignatureLogic.generate_digest(secret_key, json_str)<br>print(signature)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">JAVA<\/h4>\n\n\n\n<p>\u53c3\u8003\u5de5\u5177\uff1a<a href=\"https:\/\/reurl.cc\/M0YKXk\">https:\/\/reurl.cc\/M0YKXk<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import javax.crypto.Mac;<br>import javax.crypto.spec.SecretKeySpec;<br><br>public static String encodeHmacSHA256(String secretKey, String input) {<br>   SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), \"HmacSHA256\");<br>   Mac mac = Mac.getInstance(\"HmacSHA256\");   <br>   mac.init(secret_key);<br>   byte[] bytes = mac.doFinal(input.getBytes());<br>   return byteArrayToHexString(bytes);<br>}<br><br>private static String byteArrayToHexString(byte[] b) {<br>   StringBuilder hs = new StringBuilder();<br>   String stmp;<br>   for (int n = 0; b != null &amp;&amp; n &lt; b.length; n++) {<br>   stmp = Integer.toHexString(b[n] &amp; 0XFF);<br>      if (stmp.length() == 1) {<br>         hs.append('0');<br>      }<br>      hs.append(stmp);<br>   }<br>   return hs.toString().toLowerCase();<br>}<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"featured_media":0,"parent":1500,"menu_order":1,"comment_status":"open","ping_status":"closed","template":"","doc_tag":[],"class_list":["post-1504","docs","type-docs","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1504","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/types\/docs"}],"replies":[{"embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1504"}],"version-history":[{"count":13,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1504\/revisions"}],"predecessor-version":[{"id":1594,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1504\/revisions\/1594"}],"up":[{"embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1500"}],"prev":[{"title":"API \u5354\u8b70\u898f\u5247 (API Protocol Rules)","link":"https:\/\/open-doc.jkos.com\/?docs=%e8%a1%97%e5%8f%a3%e5%b9%a3%e7%99%bc%e6%94%be-issue-jkoscoin\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/api-%e5%8d%94%e8%ad%b0%e8%a6%8f%e5%89%87","href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1507"}],"wp:attachment":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1504"}],"wp:term":[{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_tag&post=1504"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}