5

I'm using Web Crypto API and am generating RSA Keypair using generateKey function. Because of some bugs in my code, I have deleted public key for some users. I'm wondering if there is any way to generate public key out of private key? I know that it's easily doable for ssh keys. Here is my sample code for generating RSA key pair:

const generateRSAKeys = (): Promise<CryptoKeyPair> => {
    return crypto.subtle.generateKey(
    {
        name: 'RSA-OAEP',
        modulusLength: 2048
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: { name: 'SHA-512' },
    },
    true,
    ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'],
);
Mohammad Sheykholeslam
  • 1,379
  • 5
  • 18
  • 35
  • 1
    The public key consists essentially of the modulus and public exponent, both of which are also part of the private key. So yes, this is certainly possible (trivial, even). How to do it exactly depends on the format that the private key is stored in, and the format you need the public key to be in. – Peter Jun 28 '19 at 14:16
  • Nitpick: the public exponent is not part of the private key, but must formats include it for convenience (including the one in PKCS#1, so yeah, almost universal). – Maarten Bodewes Jul 01 '19 at 11:01

1 Answers1

5

You can do it by exporting private key and importing exported data like public data

const keys = await crypto.subtle.generateKey(
  {
    name: 'RSA-OAEP',
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: { name: 'SHA-512' },
  },
  true,
  ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'],
);

// export private key to JWK
const jwk = await crypto.subtle.exportKey("jwk", keys.privateKey);

// remove private data from JWK
delete jwk.d;
delete jwk.dp;
delete jwk.dq;
delete jwk.q;
delete jwk.qi;
jwk.key_ops = ["encrypt", "wrapKey"];

// import public key
const publicKey = await crypto.subtle.importKey("jwk", jwk, { name: "RSA-OAEP", 
hash: "SHA-512" }, true, ["encrypt", "wrapKey"]);

console.log(publicKey)

enter image description here

Microshine
  • 731
  • 5
  • 19
  • 4
    How can I adjust this for ECDSA? – jg6 Jun 12 '20 at 20:31
  • What if the private key is not extractable – Mohammed Abo-zaid Jun 28 '21 at 14:03
  • It's impossible to get public key data from an unextractable private key – Microshine Jul 22 '21 at 07:49
  • 1
    For ECDSA s. e.g. [here](https://stackoverflow.com/a/72153942/9014097). – Topaco May 07 '22 at 16:27
  • Side note: described tactic work if you get a private key for import, e. g. as PKCS8. First import arriving private key as extractable, export it as JWK, crop private fields, and than imprting resulting JWK as extractable public key with relevant usages, and import the incoming private key as usual. Then you can construct a CryptoKeyPair where final private key can even be marked as non-extractable, if you save these CryptoKeyPair instances in indexedDB for example. – Kote Isaev Aug 25 '23 at 14:08