5

I exported a CryptoKey to PEM style and now I want to import it back. I generated my keys using the following code:

function generate() {
    return window.crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 2048, 
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {name: "SHA-256"}, 
    },
    true, 
    ["encrypt", "decrypt"] 
    ).then(function (key) {
        return key;
    })
    .catch(function (err) {
        console.error(err);
    });
 }

And I'm trying to import the private key which is string (pem style) using the next code:

function importPrivateKey(pemKey) {
return crypto.subtle.importKey("pkcs8", convertPemToBinary(pemKey), {name:"RSA-OAEP", hash:{name:"SHA-256"}}, true, ["encrypt", "decrypt"]);}

Unfortunately, it returns this error:

SyntaxError: Cannot create a key using the specified key usages.

UPDATE

convertPemToBinary function

function convertPemToBinary(pem) {
var lines = pem.split('\n');
var encoded = '';
for (var i = 0; i < lines.length; i++) {
    if (lines[i].trim().length > 0 &&
        lines[i].indexOf('-----BEGIN RSA PRIVATE KEY-----') < 0 &&
        lines[i].indexOf('-----BEGIN RSA PUBLIC KEY-----') < 0 &&
        lines[i].indexOf('-----BEGIN PUBLIC KEY-----') < 0 &&
        lines[i].indexOf('-----END PUBLIC KEY-----') < 0 &&
        lines[i].indexOf('-----BEGIN PRIVATE KEY-----') < 0 &&
        lines[i].indexOf('-----END PRIVATE KEY-----') < 0 &&
        lines[i].indexOf('-----END RSA PRIVATE KEY-----') < 0 &&
        lines[i].indexOf('-----END RSA PUBLIC KEY-----') < 0) {
        encoded += lines[i].trim();
    }
}
return base64StringToArrayBuffer(encoded);
}

Sub Functions used in convertPemToBinary function:

function base64StringToArrayBuffer(b64str) {
b64str = b64EncodeUnicode(b64str);
var byteStr = atob(b64str);
var bytes = new Uint8Array(byteStr.length);
for (var i = 0; i < byteStr.length; i++) {
    bytes[i] = byteStr.charCodeAt(i);
}
return bytes.buffer;
}


function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
        return String.fromCharCode('0x' + p1);
    }));
}
urb
  • 924
  • 1
  • 13
  • 28

1 Answers1

4

You can not encrypt with a RSA-OAEP private key. The issue is probably due to you have set encrypt tag in key usage when importing.

see webcrypto specification, section 22.4 https://w3c.github.io/webcrypto/Overview.html#rsa-oaep

If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.

UPDATED

The function base64StringToArrayBuffer is not correct

 b64str = b64EncodeUnicode(b64str);
 var byteStr = atob(b64str); 

PEM is base64 encoded, the function b64EncodeUnicode is encoding the content twice.

See my answer here https://stackoverflow.com/a/38714970/6371459 that contains a full example to generate RSA-OAEP key, export, encode to PEM, decode and import again (note: without using headers)

Replace these two lines with

function b64DecodeUnicode(str) {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}
Community
  • 1
  • 1
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Hmm, so should the key slot for private keys be decrypt? – urb Jan 08 '17 at 12:47
  • Yes, it is. Set key usage `[ "decrypt"]` – pedrofb Jan 08 '17 at 14:21
  • It returns Data Error. – urb Jan 08 '17 at 14:30
  • 1
    Have you checked that the previously exported PEM is correct? Then the issue should be in `convertPemToBinary(pemKey)`. Could you post the code to analyze it? – pedrofb Jan 08 '17 at 14:39
  • The error is here: `b64str = b64EncodeUnicode(b64str);var byteStr = atob(b64str);` PEM is base64 encoded, the function `b64EncodeUnicode`is encoding the content twice. See my answer here http://stackoverflow.com/a/38714970/6371459 Replace these two lines with `b64DecodeUnicode` . In fact, you could use almost all the code, It is a full example to generate RSA-OAEP, export encode to PEM ,decode and import (without using headers) – pedrofb Jan 08 '17 at 15:16