I am (slowly) learning Node JS and trying to use it in place of a PHP script I have. I need to sign a string I have assembled with SSL to pass on to a curl
request.
In PHP, this is how I’ve done it:
$sig = '2018-08-24T17:33:41Z:abcdef:/path/to/api'; $pkeyid = openssl_pkey_get_private("file://YourMomGoesToCollege.pem"); // Sign 'sig' with private key if(openssl_sign($sig, $signed_signature, $pkeyid, "sha256WithRSAEncryption")) { openssl_free_key($pkeyid); //Set curl header options ... curl_setopt($ch, CURLOPT_HTTPHEADER, [ "X-Apple-CloudKit-Request-SignatureV1: " . base64_encode($signed_signature), ] ); }
So I’m trying to generate the evuivalent of $signed_signature
, but I’m not sure how to proceed. It seems like Node’s Crypto can do something similar, but its parameters seem different. This is my best guess:
const crypto = require('crypto') const sign = crypto.createSign('SHA256') sign.write(sig) sign.end() const privateKey = __dirname + 'YourMomGoesToCollege.pem' var signedSignature = sign.sign(privateKey, 'hex') var readyForCurl = Buffer.from(signedSignature).toString('base64')
Am I on the right track?
Advertisement
Answer
Using your work as a starting point and doing some minor modifications, the following snippets result in the same signature being printed (base64-encoded):
PHP:
$data = 'some data to sign'; $key = openssl_pkey_get_private('file://private.pem'); if(openssl_sign($data, $signature, $key, 'sha256WithRSAEncryption')) { openssl_free_key($key); $signature_b64 = base64_encode($signature); echo($signature_b64."n"); }
Node JS:
const crypto = require('crypto'); const sign = crypto.createSign('SHA256'); const fs = require('fs') sign.write('some data to sign'); sign.end(); const key = fs.readFileSync('private.pem'); signature_b64 = sign.sign(key, 'base64'); console.log(signature_b64);
diff
-ing the two:
$ diff <(php sign.php) <(node sign.js)
shows the outputs are the same.
I used this resource: iotdb-crypto-example