PHP is the most efficient language for handling web requests. I have tested that PHP's OpenSSL library can decrypt data encrypted by JS using AES, OAEP, and EC-DH, and can also verify data signed by JS using HMAC and RSA-PKCS#1.5. However, it cannot verify data signed by JS using EC-DSA or RSA-PSS. Verifying data signed with EC-DSA and RSA-PSS is necessary. However, PHP's OpenSSL library still does not support verifying EC-DSA and RSA-PSS signatures.
// JS EC-DSA sign
crypto.subtle.generateKey(
{
name: 'ECDSA',
namedCurve: 'P-256' // P-521 corresponds to secp521r1, P-384 corresponds to secp384r1, p-256 corresponds to prime256v1
},
true,
['sign', 'verify']
).then(pair => {
return {
publicKey: crypto.subtle.exportKey('spki', pair.publicKey),
signature: crypto.subtle.sign(
{
name: 'ECDSA',
hash: {
name: 'SHA-1' // or SHA-256, SHA-384, SHA-512
}
},
pair.privateKey,
(new TextEncoder()).encode('test data')
)
};
}).then(data => {
// await crypto.subtle.verify(...) is true;
// convert data.publicKey ArrayBuffer to PEM publicKey and encodeURIComponent it;
// convert data.signature ArrayBuffer to base64 string;
// send data object to PHP
});
// PHP receives the above data and executes openssl_verify
openssl_verify(
base64_decode($_POST['signature']),
'test data',
urldecode($_POST['publicKey']),
OPENSSL_ALGO_SHA1 // or OPENSSL_ALGO_SHA256, OPENSSL_ALGO_SHA384, OPENSSL_ALGO_SHA512
);
// result: -1
// JS RSA-PSS sign
crypto.subtle.generateKey(
{
name: 'RSA-PSS',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: 'SHA-256' // or SHA-1, SHA-384, SHA-512
},
true,
['sign', 'verify']
).then(pair => {
return {
publicKey: crypto.subtle.exportKey('spki', pair.publicKey),
signature: crypto.subtle.sign(
{
name: 'RSA-PSS',
saltLength: 32
},
pair.privateKey,
(new TextEncoder()).encode('test data')
)
};
}).then(data => {
// await crypto.subtle.verify(...) is true;
// convert data.publicKey ArrayBuffer to PEM publicKey and encodeURIComponent it;
// convert data.signature ArrayBuffer to base64 string;
// send data object to PHP
});
// PHP receives the above data and executes openssl_verify
openssl_verify(
base64_decode($_POST['signature']),
'test data',
urldecode($_POST['publicKey']),
OPENSSL_ALGO_SHA256 // or OPENSSL_ALGO_SHA1, OPENSSL_ALGO_SHA384, OPENSSL_ALGO_SHA512
);
// result: -1, but RSA-PKCS#1.5 is OK