【问题标题】:Converting Java crypto code to NodeJS将 Java 加密代码转换为 NodeJS
【发布时间】:2016-11-13 18:40:27
【问题描述】:

我正在努力在 NodeJS 中实现 Walmart API。 Walmart 仅提供 JAVA 示例。我在正确处理时遇到问题。与使用他们提供的 Java 可执行文件相比,我的签名有点长并且不被接受。

如果有任何帮助,我将不胜感激。即使弄清楚沃尔玛提供的秘密是什么格式也会有所帮助。

这里是有效的 Java 代码:

import org.apache.commons.codec.binary.Base64;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;

public class SHA256WithRSAAlgo {
    private static String consumerId = "b68d2a72....";   // Trimmed for security reason
    private static String baseUrl = "https://marketplace.walmartapis.com/v2/feeds";
    private static String privateEncodedStr = "MIICeAIBADANBgkqhkiG9w0BAQEFAA......";       //Trimmed for security reasons
    public static void main(String[] args) {
        String httpMethod = "GET";
        String timestamp = String.valueOf(System.currentTimeMillis());
        String stringToSign = consumerId + "\n" +
                                baseUrl + "\n" +
                                httpMethod + "\n" +
                                timestamp + "\n";
        String signedString = SHA256WithRSAAlgo.signData(stringToSign, privateEncodedStr);
        System.out.println("Signed String: " + signedString);
    }
    public static String signData(String stringToBeSigned, String encodedPrivateKey) {
        String signatureString = null;
        try {
            byte[] encodedKeyBytes = Base64.decodeBase64(encodedPrivateKey);
            PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(encodedKeyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey myPrivateKey = kf.generatePrivate(privSpec);
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(myPrivateKey);
            byte[] data = stringToBeSigned.getBytes("UTF-8");
            signature.update(data);
            byte[] signedBytes = signature.sign();
            signatureString = Base64.encodeBase64String(signedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signatureString;
    }
}

这是我的节点代码:

const PK_HEADER = '\n-----BEGIN PRIVATE KEY-----\n'
const PK_FOOTER = '\n-----END PRIVATE KEY-----\n'

const consumerId = 'b68d2a72....'  
const baseUrl = 'https://marketplace.walmartapis.com/v2/feeds'
const privateEncodedStr = 'MIICeAIBADANBgkqhkiG9w0BAQEFAA......'      

const privateKey = `${PK_HEADER}${config.walmart.secret}${PK_FOOTER}`

const privateEncodedKey = Buffer.from(privateKey, 'base64')
const timestamp = Date.now()

const stringToSign = consumerId + '\n' +
                     baseUrl + '\n' +
                     httpMethod + '\n' +
                     timestamp + '\n'

const sign = createSign('RSA-SHA256')
sign.update(stringToSign)
const signedString = sign.sign(privateKey, 'hex')

console.log(signedString)

一些笔记。我尝试按原样传递privateEncodedStr,但 Crypto 拒绝没有 PEM 标头,所以我不得不添加这些。

使用相同的时间戳,Java 代码产生了类似的结果:

bhG0q4Es7iOJtBvepJ2Ao6zPRllf6nM+026dgEadPcaYDdIoCQBYxWWSXB16XcQXgCDcqZ1PW2xgAavHC57jchSXtsTYkuXcWBavQGTH+5YonxIJCzI0wimVKKbqtocKvz4sngXKvIDP7wKKUdXOT6zXVYOdjLfUTERTs7RVg=

我的 JS 代码:

219af9f3048ccef558d6ddeeb61d19ed8a968ade5125760d81717dbd62e8447dd831b123a52624d56bc35aef1b082c29585e6fece2aba0fb7853d6840f45e724489028415a9eab8a51e48037a5884f5a12a238ed61a16003e1c412f873d3cfd2f6336dec8c262b01c3ba2a234f0979b8073f096cd35c7d1425bbcfc4603ff05b

这就是沃尔玛的秘密:

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMCCJeju5NFCHc/53N0AjZnmWq0UYZyrh3jRZH3UAISeZmLxcAgO65Cg8SfRact172Iy1uYnCB4NqKT5+x0BelWHA2fci5/7VqAdTJ3iZWB1g61lLUpf0IiesMWAycMBf7GwaVIsCGoPb+IC6l1P5IV2Mtb29WnivQyE3UM4dLvCvejdyPq8IoBIywTAgMBAAECgYEAnZ7yo1JXD+9usYcIC/wT9Nrji6uQcNMRTR9FhLE861k2w/Sjok0kzepZjanNojgwQS6OWIy3VEkRj2bTO7N4s6ApLa8yxoQt6ZrOSId9Ut7IenZQ39c6c/ig6e+awyjGvJlKdf7wtv2i4l4tiL8w23RnSECQQDy0wugM5hzV5wc/ejj+9cB8cqdEjfFG8yBZ200W1DAQwepIWFqSdiHbHW9xX5SiFa7JsDHyFWSdboYQToRDHuVAkEAyvQwDqAAz/FJn9oFKXznMjFfrtfoZ/BPrc/4BOUiyWjitxE6Ia5rNuTgCq3u1XxxP78t5spzMr5H5QdoUFHfBwJAbqpYZg6dsBOBhoUBmsWv26cyyOCEg4h9113oDh3MBPEXcQJAHd2JJN3OwMrU9rzyfYRv0ScK2YPUI1dtojo0WSQr2UafYTCCnEstN5vPvDoSvwXO1myk0COs1kAAbveHMIsf1jKVx7euXYP1J8Zwdfd9FjS2CQJAZ8L+jQyGlYIIdUQA7n0bbUblsGntsk1RKkTuZ31Q4w5gBnKO4dk3WMVhNdhmJnZRHRNflA41TITLNYh0EnrWheadVrhpBm2YBn7WFPQ==

知道这是什么格式吗?它似乎是一个 private key 删除了页眉/页脚。

【问题讨论】:

  • 这有点不相关,但如果你弄清楚了,你能在 github 上发帖吗?干杯!
  • 您生成的 JS 字符串似乎是一个十六进制字节序列,而 Java 生成的字符串编码为 base64。试试console.log(new Buffer(signedString, 'hex').toString('base64'))
  • @karuzo 你是我的英雄!就是这样。请您将其发布为答案。
  • 原来只需将 'hex' 更改为 'base64' 就是我需要做的所有事情。感谢您了解
  • 好的,我已经发布了一个更新的答案。

标签: java node.js cryptography node-crypto


【解决方案1】:

您的代码是正确的,您只需以正确的格式输出signedString,即base64

只是改变:

const signedString = sign.sign(privateKey, 'hex');

收件人:

const signedString = sign.sign(privateKey, 'base64');

你去吧。

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多