首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用nodejs for Alipay API生成数字签名

使用nodejs for Alipay API生成数字签名
EN

Stack Overflow用户
提问于 2020-04-07 12:55:24
回答 1查看 288关注 0票数 1

我正在植入支付宝API,到我的项目中。为了提出一些请求,我需要生成一个签名与RSA private.pem - public.pem。文档只显示了JAVA示例,但我需要用NodeJS实现它。因此,我尝试使用crypto.sign,但无法使其正常工作。

下面是JAVA代码:

代码语言:javascript
复制
const g = (content, privateKey, charset) => {

    try {

        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));

        PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(priPKCS8);

        Signature signature = Signature.getInstance("SHA256withRSA");

        signature.initSign(priKey);

        signature.update(content.getBytes(charset));

        byte[] signed = signature.sign();

        return Base64.getEncoder().encodeToString(signed);

    } catch (Exception e) {

        throw new RuntimeException("the key's format maybe not right");

    }

}

有没有人能帮我把这段代码转换成NodeJS代码。

以下是我的工作解决方案:

代码语言:javascript
复制
/**
     * @param {*} // let parameters = new Map(); parameters.set("service", "alipay.overseas.secmerchant.maintain.queryStatus");
     */
    signRSA: async (parameters) => {


        let unnecessaryParams = Array.from(parameters.entries())
            .filter(a1 => a1[1] === undefined || a1[1].length === 0 || a1[1] === "null")
            .map(a1 => a1[0]);
        unnecessaryParams.forEach(a1 => parameters.delete(a1));

        let charset = ["_input_charset", "charset"].filter(a1 => parameters.has(a1)).map(a1 => parameters.get(a1))[0];
        charset = charset === undefined ? "UTF-8" : charset;

        //MD5,RSA,RSA2
        let signContent = Array.from(parameters.entries())
            .filter(a1 => {
                return a1[0] !== "sign" && a1[0] !== "sign_type";
            })
            .sort((a1, a2) => a1[0].localeCompare(a2[0]))
            .map(a1 => a1[0] + "=" + a1[1]).join("&");

        let key = fs.readFileSync('./services/alipay/rsa_private_key.pem');

        // let RSA_sign = r.sign_it(signContent, key, "RSA2")
        let RSA_sign = crypto.createSign('RSA-SHA256')

        RSA_sign.update(signContent)

        let s1 = RSA_sign.sign(key, "base64")
        parameters.set("sign", s1);

        return Array.from(parameters.entries()).map(a1 => a1[0] + "=" + encodeURIComponent(a1[1])).join("&");
    }

EN

回答 1

Stack Overflow用户

发布于 2020-04-07 19:55:23

我已经创建了这段代码的Node.js版本,它应该使用提供的私钥对内容进行签名。

我还创建了一个verifySignature函数来检查这一点,并用Java语言创建了等效的代码(使用您的代码作为模板),以确保我们在两种语言中得到相同的结果。

Node.js

代码语言:javascript
复制
const crypto = require("crypto");

// Sample keys I've generated
const privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAICFIt6pLMSNn9scI/h85V/DamtsFqfN4DB+VSPpGMAcwEByKVsiBzdX7JJsr8uquoVWEmFPwymxUVwIy+MOK03QEaQDns0W/SeVNXyWvDTO2w65vV9hIEO1VyiQiBA8n0yoQGfbn2KBnv7SggJDpy10cF3lx5SdHV96lF+qyBs7AgMBAAECgYAQEJRLQNpXt1xEB0B3zyTc05B53Qj38MQVS7VYx8pQOUfOxnZk7dv5DwSDSRKwYqbuA9RIVbAPhhqlZnQV7a9722QBFcEKLh6/65HCX248t/v6/x1kj9p6rcbLuFuakjKXs4AznWmb4YV2Flh9/qx9keUzdS5/UPJZVU2+grAAAQJBAO/3JjTRgiGQxEdA4MVpfs0lh/+gzbDszL1In5USAPKyGPDqYIktAfF3cBc7BKyK3kBenJi3S5Qv5R3u2Ly6H0cCQQCJG5oAvEt8JPL7ZyxHzdTP7+7hWXRGOyK2Ar0CO3fbg+SGls5liJY3HNHc0lrdyG1A+5Z6AKUNYCgfbOhqmeZtAkEA5CzhUoYJNDuAt7Q0RuLqZM2URPk1vU9d23qr68ajyiKZXrOuuaFnYKDOn/hJmHuvnAua4gggwLbOKSlNRB/CzwJAKedztBHYiELKuKeZ0wBHsJ3GRr2OWgCs5TAFEG+YfFDdQX1J66JJNuLqCTGJcAtXyOqb3QHhcCsZWDFy/1G2KQJBAKRnm7D0BHLOK37Xp3MxGva4tFP6VPdqjgIVBW3PM8BcwTcw8VML3kkFh2y0gJdLRxzFwDDJgfG6Cxp8i1gqB+4=";
const publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAhSLeqSzEjZ/bHCP4fOVfw2prbBanzeAwflUj6RjAHMBAcilbIgc3V+ySbK/LqrqFVhJhT8MpsVFcCMvjDitN0BGkA57NFv0nlTV8lrw0ztsOub1fYSBDtVcokIgQPJ9MqEBn259igZ7+0oICQ6ctdHBd5ceUnR1fepRfqsgbOwIDAQAB";

