title: RSA-OAEP SHA-512 Encrypt / Decrypt from Javascriptwebcrypt api to PHP openssl?
body: <p>I've been rather busy trying to get a secure exchange established between a browserclient, using the webcrypto api and PHP server using openssl. I've broken down things as much as I can. I wrote some javascript to generate a keypair, print out the values private and public, encrypt a simple string and print it out as well.</p>
  
  <p>I've copied the values straight to a simple php script. Trying to decode it with the values from the javascipt.</p>
  
  <p>Encoding and decoding works properly in the javascript (as posted below), decoding in php does not (also posted beneath the javascript). I also can't seem to find where to set the SHA-512 declaration in PHP. Does anyone have experience with this kind of exchange and perhaps point me in the right direction. RSA-OAEP was chosen because it's supported by chrome, mozilla, IE11 and Safari as well as PHP.</p>
  
  <p>Kind regards,
  Gideon</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// JavaScript Document
  var keyPair;
  var pemPublicKey;
  var pemPrivateKey;
  
  var _spki;
  var _pkcs8;
  
   window.crypto.subtle.generateKey({
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([1, 0, 1]),  // 24 bit representation of 65537
    hash: {name: "SHA-512"}
   }, true, ["encrypt", "decrypt"])
   .then(function(newKeyPair) {
    keyPair = newKeyPair;
    return keyPair;
   })
   .then(function(keyPair) {
    window.crypto.subtle.exportKey('spki', keyPair.publicKey)
    .then(function(spki) {
     _spki = spki;
     var pemPublicKey = convertBinaryToPem(spki, "PUBLIC KEY");
     document.writeln(pemPublicKey);
     sendToPhp();
    });
   
    window.crypto.subtle.exportKey('pkcs8', keyPair.privateKey)
    .then(function(pkcs8) {
     _pkcs8 = pkcs8;
     var pemPrivateKey = convertBinaryToPem(pkcs8, "PRIVATE KEY");
     document.writeln(pemPrivateKey);
    })
   });
   
   function sendToPhp() {
    window.crypto.subtle.importKey('spki', _spki, {name:"RSA-OAEP", hash: {name: "SHA-512"}}, false, ["encrypt"])
    .then(function(cryptokey) {
     window.crypto.subtle.encrypt({ name: "RSA-OAEP"}, cryptokey, str2ab('mijn geheimpje') )
     .then(function(encrypted){
      //returns an ArrayBuffer containing the encrypted data
      document.writeln(arrayBufferToBase64String(encrypted));
      receivedFromPhp(arrayBufferToBase64String(encrypted));
     });
    });
   }
   
   function receivedFromPhp(encrypted) {
    window.crypto.subtle.importKey('pkcs8', _pkcs8, {name:"RSA-OAEP", hash: {name: "SHA-512"}}, false, ["decrypt"])
    .then(function(cryptokey) {
     window.crypto.subtle.decrypt({ name: "RSA-OAEP"}, cryptokey, base64StringToArrayBuffer(encrypted) )
     .then(function(decrypted){
      //returns an ArrayBuffer containing the encrypted data
      var decryp = ab2str(decrypted);
      debugger;
     });
    });
   }
   
   function ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
   }
  
   function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i&lt;strLen; i++) {
     bufView[i] = str.charCodeAt(i);
    }
    return buf;
   }
   function base64StringToArrayBuffer(base64) {
    var binary_string =  atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array( len );
    for (var i = 0; i &lt; len; i++)        {
     bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
   }
   function arrayBufferToBase64String(arrayBuffer) {
    var byteArray = new Uint8Array(arrayBuffer)
    var byteString = '';
    for (var i=0; i&lt;byteArray.byteLength; i++) {
     byteString += String.fromCharCode(byteArray[i]);
    }
    return btoa(byteString);
   }
  
   function convertBinaryToPem(binaryData, label) {
    var base64Cert = arrayBufferToBase64String(binaryData);
  
    var pemCert = "-----BEGIN " + label + "-----\r\n";
  
    var nextIndex = 0;
    var lineLength;
    while (nextIndex &lt; base64Cert.length) {
     if (nextIndex + 64 &lt;= base64Cert.length) {
      pemCert += base64Cert.substr(nextIndex, 64) + "\r\n";
     } else {
      pemCert += base64Cert.substr(nextIndex) + "\r\n";
     }
     nextIndex += 64;
    }
  
    pemCert += "-----END " + label + "-----\r\n";
    return pemCert;
   }</code></pre>
  </div>
  </div>
  </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>&lt;?php
  
   error_reporting(E_ALL);
   ini_set("display_errors", 1);
   $pemPublicKey =  '-----BEGIN PUBLIC KEY-----
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzJ07T/SiZsUPfC4ymwj
  G/TqVdO04QZRUMcsmHeUG0BawSxlwoz+0YD48UZFYyTetw3egoasQfkvOPIUKuqq
  mPEXwGsVlLbkqvPsgNA2K6Zye8El9DEp83eoPqylopU0L9zSnQp9VaNpSgsOlltr
  0RRyq3q8gBJb7PkzuDzmXrr5KEuGmkLmOE3TH0Ck9u+c4xE87g3s5HtQ6uGa6jB6
  JooTN1edPum+kBJdJajOW5FvOfDnEHQBsKZPd4HiYcOlM7crt2Y9XnBSBIIZ1uR6
  a4Qs+EP6CwczPA6/J5a+GOV9ch1xZLsW5JuO55lCDpwrvKr7VVqwQG3qNewk8vVA
  iwIDAQAB
  -----END PUBLIC KEY-----';
  
   $pemPrivateKey = '-----BEGIN PRIVATE KEY-----
  MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/MnTtP9KJmxQ9
  8LjKbCMb9OpV07ThBlFQxyyYd5QbQFrBLGXCjP7RgPjxRkVjJN63Dd6ChqxB+S84
  8hQq6qqY8RfAaxWUtuSq8+yA0DYrpnJ7wSX0MSnzd6g+rKWilTQv3NKdCn1Vo2lK
  Cw6WW2vRFHKreryAElvs+TO4POZeuvkoS4aaQuY4TdMfQKT275zjETzuDezke1Dq
  4ZrqMHomihM3V50+6b6QEl0lqM5bkW858OcQdAGwpk93geJhw6Uztyu3Zj1ecFIE
  ghnW5HprhCz4Q/oLBzM8Dr8nlr4Y5X1yHXFkuxbkm47nmUIOnCu8qvtVWrBAbeo1
  7CTy9UCLAgMBAAECggEBAK1i7HZacmsnn2usaWfoOM6ZhAjhPB70w7klZmO9zSoJ
  akPUJ1QO2ObUtuzWdQY74VzPzwE/b+dEOnbB0Vg6Bws7V/a/JYr/cM829Tq7luRu
  xVNFDU4tZ4XK9WAg4PRXqkPdVYHkiVSoJEtpS4k+zr+Ec5jebSMXgxWbyDNDxwYP
  p6TenCVIhLGK3cR2uWADsXLAQQ5p5QMnpXDhr2m8cbe7496B4lTwe/gyjomzNutD
  ZnIQCfAY9r1r7U7ryT2eoNXmb9uDG+fqSaAvaB/kujOT6y1takSxf7Ij26dUL9iA
  7h59c2Ztu4PMrISV+04DGYfFs1MzYeBfoz7pxqHEHMECgYEA4IVY54trkJ5/8CId
  ad1s+bV3exNTJNgTAiqZE/a4eNnBzQD85SGbUAnk9PGzGvW9o3spQkcnJIqqDWJQ
  cOJlh8HQJqm/0pkWJKonoHUy05SleB67sZz97gAFj/NsPOSSQ6yMnf/pEeKwbrIa
  /fkOhdjAXk//WnECvo11o6MC7cUCgYEA2gEHoyRS5dbv+FtL1WFn0lNTlMl8tHz3
  fAdXuPi5dp3gPhqfxcP5n3QpT9Jc3rhQQaRswbKCjo2YAOhSdHR6nqYTyte+F+H2
  ImsqTGFlunIMpXmYK4ssOl00gnG+9cLHDNbHtjCb+oZy9sh8pZZniafSg0aYImo0
  VG4RGesbKg8CgYEAq1179vaV+gLP+ZPASX4k4A7ejAS68CMvlva2ceNc93iVEAiR
  /b0B0zxKEZ6tKoWn4bBuVFUEjkJ7+s0wQoi6H70RR4FGlNIdcYyhxDnPumf5R86F
  SdJeihpgJHgSBAQdkyOPDEU4OluAeGzeZzyCFizS3ulGKFybUJ+dy3DvGlUCgYBp
  KjwD8F7pL2G9/lS7z+xkovvb98Ln0q0UsPoZaisV1J07eF6A6cQ+rqvLLODOND3L
  HMW2PyYKHLYqIei88v/ADr/Xh3HVVZUGD4ptJEMNyTzeiqTkxJOGaDYPg02qgtbB
  E89tzU9BcKB++kJfIwo5drLvzxtO5srtu9cWGLuW8wKBgQCK0k/hYZyvB+9vELyH
  fNaVxj+jn5BWOmFtk6/TC/J5dQzldt7uyxkwoWOsJinpc0JByG9TKftaTEZI35xb
  tcNv214uLovTSNoxk2Yd++Ltg1O2vvjD39NXPIZH8et/unz9PEQXSJjO09Pi9AiH
  8a+VdAUhcHLNwqea8T6y5N9N9w==
  -----END PRIVATE KEY-----';
  
   $encrMessage = 'd14QunL/M8XwYvsogvjkExe24LP1aYY51OM3ACyl3xJam5DnhwBB4o+cf6/tRaBp+AzoZYQuemd7IP3NjYYEHj23DPaxDzoPNfHoWxNfKC9xqcgoLDywEjJvwtvNaJDAO+mGfNHfsi4TFtsSFRvJ8rkxNOYhoprD2XMIEeklSpFHC3V9hnadHunP+Vgwc5TNRCRPZ1AEcEiSlNmBkvd8pB+iMyAwA7P2tmamrpNQYbEjoQu0mCNPUVrft1QI1IS4XWAL4+HP2vBWV41AttL8XjFxicrR3mXXZVukwiu7PJFPjwW9cLGEgTMkcpBkPZoTGPefiCQYVh4LEq6fYb4kdw==';
  
      //just for testing if it works with the public/private keys supplied by javascript, which it does
   //$publicKey = openssl_pkey_get_public($pemPublicKey);
   //openssl_public_encrypt('mijn geheimpje',$encr,$publicKey,OPENSSL_PKCS1_OAEP_PADDING); 
   //$encr64 = base64_encode($encr); 
   
   $privateKey = openssl_get_privatekey($pemPrivateKey);
   if (!$privateKey) {
    echo "Cannot get private key";
   }
   
   $encr = base64_decode($encrMessage);
   
   $b = openssl_private_decrypt($encr,$decr,$privateKey,OPENSSL_PKCS1_OAEP_PADDING);
   if (!$b) {
    echo "Cannot decode message";
   }
   echo "String decrypt :". $decr;
  ?&gt;</code></pre>
  </div>
  </div>
  </p>