3

I have generated a pair of public and private key using window.crypto.subtle.generateKey.

window.crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 2048,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: "SHA-1"
    },
    true,
    ["encrypt", "decrypt"]
).then(function(keyPair) {
    exportPrivateCryptoKey(keyPair.privateKey);
    exportPublicCryptoKey(keyPair.publicKey);
});

Now I have the keys, I encrypt the data and send to my PHP backend.

Frontend:

const publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzi0NKGfWSZvDe/W6VW7BwITz9vT0GePtnwRXlUPCivruf1VjurUtQhDFZw+SGAjXCwf9pf39AlunDpdp+nuAgpCaVO+RXBnwB5nnTOzXUdAxuIWfLOzXHbwEN59eh6a3RZ6bpmjnKgZ8/6oRn/e0LzqG/NKI9oNAMxKKwAD4G9Oh0sNgF5ZdR8keRm7+f/mUQNfASS3HdERWexDLRxAFZLfoSvbu3gBvg/jzv3hsju05r5RLxhsislDHxRlMIP7Zo4v0KHa9JNm6xMyBFUtzt9XPxilJy9KYrJFPVY2QcLqn8e5M95aW3yBO3LMNZ0N8VoMT7F59Q4k7AqEooQL31QIDAQAB';

function encrypt(data) {
    return window.crypto.subtle.importKey(
        'spki',
        str2ab(window.atob(publicKey)),
        {
            name: 'RSA-OAEP',
            hash: {name: 'SHA-1'}
        },
        true,
        ['encrypt']
    ).then(function(cryptokey) {
        return window.crypto.subtle.encrypt({name: "RSA-OAEP"}, cryptokey, str2ab(data)).then(function(encrypted) {
            return arrayBufferToBase64String(encrypted);
        });
    });
}

$.ajax({
    type: "POST",
    url: url,
    data: "message=" + encrypt("Hello World"),
    dataType: "json",
    success: function(data) { ... },
    error: function(data) { ... }
});

Backend:

$data = $_POST['message'];
$privateKey = 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDOLQ0oZ9ZJm8N79bpVbsHAhPP29PQZ4+2fBFeVQ8KK+u5/VWO6tS1CEMVnD5IYCNcLB/2l/f0CW6cOl2n6e4CCkJpU75FcGfAHmedM7NdR0DG4hZ8s7NcdvAQ3n16HprdFnpumaOcqBnz/qhGf97QvOob80oj2g0AzEorAAPgb06HSw2AXll1HyR5Gbv5/+ZRA18BJLcd0RFZ7EMtHEAVkt+hK9u7eAG+D+PO/eGyO7TmvlEvGGyKyUMfFGUwg/tmji/Qodr0k2brEzIEVS3O31c/GKUnL0piskU9VjZBwuqfx7kz3lpbfIE7csw1nQ3xWgxPsXn1DiTsCoSihAvfVAgMBAAECggEAIZBp/PLyiqcl6s81F2Vhe2LpiIGWH4TgkSuWyoDuccup+ea/xoxqIsAyMrXxNaJyx6P0Ygp4HuMmzhRON23VnOvHhB5ADrtWPRaL9hT0dKgs//oY0Kp51qheE2QJcpHschQBCNU5FLlbrg9UsTMVDT887HmlvGPflrDlD57YxUaiydDedruDKtrD40cVLU9wTlgjYtrMrlB/aKnSnlE13JzDst6vbiREMag5NIbXBZ3cfp1126PLbyazbPhaptgipfIXLX+MnQXtcUrobHLHyHcKgxTfqkSKFj/G5IIfOVwr+tQDGBEl1YEVivNYv0eBVunX9hmTyZHfZt+EkFDivQKBgQDvvHpHA+9WmOgGKn45g/NmS2B3aovQjc74Ue21fJLhOth5/DI0D1Vulx10SLpBjPYI7OB1GMYh5LXk0JRVbUoa5sW2ECUCTw5e5qOQiyjRBOyJY8ZLqUW3EhmE3pvcMzVJYYDN9beNaT3u/Bcmjr+naovko2OLqIDkLFPPjbv43wKBgQDcKbrBHx9cuDDb4ZwnL4CJuFERRiQ+O+Agic5sxMIZDulhmWgsvRAoTW0gFzf550lGGr2FZ4omVQ1aBmaYa/2nPp3CrQVypSsDxx3WO5h33MMl2DEQ0s+UAmqdRpIE+Jk6mJYMkw7Dz+P7JYZKK0RNgmJfTMhRSwrPtGxpIbxBywKBgA8W4OdpYv4jX69Lq2g5Wu+cXPUHOsektVtB5OFgdupARvHeotZOBMWSM2NnVHndwnqrVjFonsfxWlWNn1iFKX3p+pXMDFhJ25CzmaX2bFpDohO/uPJ4NBAizoJjdJH2kysMPQw5pBT9g81wBpEBuSRze1ynwBNBRuOVuqy8shEnAoGAZ1/gpJUscKi7qELCw1N2kzPMPMQmeGI81opeNowcZw+tXXpeg8MyNvpD5vGAAwMqUJR1sJHxOBZvcnnW6nKqY0Dval07VZ1gGSIBTHonGQC7UKW2RCP3+5M25Coindrsd6r1qWnTYPXYIjB4YZL3Oz2hWwX+eM03gldBIAwLDQkCgYB4gLX86SZCGiAkyGFKee9IrBfdKKXdvefKCiUBMUXo+htVHciHYhSYTmz1LmToJBPuw3fMc9OtwSiiwTBwgRe5RPcoWpdvBfyxTVg1AURRiC/YjXI/C5WBpVrR20xRmgCLDNKW8fl6UogkPcBe+ZLjBn+61Pz8fB9dwk/PT01BMw==';
$privateKeyPem = "-----BEGIN PRIVATE KEY-----\n" . wordwrap($privateKey, 64, "\n", true) . "\n-----END PRIVATE KEY-----";
$success = openssl_private_decrypt(base64_decode($data), $message, $privateKey);
# not $success and $message is NULL

