{"id":1303,"date":"2023-03-18T10:34:50","date_gmt":"2023-03-18T02:34:50","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1303"},"modified":"2023-04-29T09:16:39","modified_gmt":"2023-04-29T01:16:39","slug":"nodejs-and-java-use-rsa-for-signature-and-verification-in-two-ways","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/18\/nodejs-and-java-use-rsa-for-signature-and-verification-in-two-ways\/","title":{"rendered":"Nodejs\u548cJava\u901a\u8fc7RSA\u8fdb\u884c\u7b7e\u540d\u548c\u9a8c\u7b7e\u7684\u4e24\u79cd\u65b9\u5f0f"},"content":{"rendered":"<h2>\u524d\u8a00<\/h2>\n<ol>\n<li>\u901a\u5e38\u6211\u4eec\u4f7f\u7528\u7684\u662f\u6807\u51c6\u7684PEM\u8bc1\u4e66\uff0cPEM\u8bc1\u4e66\u662fOpenSSL\u7684\u6807\u51c6\u683c\u5f0f\u3002<\/li>\n<li>PEM\u683c\u5f0f\u4fe1\u606f\u6700\u5927\u7684\u7279\u70b9\u662f\u4f1a\u5e26\u5934\u4fe1\u606f\u548c\u5c3e\u4fe1\u606f\u3002\u516c\u94a5\uff1a<code>-----BEGIN PUBLIC KEY-----<\/code>\u3001<code>-----END PUBLIC KEY-----<\/code>\u3002\u79c1\u94a5\uff1a<code>-----BEGIN PRIVATE KEY-----<\/code>\u3001<code>-----END PRIVATE KEY-----<\/code><\/li>\n<li>\u7b80\u8ff0\u4e0b\u5229\u7528openssl\u751f\u6210pem\u7684\u8fc7\u7a0b\uff1a<\/li>\n<\/ol>\n<p><!-- more --><\/p>\n<ul>\n<li>\u751f\u6210RSA\u79c1\u94a5 \u901a\u5e38\u5927\u4e8e512\uff0c\u9009\u62e91024\u6216\u80052048<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">openssl genrsa -out rsa_private_key.pem 1024<\/code><\/pre>\n<ul>\n<li>\u9700\u8981\u8f6c\u6362\u6210RSA\u79c1\u94a5\u8f6c\u6362\u6210PKCS8\u683c\u5f0f<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem-outform PEM -nocrypt<\/code><\/pre>\n<ul>\n<li>\u751f\u6210RSA\u516c\u94a5<\/li>\n<\/ul>\n<pre><code class=\"language-bash\">openssl rsa -in rsa_private_key.pem-pubout -out rsa_public_key.pem<\/code><\/pre>\n<h2>\u901a\u8fc7PEM\u8fdb\u884c\u52a0\u5bc6\u3001\u89e3\u5bc6\u3001\u7b7e\u540d\u3001\u9a8c\u7b7e<\/h2>\n<p>Java\u901a\u8fc7RSA\u5bf9\u6570\u636e\u8fdb\u884c\u52a0\u5bc6\u3001\u89e3\u5bc6\u3001\u7b7e\u540d\u3001\u9a8c\u7b7e\u7684\u6d41\u7a0b\u3002<\/p>\n<h3>\u79c1\u94a5\u7b7e\u540d<\/h3>\n<p>a\uff09\u83b7\u53d6\u79c1\u94a5<\/p>\n<pre><code class=\"language-java\">\/\/\u83b7\u53d6KeyFactory\uff0c\u6307\u5b9aRSA\u7b97\u6cd5\nKeyFactorykeyFactory = KeyFactory.getInstance(&quot;RSA&quot;);\n\n\/\/\u5c06BASE64\u7f16\u7801\u7684\u79c1\u94a5\u5b57\u7b26\u4e32\u8fdb\u884c\u89e3\u7801\nBASE64Decoderdecoder = newBASE64Decoder();\n\nbyte[] encodeByte = decoder.decodeBuffer(priKey);\n\n\/\/\u5c06BASE64\u89e3\u7801\u540e\u7684\u5b57\u8282\u6570\u7ec4\uff0c\u6784\u9020\u6210PKCS8EncodedKeySpec\u5bf9\u8c61\uff0c\u751f\u6210\u79c1\u94a5\u5bf9\u8c61\nPrivateKeyprivatekey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodeByte));<\/code><\/pre>\n<p>b\uff09\u4f7f\u7528\u79c1\u94a5\uff0c\u5bf9\u6570\u636e\u8fdb\u884c\u7b7e\u540d<\/p>\n<pre><code class=\"language-java\">\/\/\u83b7\u53d6Signature\u5b9e\u4f8b\uff0c\u6307\u5b9a\u7b7e\u540d\u7b97\u6cd5\uff08\u672c\u4f8b\u4f7f\u7528SHA1WithRSA\uff09\nSignaturesignature = Signature.getInstance(&quot;SHA1WithRSA&quot;);\n\n\/\/\u52a0\u8f7d\u79c1\u94a5\nsignature.initSign(privatekey);\n\n\/\/\u66f4\u65b0\u5f85\u7b7e\u540d\u7684\u6570\u636e\nsignature.update(plain.getBytes(&quot;UTF-8&quot;));\n\n\/\/\u8fdb\u884c\u7b7e\u540d\nbyte[] signed = signature.sign();\n\n\/\/\u5c06\u52a0\u5bc6\u540e\u7684\u5b57\u8282\u6570\u7ec4\uff0c\u8f6c\u6362\u6210BASE64\u7f16\u7801\u7684\u5b57\u7b26\u4e32\uff0c\u4f5c\u4e3a\u6700\u7ec8\u7684\u7b7e\u540d\u6570\u636e\nBASE64Encoderencoder = newBASE64Encoder();\n\nreturn encoder.encode(signed);<\/code><\/pre>\n<h3>\u516c\u94a5\u9a8c\u7b7e<\/h3>\n<p>a\uff09\u83b7\u53d6\u516c\u94a5<\/p>\n<pre><code class=\"language-java\">\/\/\u83b7\u53d6KeyFactory\uff0c\u6307\u5b9aRSA\u7b97\u6cd5\nKeyFactorykeyFactory = KeyFactory.getInstance(&quot;RSA&quot;);\n\n\/\/\u5c06BASE64\u7f16\u7801\u7684\u516c\u94a5\u5b57\u7b26\u4e32\u8fdb\u884c\u89e3\u7801\nBASE64Decoderdecoder = newBASE64Decoder();\n\nbyte[] encodeByte = decoder.decodeBuffer(pubKey);\n\n\/\/\u5c06BASE64\u89e3\u7801\u540e\u7684\u5b57\u8282\u6570\u7ec4\uff0c\u6784\u9020\u6210X509EncodedKeySpec\u5bf9\u8c61\uff0c\u751f\u6210\u516c\u94a5\u5bf9\u8c61\nPublicKeypublicKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodeByte));<\/code><\/pre>\n<p>b\uff09\u4f7f\u7528\u516c\u94a5\uff0c\u8fdb\u884c\u9a8c\u7b7e<\/p>\n<pre><code class=\"language-java\">\/\/\u83b7\u53d6Signature\u5b9e\u4f8b\uff0c\u6307\u5b9a\u7b7e\u540d\u7b97\u6cd5(\u4e0e\u4e4b\u524d\u4e00\u81f4)\nSignaturesignature = Signature.getInstance(&quot;SHA1WithRSA&quot;);\n\n\/\/\u52a0\u8f7d\u516c\u94a5\nsignature.initVerify(publicKey);\n\n\/\/\u66f4\u65b0\u539f\u6570\u636e\nsignature.update(plain.getBytes(&quot;UTF-8&quot;));\n\n\/\/\u516c\u94a5\u9a8c\u7b7e\uff08true-\u9a8c\u7b7e\u901a\u8fc7\uff1bfalse-\u9a8c\u7b7e\u5931\u8d25\uff09\nBASE64Decoderdecoder = newBASE64Decoder();\n\nreturn signature.verify(decoder.decodeBuffer(sign));<\/code><\/pre>\n<h2>Nodejs\u901a\u8fc7RSA\u8fdb\u884c\u7b7e\u540d\u548c\u9a8c\u7b7e<\/h2>\n<h3>\u5b89\u88c5\u76f8\u5173\u5305<\/h3>\n<pre><code class=\"language-bash\">npm install node-rsa --save<\/code><\/pre>\n<h3>\u9996\u5148\u751f\u6210key<\/h3>\n<p>\u4f7f\u7528\u7684\u79c1\u94a5\u662f\u7531Java\u7aef\u751f\u6210\u7684<\/p>\n<pre><code class=\"language-javascript\">const NodeRSA = require(&#039;node-rsa&#039;);\n\nconst key = new NodeRSA({\n  b: 1024\n});\nkey.importKey(privateKey, &#039;pkcs8&#039;); \/\/ privateKey \u5e26\u5934\u5c3e\u7684\u683c\u5f0f\u5316\u7684\u5b57\u7b26\u4e32\nkey.setOptions({ signingScheme: &#039;sha256&#039; }); \/\/\u6307\u5b9a\u52a0\u5bc6\u683c\u5f0f<\/code><\/pre>\n<h3>nodejs\u8fdb\u884c\u7b7e\u540d<\/h3>\n<pre><code class=\"language-javascript\">key.sign(buffer, [encoding], [source_encoding]);<\/code><\/pre>\n<h3>nodejs\u8fdb\u884c\u9a8c\u7b7e<\/h3>\n<pre><code class=\"language-javascript\">key.verify(buffer, signature, [source_encoding], [signature_encoding]) \/\/Return result of check, true or false.<\/code><\/pre>\n<h2>\u5b9e\u8df5<\/h2>\n<p>\u73b0\u5b9e\u60c5\u51b5\u4e0b\uff0cJava\u6709\u81ea\u5df1\u7684<code>KeyPairGenerator<\/code>\u7c7b\u53ef\u4ee5\u81ea\u5df1\u751f\u6210\u516c\u94a5\u548c\u79c1\u94a5\uff0c\u5e76\u4e0d\u7528\u501f\u52a9openssl\u3002\u5bfc\u81f4\u5176\u4ed6\u8bed\u8a00\u6bd4\u5982nodejs\u548cpython\u7edf\u4e00\u4e0d\u4e86\u79c1\u94a5\u548c\u516c\u94a5\u7684\u683c\u5f0f\u3002\u6700\u5927\u7684\u533a\u522b\u662f<code>KeyPairGenerator<\/code>\u751f\u6210\u7684\u662f\u5b57\u7b26\u4e32\u5f62\u5f0f\u7684KEY\u800c\u4e0d\u662fPEM\u683c\u5f0f\u7684\u3002<\/p>\n<h3>Java\u7b7e\u540d\u548c\u9a8c\u7b7e<\/h3>\n<h4>Java\u751f\u6210\u516c\u94a5\u548c\u79c1\u94a5<\/h4>\n<pre><code class=\"language-java\">\/\/ KeyPairGenerator\u7c7b\u7528\u4e8e\u751f\u6210\u516c\u94a5\u548c\u79c1\u94a5\u5bf9\uff0c\u57fa\u4e8eRSA\u7b97\u6cd5\u751f\u6210\u5bf9\u8c61\nKeyPairGenerator keyPairGen = null;\ntry {\n    keyPairGen = KeyPairGenerator.getInstance(&quot;RSA&quot;);\n} catch (NoSuchAlgorithmException e) {\n    \/\/ TODO Auto-generated catch block\n    e.printStackTrace();\n}\n\/\/ \u521d\u59cb\u5316\u5bc6\u94a5\u5bf9\u751f\u6210\u5668\uff0c\u5bc6\u94a5\u5927\u5c0f\u4e3a96-1024\u4f4d\nkeyPairGen.initialize(2048, new SecureRandom());\n\/\/ \u751f\u6210\u4e00\u4e2a\u5bc6\u94a5\u5bf9\uff0c\u4fdd\u5b58\u5728keyPair\u4e2d\nKeyPair keyPair = keyPairGen.generateKeyPair();\n\/\/ \u5f97\u5230\u79c1\u94a5\nRSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();\n\/\/ \u5f97\u5230\u516c\u94a5\nRSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();\n\/\/ \u5f97\u5230\u516c\u94a5\u5b57\u7b26\u4e32\nString publicKeyString = Base64.encode(publicKey.getEncoded());\n\/\/ \u5f97\u5230\u79c1\u94a5\u5b57\u7b26\u4e32\nString privateKeyString = Base64.encode(privateKey.getEncoded());<\/code><\/pre>\n<h4>Java\u7b7e\u540d<\/h4>\n<pre><code class=\"language-java\">\/**\n * RSA\u7b7e\u540d\n * \n * @param content    \u5f85\u7b7e\u540d\u6570\u636e\n * @param privateKey \u5546\u6237\u79c1\u94a5\n * @param encode     \u5b57\u7b26\u96c6\u7f16\u7801\n * @return \u7b7e\u540d\u503c\n *\/\npublic static String sign(String content, String privateKey, String encode) {\n    try {\n        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));\n\n        KeyFactory keyf = KeyFactory.getInstance(&quot;RSA&quot;);\n        PrivateKey priKey = keyf.generatePrivate(priPKCS8);\n\n        java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);\n\n        signature.initSign(priKey);\n        signature.update(content.getBytes(encode));\n\n        byte[] signed = signature.sign();\n\n        return Base64.encode(signed);\n    } catch (Exception e) {\n        e.printStackTrace();\n    }\n\n    return null;\n}<\/code><\/pre>\n<h4>Java \u9a8c\u7b7e<\/h4>\n<pre><code class=\"language-java\">\/**\n * RSA\u9a8c\u7b7e\u540d\u68c0\u67e5\n * \n * @param content   \u5f85\u7b7e\u540d\u6570\u636e\n * @param sign      \u7b7e\u540d\u503c\n * @param publicKey \u5206\u914d\u7ed9\u5f00\u53d1\u5546\u516c\u94a5\n * @param encode    \u5b57\u7b26\u96c6\u7f16\u7801\n * @return \u5e03\u5c14\u503c\n *\/\npublic static boolean doCheck(String content, String sign, String publicKey, String encode) {\n    try {\n        KeyFactory keyFactory = KeyFactory.getInstance(&quot;RSA&quot;);\n        byte[] encodedKey = Base64.decode(publicKey);\n        PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));\n\n        java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);\n\n        signature.initVerify(pubKey);\n        signature.update(content.getBytes(encode));\n\n        boolean bverify = signature.verify(Base64.decode(sign));\n        return bverify;\n\n    } catch (Exception e) {\n        e.printStackTrace();\n    }\n\n    return false;\n}<\/code><\/pre>\n<h3>node\u7b7e\u540d\u548c\u9a8c\u7b7e<\/h3>\n<h4>\u79d8\u94a5\u683c\u5f0f\u8f6c\u6362<\/h4>\n<p>\u9700\u8981\u501f\u52a9\u8f6c\u6362\u51fd\u6570\u8f6c\u6362\u6210PEM\u683c\u5f0f<\/p>\n<pre><code class=\"language-javascript\">function insertStr(str, insertStr, sn) {\n    var newstr = &#039;&#039;;\n    for (var i = 0; i &lt; str.length; i += sn) {\n    var tmp = str.substring(i, i + sn);\n    newstr += tmp + insertStr;\n    }\n    return newstr;\n}\n\nconst getPrivateKey = function(key) {\n    const result = insertStr(key, &#039;\\n&#039;, 64);\n    return &#039;-----BEGIN PRIVATE KEY-----\\n&#039; + result + &#039;-----END PRIVATE KEY-----&#039;;\n};\n\nconst getPublicKey = function(key) {\n    const result = insertStr(key, &#039;\\n&#039;, 64);\n    return &#039;-----BEGIN PUBLIC KEY-----\\n&#039; + result + &#039;-----END PUBLIC KEY-----&#039;;\n};<\/code><\/pre>\n<h4>\u7b7e\u540d<\/h4>\n<pre><code class=\"language-javascript\">const key = new NodeRSA({\n b: 2048  \/\/\u53ef\u4ee5\u77e5\u9053\u4f4d\u6570\n});\nkey.importKey(privateKey, &#039;pkcs8&#039;); \/\/\u6839\u636ejava\u7aef\u6a21\u5f0f\nkey.setOptions({ signingScheme: &#039;sha256&#039; }); \/\/\u6307\u5b9a\u52a0\u5bc6\u683c\u5f0f\n\n\/\/ API key.sign(buffer, [encoding], [source_encoding]);\nlet sign = key.sign(noSign, &#039;base64&#039;, &#039;utf8&#039;);<\/code><\/pre>\n<p>\u7279\u522b\u6ce8\u610fhttp\u8bf7\u6c42\u7684\u65f6\u5019\u4f1a\u628aRSA\u7b7e\u540d\u540e\u7684\u5b57\u7b26\u4e32\u4e2d\u7684<code>+<\/code>\u53f7\u8fdb\u884c\u8f6c\u4e49\u3002\u9700\u8981\u8c03\u7528\u4e0b<code>encodeURIComponent<\/code>\u65b9\u6cd5\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00 \u901a\u5e38\u6211\u4eec\u4f7f\u7528\u7684\u662f\u6807\u51c6\u7684PEM\u8bc1\u4e66\uff0cPEM\u8bc1\u4e66\u662fOpenSSL\u7684\u6807\u51c6\u683c\u5f0f\u3002 PEM\u683c\u5f0f\u4fe1\u606f\u6700\u5927\u7684\u7279\u70b9\u662f\u4f1a\u5e26 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43,34],"tags":[135,108],"class_list":["post-1303","post","type-post","status-publish","format-standard","hentry","category-java-basic","category-node","tag-node","tag-rsa"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1303"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1303\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}