I would like to encrypt and sign certain data in nodejs and validate the signature in php. I keep on getting this error:
error:04091077:rsa routines:int_rsa_verify:wrong signature length
I have tried to change the algorithm being used, Also tried php extension such as phpseclib. In Nodejs am using the "crypto": "^1.0.1"
. Also this openssl_verify in php.
Here is my nodejs code
const crypto = require('crypto');
module.exports = {
generateKey: () => {
return { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
});
},
encryptMessage: (message) => {
const config = new Configstore(packageJson.name);
const algorithm = 'aes-256-cbc';
const key = config.get('serverKey');
const iv = crypto.randomBytes(16);
let cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key), iv);
let encrypted = cipher.update(message);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex')};
},
signMessage: (message) => {
console.log(message);
const config = new Configstore(packageJson.name);
const sign = crypto.createSign('SHA256');
sign.update(message);
sign.end();
const signature = sign.sign(config.get('privateKey'),'base64');
const verify = crypto.createVerify('SHA256');
verify.update(message);
verify.end();
console.log(config.get('publicKey'));
console.log('Its working: ' + verify.verify(config.get('publicKey'), signature, 'base64'));
return signature;
}
}
Here is php:
public function saveSecreteMessage(Request $request) {
$request->validate([
'username' => 'required',
'secretName' => 'required',
'secretMessage' => 'required'
]);
$publicKey = User::where('username', $request->input('username'))->first();
if (!$publicKey) {
return response()->json('Not allowed', 401);
}
$data = $request->input('secretMessage')['encryptedData'];
$signature = $request->input('secretMessage')['signature'];
/* $rsa = new RSA();
$rsa->loadKey($publicKey->publicKey); // public key;
return $rsa->verify('message', $signature, 'base64') ? 'verified' : 'unverified';*/
$ok = openssl_verify(base64_encode($data), base_path($signature), $publicKey->publicKey, 'SHA256');
if ($ok == 1) {
return response()->json('', 200);
} else {
return response()->json(openssl_error_string(), 400);
}
$pet = $request->all();
return $pet;
}
I expect the php code to validate the signature sent over from nodejs. I can't seem to get it to work. The error I get is:
error:04091077:rsa routines:int_rsa_verify:wrong signature length
I got it working.
JS code:
const crypto = require('crypto');
keyPair = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
}
});
var message = "zzzz";
const sign = crypto.createSign('SHA256');
sign.update(message);
sign.end();
const signature = sign.sign(keyPair.privateKey,'base64');
console.log(keyPair.publicKey);
console.log(signature);
PHP code:
$rsa = new RSA;
$rsa->loadKey('-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1e4Gi38Dlyl41RSGnQAK
UsHONpX806tFD3fuOby3JQlhlDM+Pe/H8y6E/zMDtNSZXtO+QCqghtMLDVG2br9e
i8uvGFwxLFUaWVkOYY7Tz21vJYYclvn67y0fJE8jgKUOdl3fgv/H3IGRVTROOetH
4oMpHMTGRpjZFfI6mi7CSDiaR8D1EpmPeXJn8yYPHK4uDn5srhZDQTvXXwbYkskX
FjbSx3yKvu1wkwKbKU5GkbBCzsFlNDhlCN4fvZ9SjinnV1iARgB80qIQlQ6JAUpp
xM/bTUntjI73DHCF3dXv9pbwn6w/vfjoyxstwAzgp+7C8HuaVm12KOeKG5Lsbj/L
XwIDAQAB
-----END PUBLIC KEY-----');
$plaintext = 'zzzz';
$signature = base64_decode('Vzc+63A5nAZWwIPD99pJQkzR7JfOhG0xyaTQh+Pel2wWklnzN9lTibwhliJs7tyZlJzjZrhgS2reTDd26HqLw11RDbqMCxim/InOiuFPbOg8EgNt55mNyfICszt+2ZVa1Mjm8zXpFBvNee5EPPFbqoCRKUpulDiGwRVz8v6rgSrx+Ptl11dIXyQuTa90bTdJEHiGK73F/uPh/B9AQOVYkoJKA4GC8H7pC3+AiTBREeBfRZp7gMF3wq2pYS5ffGemxsIkKuVoDurVNSJL9xWF10H3nn0egpIDwDQLYdilrVAUW7z+Qu6lQ2FxNiFSX0TT6gL02WN5/UxCVokCSnufkg==');
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$rsa->setHash('sha256');
echo $rsa->verify($plaintext, $signature) ? 'good' : 'bad';