However, if I encrypt the message using openssl_public_encrypt in PHP then decrypt it then works, which means the key pair itself is valid.

$publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzi0NKGfWSZvDe/W6VW7BwITz9vT0GePtnwRXlUPCivruf1VjurUtQhDFZw+SGAjXCwf9pf39AlunDpdp+nuAgpCaVO+RXBnwB5nnTOzXUdAxuIWfLOzXHbwEN59eh6a3RZ6bpmjnKgZ8/6oRn/e0LzqG/NKI9oNAMxKKwAD4G9Oh0sNgF5ZdR8keRm7+f/mUQNfASS3HdERWexDLRxAFZLfoSvbu3gBvg/jzv3hsju05r5RLxhsislDHxRlMIP7Zo4v0KHa9JNm6xMyBFUtzt9XPxilJy9KYrJFPVY2QcLqn8e5M95aW3yBO3LMNZ0N8VoMT7F59Q4k7AqEooQL31QIDAQAB';
$privateKey = 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDOLQ0oZ9ZJm8N79bpVbsHAhPP29PQZ4+2fBFeVQ8KK+u5/VWO6tS1CEMVnD5IYCNcLB/2l/f0CW6cOl2n6e4CCkJpU75FcGfAHmedM7NdR0DG4hZ8s7NcdvAQ3n16HprdFnpumaOcqBnz/qhGf97QvOob80oj2g0AzEorAAPgb06HSw2AXll1HyR5Gbv5/+ZRA18BJLcd0RFZ7EMtHEAVkt+hK9u7eAG+D+PO/eGyO7TmvlEvGGyKyUMfFGUwg/tmji/Qodr0k2brEzIEVS3O31c/GKUnL0piskU9VjZBwuqfx7kz3lpbfIE7csw1nQ3xWgxPsXn1DiTsCoSihAvfVAgMBAAECggEAIZBp/PLyiqcl6s81F2Vhe2LpiIGWH4TgkSuWyoDuccup+ea/xoxqIsAyMrXxNaJyx6P0Ygp4HuMmzhRON23VnOvHhB5ADrtWPRaL9hT0dKgs//oY0Kp51qheE2QJcpHschQBCNU5FLlbrg9UsTMVDT887HmlvGPflrDlD57YxUaiydDedruDKtrD40cVLU9wTlgjYtrMrlB/aKnSnlE13JzDst6vbiREMag5NIbXBZ3cfp1126PLbyazbPhaptgipfIXLX+MnQXtcUrobHLHyHcKgxTfqkSKFj/G5IIfOVwr+tQDGBEl1YEVivNYv0eBVunX9hmTyZHfZt+EkFDivQKBgQDvvHpHA+9WmOgGKn45g/NmS2B3aovQjc74Ue21fJLhOth5/DI0D1Vulx10SLpBjPYI7OB1GMYh5LXk0JRVbUoa5sW2ECUCTw5e5qOQiyjRBOyJY8ZLqUW3EhmE3pvcMzVJYYDN9beNaT3u/Bcmjr+naovko2OLqIDkLFPPjbv43wKBgQDcKbrBHx9cuDDb4ZwnL4CJuFERRiQ+O+Agic5sxMIZDulhmWgsvRAoTW0gFzf550lGGr2FZ4omVQ1aBmaYa/2nPp3CrQVypSsDxx3WO5h33MMl2DEQ0s+UAmqdRpIE+Jk6mJYMkw7Dz+P7JYZKK0RNgmJfTMhRSwrPtGxpIbxBywKBgA8W4OdpYv4jX69Lq2g5Wu+cXPUHOsektVtB5OFgdupARvHeotZOBMWSM2NnVHndwnqrVjFonsfxWlWNn1iFKX3p+pXMDFhJ25CzmaX2bFpDohO/uPJ4NBAizoJjdJH2kysMPQw5pBT9g81wBpEBuSRze1ynwBNBRuOVuqy8shEnAoGAZ1/gpJUscKi7qELCw1N2kzPMPMQmeGI81opeNowcZw+tXXpeg8MyNvpD5vGAAwMqUJR1sJHxOBZvcnnW6nKqY0Dval07VZ1gGSIBTHonGQC7UKW2RCP3+5M25Coindrsd6r1qWnTYPXYIjB4YZL3Oz2hWwX+eM03gldBIAwLDQkCgYB4gLX86SZCGiAkyGFKee9IrBfdKKXdvefKCiUBMUXo+htVHciHYhSYTmz1LmToJBPuw3fMc9OtwSiiwTBwgRe5RPcoWpdvBfyxTVg1AURRiC/YjXI/C5WBpVrR20xRmgCLDNKW8fl6UogkPcBe+ZLjBn+61Pz8fB9dwk/PT01BMw==';
$publicKeyPem = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publicKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
$privateKeyPem = "-----BEGIN PRIVATE KEY-----\n" . wordwrap($privateKey, 64, "\n", true) . "\n-----END PRIVATE KEY-----";
openssl_public_encrypt("Hello World", $encrypted, $publicKeyPem);
$success = openssl_private_decrypt($encrypted, $message, $privateKeyPem);
# $success and $message = "Hello World"

Is there any setup I have done wrong? for example: different hash, modulusLength, padding?

I also have looked up RSA-OAEP SHA-512 Encrypt / Decrypt from Javascriptwebcrypt api to PHP openssl?, but I couldn't make this to work. I will keep trying, and post my solution if I got it. Meanwhile seeing any suggestion from the hackers. Thanks a lot.

Leon Ma
  • 303
  • 4
  • 13
  • 1
    You need to set the padding on the PHP side to `OPENSSL_PKCS1_OAEP_PADDING`. See [openssl_private_encrypt](https://www.php.net/manual/en/function.openssl-private-decrypt.php). – President James K. Polk Feb 17 '20 at 20:17
  • @JamesReinstateMonicaPolk that works, thank you so much. Should have done more thorough research and testing. I actually did try ```OPENSSL_PKCS1_OAEP_PADDING``` before, but I was using SHA-256 at the time which doesn't work, but using SHA-1 works with the padding. – Leon Ma Feb 18 '20 at 01:44

0 Answers0