2016-11-13 160 views
2

我正在NodeJS中实施Walmart API。沃尔玛仅提供JAVA示例。我遇到的问题正确。与使用它们提供的Java可执行文件相比,我的签名更长,并且不被接受。将Java加密代码转换为NodeJS

我很感激任何帮助。即便搞清楚沃尔玛提供的秘密是什么格式也会有所帮助。

这里的工作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 balks没有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删除了页眉/页脚。

+0

这有点不相关,但如果你确实搞清楚了,你可以在github上发布吗?干杯! –

+0

您生成的JS字符串似乎是一个十六进制字节序列,而生成的Java字符串则在'base64'中编码。试试'console.log(new Buffer(signedString,'hex')。toString('base64'))' – karliwson

+0

@karuzo你是我的英雄!就是这样。你会张贴作为答案请。 – cyberwombat

回答

1

你的代码是正确的,你只需要输出signedString在正确的格式,这是base64

只是改变:

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

要:

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

而且你去那里。

+0

这里是Gist https://gist.github.com/cyberwombat/bc22fcd44037b7f8c1920432636f9cd5 – cyberwombat