javascriptphpdigital-signaturejson-web-signature

Different digital signature results between PHP and Javascript JWA


I'm trying to generate a signature using RSA 256 but I've got a different result between JavaScript and PHP.

My JavaScript code:

let private_key_path = Helpers.publicPath('key/API_Portal.pem');
// password .pem file
let password = 'mandiri123';
let data = client_id + "|" + timestamp;

// load private key file
let rsa_algorithm = jwa('RS256');
let privateKey = fs.readFileSync(private_key_path);
let signature = rsa_algorithm.sign(data, {'key': privateKey, 'passphrase': password});
return signature;

Output:

tCB6v9_UnUTNpkeTZwgjn-iepO4XGwhZ72Q7LONarc-wT8pC18gyd46GYT8I1dLwVymPRDOzWwA9XXELRncG-CmYXlrutJssAUKmDv3hMRedbDu7-60OU9haSaBskedPoqlL76CigQXJ8ZX2_gnf8YG2-wALJfD1VquQWinmSUsMAD2bMB_EgDmSlOLrr_5BSKO2Pzq3XpJxcriptl-l6s7SsR_K6Gb1KYyhxmOAm41nKG9i-kUhvyDaZzTQ9Hw1_vqPOJN8gNhj6lnHimwizIOENsOtkIKhwa5QjL1Oa3PtnrMhCaQ9fWsUG83-rPOkbOulB5o12qWTxmeSJVsW8w

My PHP code:

// Specify private key location, passphrase, data, and hash algorithm
$private_key_path = public_path('key\API_Portal.pem');
// Password .pem file
$password = 'mandiri123';
$data = $this->clientId . '|' . "2020-11-19T11:35:57.190T+0700";
$rsa_algorithm = OPENSSL_ALGO_SHA256;

// Load private key file
$fp = fopen($private_key_path, 'r');
$privatekey_file = fread($fp, 8192);
fclose($fp);
$privatekey = openssl_pkey_get_private($privatekey_file, $password);
// return $privatekey_file;
// Sign data
openssl_sign($data, $signature, $privatekey, $rsa_algorithm);
$result = base64_encode($signature);
return $result;

Output:

tCB6v9/UnUTNpkeTZwgjn+iepO4XGwhZ72Q7LONarc+wT8pC18gyd46GYT8I1dLwVymPRDOzWwA9XXELRncG+CmYXlrutJssAUKmDv3hMRedbDu7+60OU9haSaBskedPoqlL76CigQXJ8ZX2/gnf8YG2+wALJfD1VquQWinmSUsMAD2bMB/EgDmSlOLrr/5BSKO2Pzq3XpJxcriptl+l6s7SsR/K6Gb1KYyhxmOAm41nKG9i+kUhvyDaZzTQ9Hw1/vqPOJN8gNhj6lnHimwizIOENsOtkIKhwa5QjL1Oa3PtnrMhCaQ9fWsUG83+rPOkbOulB5o12qWTxmeSJVsW8w==

The result in PHP is correct, why is there a difference between the two?


Solution

  • According to section 3.3 of JWA specification:

    The RSA SHA-256 digital signature is generated as follows:

    1. Generate a digital signature of the bytes of the ASCII representation of the JWS Secured Input using RSASSA-PKCS1-V1_5-SIGN and the SHA-256 hash function with the desired private key. The output will be a byte array.
    2. Base64url encode the resulting byte array.

    Note that base64url encoding is different from the standard base64 encoding used by PHP. The + and / are replaced with - and _. A simple string substitution is all that's needed to make them the same.