{"id":1534,"date":"2022-06-01T12:21:57","date_gmt":"2022-06-01T04:21:57","guid":{"rendered":"http:\/\/diuut.com\/?p=1534"},"modified":"2022-07-21T17:28:57","modified_gmt":"2022-07-21T09:28:57","slug":"%e5%9b%bd%e5%af%86sm4utils%e5%b7%a5%e5%85%b7%e7%b1%bb%ef%bc%88java%ef%bc%89","status":"publish","type":"post","link":"https:\/\/diuut.com\/?p=1534","title":{"rendered":"SM4Utils\u5de5\u5177\u7c7b\uff08Java\uff09"},"content":{"rendered":"\n<blockquote class=\"wp-block-quote\"><p>\u9700\u6c42<\/p><cite>\u7b2c\u4e09\u65b9\u4ea4\u4e92\uff0c\u8981\u6c42\u56fd\u5bc6SM4\u8fdb\u884c\u52a0\u5bc6\uff0c\u6545\u5f15\u5165\u3002<\/cite><\/blockquote>\n\n\n\n<p>SM4\u4e3a\u5bf9\u79f0\u52a0\u5bc6\uff0c\u7528\u5c31\u5b8c\u4e8b\u3002<\/p>\n\n\n\n<p>\u5f15\u5165Maven\u4f9d\u8d56<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n       &lt;groupId&gt;org.bouncycastle&lt;\/groupId&gt;\n       &lt;artifactId&gt;bcprov-jdk15on&lt;\/artifactId&gt;\n       &lt;version&gt;1.57&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre><\/div>\n\n\n<p>SM4Utils\u5de5\u5177\u7c7b<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nimport org.bouncycastle.jce.provider.BouncyCastleProvider;\nimport org.bouncycastle.pqc.math.linearalgebra.ByteUtils;\nimport xyz.diuut.pojo.BaseSmEnum;\n\nimport javax.crypto.Cipher;\nimport javax.crypto.KeyGenerator;\nimport javax.crypto.spec.IvParameterSpec;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.security.AlgorithmParameters;\nimport java.security.Key;\nimport java.security.SecureRandom;\nimport java.security.Security;\nimport java.util.Arrays;\n\n\/**\n * @description:\n * @author: Diuut\n * @date: 2022\/5\/31 10:56\n *\/\npublic class SM4Utils {\n    static {\n        Security.addProvider(new BouncyCastleProvider());\n    }\n\n    private static final String ENCODING = BaseSmEnum.ENCODING.getMsg();\n\n    public static final String ALGORITHM_NAME = BaseSmEnum.ALGORITHM_NAME.getMsg();\n    \/\/ \u52a0\u5bc6\u7b97\u6cd5\/\u5206\u7ec4\u52a0\u5bc6\u6a21\u5f0f\/\u5206\u7ec4\u586b\u5145\u65b9\u5f0f\n    \/\/ PKCS5Padding-\u4ee58\u4e2a\u5b57\u8282\u4e3a\u4e00\u7ec4\u8fdb\u884c\u5206\u7ec4\u52a0\u5bc6\n    \/\/ \u5b9a\u4e49\u5206\u7ec4\u52a0\u5bc6\u6a21\u5f0f\u4f7f\u7528\uff1aPKCS5Padding\n\n    public static final String ALGORITHM_NAME_CBC_PADDING = BaseSmEnum.ALGORITHM_NAME_CBC_PADDING.getMsg();\n    public static final String ALGORITHM_NAME_ECB_PADDING = BaseSmEnum.ALGORITHM_NAME_ECB_PADDING.getMsg();\n    \/\/ 128-32\u4f4d16\u8fdb\u5236\uff1b256-64\u4f4d16\u8fdb\u5236\n    public static final int DEFAULT_KEY_SIZE = 128;\n\n    \/**\n     * \u81ea\u52a8\u751f\u6210\u5bc6\u94a5\n     *\n     * @return\n     * @explain\n     *\/\n    public static byte&#91;] generateKey() throws Exception {\n        return generateKey(DEFAULT_KEY_SIZE);\n    }\n\n\n    public static String generateKeyString() throws Exception {\n        return ByteUtils.toHexString(generateKey());\n    }\n\n    \/**\n     * @param keySize\n     * @return\n     * @throws Exception\n     * @explain\n     *\/\n    public static byte&#91;] generateKey(int keySize) throws Exception {\n        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);\n        kg.init(keySize, new SecureRandom());\n        return kg.generateKey().getEncoded();\n    }\n\n    \/**\n     * sm4\u52a0\u5bc6_CBC\n     *\n     * @param hexKey   16\u8fdb\u5236\u5bc6\u94a5\uff08\u5ffd\u7565\u5927\u5c0f\u5199\uff09\n     * @param paramStr \u5f85\u52a0\u5bc6\u5b57\u7b26\u4e32\n     * @return \u8fd4\u56de16\u8fdb\u5236\u7684\u52a0\u5bc6\u5b57\u7b26\u4e32\n     * @throws Exception\n     * @explain \u52a0\u5bc6\u6a21\u5f0f\uff1aCBC\n     *\/\n    public static String protectMsg_CBC(String hexKey, String paramStr) throws Exception {\n        String result = &quot;&quot;;\n        \/\/ 16\u8fdb\u5236\u5b57\u7b26\u4e32--&gt;byte&#91;]\n        byte&#91;] keyData = ByteUtils.fromHexString(hexKey);\n        \/\/ String--&gt;byte&#91;]\n        byte&#91;] srcData = paramStr.getBytes(ENCODING);\n        \/\/ \u52a0\u5bc6\u540e\u7684\u6570\u7ec4\n        byte&#91;] cipherArray = encrypt_Cbc_Padding(keyData, srcData);\n\n        \/\/ byte&#91;]--&gt;hexString\n        result = ByteUtils.toHexString(cipherArray);\n        return result;\n    }\n\n    \/**\n     * sm4\u52a0\u5bc6_ECB\n     *\n     * @param hexKey   16\u8fdb\u5236\u5bc6\u94a5\uff08\u5ffd\u7565\u5927\u5c0f\u5199\uff09\n     * @param paramStr \u5f85\u52a0\u5bc6\u5b57\u7b26\u4e32\n     * @return \u8fd4\u56de16\u8fdb\u5236\u7684\u52a0\u5bc6\u5b57\u7b26\u4e32\n     * @throws Exception\n     * @explain \u52a0\u5bc6\u6a21\u5f0f\uff1aCBC\n     *\/\n    public static String protectMsg_ECB(String hexKey, String paramStr) throws Exception {\n        String result = &quot;&quot;;\n        \/\/ 16\u8fdb\u5236\u5b57\u7b26\u4e32--&gt;byte&#91;]\n        byte&#91;] keyData = ByteUtils.fromHexString(hexKey);\n        \/\/ String--&gt;byte&#91;]\n        byte&#91;] srcData = paramStr.getBytes(ENCODING);\n        \/\/ \u52a0\u5bc6\u540e\u7684\u6570\u7ec4\n        byte&#91;] cipherArray = encrypt_Ecb_Padding(keyData, srcData);\n\n        \/\/ byte&#91;]--&gt;hexString\n        result = ByteUtils.toHexString(cipherArray);\n        return result;\n    }\n\n    \/**\n     * \u52a0\u5bc6\u6a21\u5f0f\u4e4bCBC\n     *\n     * @param key\n     * @param data\n     * @return\n     * @throws Exception\n     * @explain\n     *\/\n    public static byte&#91;] encrypt_Cbc_Padding(byte&#91;] key, byte&#91;] data) throws Exception {\n        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key);\n        return cipher.doFinal(data);\n    }\n\n    private static Cipher generateCbcCipher(String algorithmName, int mode, byte&#91;] key) throws Exception {\n        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);\n        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);\n        cipher.init(mode, sm4Key, generateIV());\n        return cipher;\n    }\n\n    \/**\n     * \u52a0\u5bc6\u6a21\u5f0f\u4e4bECB\n     *\n     * @param key\n     * @param data\n     * @return\n     * @throws Exception\n     * @explain\n     *\/\n    public static byte&#91;] encrypt_Ecb_Padding(byte&#91;] key, byte&#91;] data) throws Exception {\n        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);\n        return cipher.doFinal(data);\n    }\n\n    private static Cipher generateEcbCipher(String algorithmName, int mode, byte&#91;] key) throws Exception {\n        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);\n        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);\n        cipher.init(mode, sm4Key);\n        return cipher;\n    }\n\n    \/\/\u751f\u6210iv\n    public static AlgorithmParameters generateIV() throws Exception {\n        \/\/iv \u4e3a\u4e00\u4e2a 16 \u5b57\u8282\u7684\u6570\u7ec4\uff0c\u8fd9\u91cc\u91c7\u7528\u548c iOS \u7aef\u4e00\u6837\u7684\u6784\u9020\u65b9\u6cd5\uff0c\u6570\u636e\u5168\u4e3a0\n        byte&#91;] iv = new byte&#91;16];\n        Arrays.fill(iv, (byte) 0x00);\n        System.out.println(&quot;generateIV&quot;+ByteUtils.toHexString(iv));\n        AlgorithmParameters params = AlgorithmParameters.getInstance(ALGORITHM_NAME);\n        params.init(new IvParameterSpec(iv));\n        return params;\n    }\n\n    \/**\n     * sm4\u89e3\u5bc6_CBC\n     *\n     * @param hexKey 16\u8fdb\u5236\u5bc6\u94a5\n     * @param text   16\u8fdb\u5236\u7684\u52a0\u5bc6\u5b57\u7b26\u4e32\uff08\u5ffd\u7565\u5927\u5c0f\u5199\uff09\n     * @return \u89e3\u5bc6\u540e\u7684\u5b57\u7b26\u4e32\n     * @throws Exception\n     * @explain \u89e3\u5bc6\u6a21\u5f0f\uff1a\u91c7\u7528CBC\n     *\/\n    public static String uncoverMsg_CBC(String hexKey, String text) throws Exception {\n        \/\/ \u7528\u4e8e\u63a5\u6536\u89e3\u5bc6\u540e\u7684\u5b57\u7b26\u4e32\n        String result = &quot;&quot;;\n        \/\/ hexString--&gt;byte&#91;]\n        byte&#91;] keyData = ByteUtils.fromHexString(hexKey);\n        \/\/ hexString--&gt;byte&#91;]\n        byte&#91;] resultData = ByteUtils.fromHexString(text);\n        \/\/ \u89e3\u5bc6\n        byte&#91;] srcData = decrypt_Cbc_Padding(keyData, resultData);\n        \/\/ byte&#91;]--&gt;String\n        result = new String(srcData, ENCODING);\n        return result;\n    }\n\n    \/**\n     * sm4\u89e3\u5bc6_ECB\n     *\n     * @param hexKey 16\u8fdb\u5236\u5bc6\u94a5\n     * @param text   16\u8fdb\u5236\u7684\u52a0\u5bc6\u5b57\u7b26\u4e32\uff08\u5ffd\u7565\u5927\u5c0f\u5199\uff09\n     * @return \u89e3\u5bc6\u540e\u7684\u5b57\u7b26\u4e32\n     * @throws Exception\n     * @explain \u89e3\u5bc6\u6a21\u5f0f\uff1a\u91c7\u7528ECB\n     *\/\n    public static String uncoverMsg_ECB(String hexKey, String text) throws Exception {\n        \/\/ \u7528\u4e8e\u63a5\u6536\u89e3\u5bc6\u540e\u7684\u5b57\u7b26\u4e32\n        String result = &quot;&quot;;\n        \/\/ hexString--&gt;byte&#91;]\n        byte&#91;] keyData = ByteUtils.fromHexString(hexKey);\n        \/\/ hexString--&gt;byte&#91;]\n        byte&#91;] resultData = ByteUtils.fromHexString(text);\n        \/\/ \u89e3\u5bc6\n        byte&#91;] srcData = decrypt_Ecb_Padding(keyData, resultData);\n        \/\/ byte&#91;]--&gt;String\n        result = new String(srcData, ENCODING);\n        return result;\n    }\n\n    \/**\n     * \u89e3\u5bc6\n     *\n     * @param key\n     * @param cipherText\n     * @return\n     * @throws Exception\n     * @explain\n     *\/\n    public static byte&#91;] decrypt_Cbc_Padding(byte&#91;] key, byte&#91;] cipherText) throws Exception {\n        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key);\n        return cipher.doFinal(cipherText);\n    }\n\n    \/**\n     * \u89e3\u5bc6\n     *\n     * @param key\n     * @param cipherText\n     * @return\n     * @throws Exception\n     * @explain\n     *\/\n    public static byte&#91;] decrypt_Ecb_Padding(byte&#91;] key, byte&#91;] cipherText) throws Exception {\n        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);\n        return cipher.doFinal(cipherText);\n    }\n\n\n\n    public static void main(String&#91;] args) {\n        try {\n            String json = &quot;openid=ooj0E5I8XR4AC5RnafNaZTwRhQn6&quot;;\n            System.out.println(&quot;\u52a0\u5bc6\u524d\u6e90\u6570\u636e\u2014\u2014\u2014\u2014&quot; + json);\n            \/\/ \u751f\u621032\u4f4d16\u8fdb\u5236\u5bc6\u94a5\n            String key=&quot;0qig5udx3ntl8wci&quot;;\n\/\/             key = SM4Utils.generateKeyString();\n            key=StringToHex.stringToHexString(key);\n\/\/            System.out.println(key + &quot;-----\u751f\u6210key&quot;);\n            String cipher = SM4Utils.protectMsg_ECB(key,json);\n            System.out.println(&quot;\u52a0\u5bc6\u4e32---&quot; + cipher);\n            json = SM4Utils.uncoverMsg_ECB(key, cipher);\n            System.out.println(&quot;\u89e3\u5bc6\u540e\u6570\u636e---&quot; + json);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<p>SM4Utils\u5de5\u5177\u7c7b\u4f7f\u7528\u679a\u4e3e<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage xyz.diuut.pojo;\n\npublic enum BaseSmEnum {\n\n    \/**\n     *\n     *\/\n    ENCODING(&quot;UTF-8&quot;),\n    ALGORITHM_NAME(&quot;SM4&quot;),\n    ALGORITHM_NAME_CBC_PADDING(&quot;SM4\/CBC\/PKCS7Padding&quot;),\n    ALGORITHM_NAME_ECB_PADDING(&quot;SM4\/ECB\/PKCS5Padding&quot;),\n\n    ;\n\n\n    private String msg;\n\n    BaseSmEnum(String msg) {\n        this.msg = msg;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n\n    @Override\n    public String toString() {\n        return &quot;BaseEnum{&quot; +\n                &quot;msg='&quot; + msg + '\\'' +\n                '}';\n    }\n}\n<\/pre><\/div>\n\n\n<p>StringToHex\u5de5\u5177\u7c7b\uff08\u90e8\u5206\u5bf9\u63a5\u63d0\u4f9b\u7684\u79d8\u94a5\u9700\u8f6c\u6210hex\u624d\u53ef\u4ee5\u4f7f\u7528\uff09<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage xyz.diuut;\n\n\/**\n * @Author Diuut\n * @Date 2022\/5\/31  11:09\n *\/\npublic class StringToHex {\n\n    \/**\n     * \u5b57\u7b26\u4e32\u8f6c\u6362\u4e3a16\u8fdb\u5236\u5b57\u7b26\u4e32\n     *\n     * @param s\n     * @return\n     *\/\n    public static String stringToHexString(String s) {\n        String str = &quot;&quot;;\n        for (int i = 0; i &lt; s.length(); i++) {\n            int ch = s.charAt(i);\n            String s4 = Integer.toHexString(ch);\n            str = str + s4;\n        }\n        return str;\n    }\n\n    \/**\n     * 16\u8fdb\u5236\u5b57\u7b26\u4e32\u8f6c\u6362\u4e3a\u5b57\u7b26\u4e32\n     *\n     * @param s\n     * @return\n     *\/\n    public static String hexStringToString(String s) {\n        if (s == null || s.equals(&quot;&quot;)) {\n            return null;\n        }\n        s = s.replace(&quot; &quot;, &quot;&quot;);\n        byte&#91;] baKeyword = new byte&#91;s.length() \/ 2];\n        for (int i = 0; i &lt; baKeyword.length; i++) {\n            try {\n                baKeyword&#91;i] = (byte) (0xff &amp; Integer.parseInt(\n                        s.substring(i * 2, i * 2 + 2), 16));\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n        try {\n            s = new String(baKeyword, &quot;gbk&quot;);\n            new String();\n        } catch (Exception e1) {\n            e1.printStackTrace();\n        }\n        return s;\n    }\n\n    \/**\n     * 16\u8fdb\u5236\u8868\u793a\u7684\u5b57\u7b26\u4e32\u8f6c\u6362\u4e3a\u5b57\u8282\u6570\u7ec4\n     *\n     * @param s 16\u8fdb\u5236\u8868\u793a\u7684\u5b57\u7b26\u4e32\n     * @return byte&#91;] \u5b57\u8282\u6570\u7ec4\n     *\/\n    public static byte&#91;] hexStringToByteArray(String s) {\n        int len = s.length();\n        byte&#91;] b = new byte&#91;len \/ 2];\n        for (int i = 0; i &lt; len; i += 2) {\n            \/\/ \u4e24\u4f4d\u4e00\u7ec4\uff0c\u8868\u793a\u4e00\u4e2a\u5b57\u8282,\u628a\u8fd9\u6837\u8868\u793a\u768416\u8fdb\u5236\u5b57\u7b26\u4e32\uff0c\u8fd8\u539f\u6210\u4e00\u4e2a\u5b57\u8282\n            b&#91;i \/ 2] = (byte) ((Character.digit(s.charAt(i), 16) &lt;&lt; 4) + Character\n                    .digit(s.charAt(i + 1), 16));\n        }\n        return b;\n    }\n\n    \/**\n     * byte\u6570\u7ec4\u8f6c16\u8fdb\u5236\u5b57\u7b26\u4e32\n     * @param bArray\n     * @return\n     *\/\n    public static final String bytesToHexString(byte&#91;] bArray) {\n        StringBuffer sb = new StringBuffer(bArray.length);\n        String sTemp;\n        for (int i = 0; i &lt; bArray.length; i++) {\n            sTemp = Integer.toHexString(0xFF &amp; bArray&#91;i]);\n            if (sTemp.length() &lt; 2) {\n                sb.append(0);\n            }\n            sb.append(sTemp.toUpperCase());\n        }\n        return sb.toString();\n    }\n}\n<\/pre><\/div>\n\n\n<p>\u4e0a\u9762\u7684\u5185\u5bb9\u90fd\u5f15\u5165\u540e\u5de5\u5177\u7c7b\u4e2d\u6709\u6d4b\u8bd5\u65b9\u6cd5\u53ef\u4ee5\u8bd5\u4e0b\u3002\u6682\u65f6\u53ea\u7528\u5230\u4e86\u4e0a\u9762\u7684\u4e1c\u897f\uff0c\u540e\u9762\u5982\u679c\u6709\u5176\u4ed6\u7528\u5230\u7684\u518d\u8865\u5145\u3002\u4ee5\u4e0a\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u9700\u6c42 \u7b2c\u4e09\u65b9\u4ea4\u4e92\uff0c\u8981\u6c42\u56fd\u5bc6SM4\u8fdb\u884c\u52a0\u5bc6\uff0c\u6545\u5f15\u5165\u3002 SM4\u4e3a\u5bf9\u79f0\u52a0\u5bc6\uff0c\u7528\u5c31\u5b8c\u4e8b\u3002 \u5f15\u5165Maven\u4f9d\u8d56 SM4U<span class=\"more-button\"><a href=\"https:\/\/diuut.com\/?p=1534\" class=\"more-link\">view all . . .<span class=\"screen-reader-text\">SM4Utils\u5de5\u5177\u7c7b\uff08Java\uff09<\/span><\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":657,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[52,53],"_links":{"self":[{"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/posts\/1534"}],"collection":[{"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diuut.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1534"}],"version-history":[{"count":3,"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/posts\/1534\/revisions"}],"predecessor-version":[{"id":1544,"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/posts\/1534\/revisions\/1544"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/diuut.com\/index.php?rest_route=\/wp\/v2\/media\/657"}],"wp:attachment":[{"href":"https:\/\/diuut.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diuut.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diuut.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}