const content = "We are such stuff as dreams are made on, and our little life is rounded with a sleep";

const signature = signContent(content, base64KeyToPEM(privateKey, "PRIVATE"), "utf8");

console.log("Signature:", signature);
console.log("Verify signature:", verifySignature(content, base64KeyToPEM(publicKey, "PUBLIC"), signature, "utf8"));

function signContent(content, privateKey, encoding) {
    const sign = crypto.createSign("SHA256");
    sign.write(content, encoding);
    sign.end();
    return sign.sign(privateKey, "base64");
}

function verifySignature(content, publicKey, signature, encoding) {
    const verify = crypto.createVerify("SHA256");    
    verify.write(content, encoding);
    verify.end();
    return verify.verify(publicKey, Buffer.from(signature, "base64"));
}

function base64KeyToPEM(base64Key, keyType) {
    return [`-----BEGIN ${keyType} KEY-----`, ...splitStringIntoChunks(base64Key, 64), `-----END ${keyType} KEY-----`].join("\n");
}

function splitStringIntoChunks(input, chunkSize) {
    const chunkCount = Math.ceil(input.length / chunkSize)
    return Array.from( { length: chunkCount } ).map((v, chunkIndex) => input.substr(chunkIndex * chunkSize, chunkSize));
}

Java

代码语言:javascript
复制
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

public class DigitalSignature {


    public static void main(String[] args)
    {
        try {

            // Sample keys I've generated
            final String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAICFIt6pLMSNn9scI/h85V/DamtsFqfN4DB+VSPpGMAcwEByKVsiBzdX7JJsr8uquoVWEmFPwymxUVwIy+MOK03QEaQDns0W/SeVNXyWvDTO2w65vV9hIEO1VyiQiBA8n0yoQGfbn2KBnv7SggJDpy10cF3lx5SdHV96lF+qyBs7AgMBAAECgYAQEJRLQNpXt1xEB0B3zyTc05B53Qj38MQVS7VYx8pQOUfOxnZk7dv5DwSDSRKwYqbuA9RIVbAPhhqlZnQV7a9722QBFcEKLh6/65HCX248t/v6/x1kj9p6rcbLuFuakjKXs4AznWmb4YV2Flh9/qx9keUzdS5/UPJZVU2+grAAAQJBAO/3JjTRgiGQxEdA4MVpfs0lh/+gzbDszL1In5USAPKyGPDqYIktAfF3cBc7BKyK3kBenJi3S5Qv5R3u2Ly6H0cCQQCJG5oAvEt8JPL7ZyxHzdTP7+7hWXRGOyK2Ar0CO3fbg+SGls5liJY3HNHc0lrdyG1A+5Z6AKUNYCgfbOhqmeZtAkEA5CzhUoYJNDuAt7Q0RuLqZM2URPk1vU9d23qr68ajyiKZXrOuuaFnYKDOn/hJmHuvnAua4gggwLbOKSlNRB/CzwJAKedztBHYiELKuKeZ0wBHsJ3GRr2OWgCs5TAFEG+YfFDdQX1J66JJNuLqCTGJcAtXyOqb3QHhcCsZWDFy/1G2KQJBAKRnm7D0BHLOK37Xp3MxGva4tFP6VPdqjgIVBW3PM8BcwTcw8VML3kkFh2y0gJdLRxzFwDDJgfG6Cxp8i1gqB+4=";
            final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAhSLeqSzEjZ/bHCP4fOVfw2prbBanzeAwflUj6RjAHMBAcilbIgc3V+ySbK/LqrqFVhJhT8MpsVFcCMvjDitN0BGkA57NFv0nlTV8lrw0ztsOub1fYSBDtVcokIgQPJ9MqEBn259igZ7+0oICQ6ctdHBd5ceUnR1fepRfqsgbOwIDAQAB";

            final String content = "We are such stuff as dreams are made on, and our little life is rounded with a sleep";

            String signature = signContent(content, privateKey, "UTF-8");

            System.out.println("Signature: " + signature);
            System.out.println("verifySignature: " + verifySignature(signature, content, getPublicKeyFromBase64(publicKey), "UTF-8"));
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    private static PublicKey getPublicKeyFromBase64(String publicKeyBase64) throws Exception {
        return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyBase64)));
    }

    public static String signContent(String content, String privateKey, String charset) throws Exception
    {

            try {

                PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));

                PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(priPKCS8);

                Signature signature = Signature.getInstance("SHA256withRSA");

                signature.initSign(priKey);

                signature.update(content.getBytes(charset));

                byte[] signed = signature.sign();

                return Base64.getEncoder().encodeToString(signed);

            } catch (Exception e) {
                throw new RuntimeException("signContent: Exception occurred: " + e.getMessage());
            }
        }

        public static Boolean verifySignature(String signatureBase64, String content, PublicKey publicKey, String charset) throws Exception {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initVerify(publicKey);
            signature.update(content.getBytes(charset));
            return signature.verify(Base64.getDecoder().decode(signatureBase64));
        }

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61073068

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档