Created
September 3, 2025 14:02
-
-
Save FeernandoOFF/c18031b42f8eae8342856592cc1f4b69 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // First Attempt (throws DOMException [NotSupportedError]: Unable to import RSA key with format raw) | |
| const { subtle } = require('crypto').webcrypto; | |
| async function generateKey() { | |
| const algoritm = { name: "AES-CBC", length: 256 }; | |
| const exportable = true; | |
| const usage = ['encrypt', 'decrypt']; | |
| return await subtle.generateKey(algoritm, exportable, usage); | |
| } | |
| async function encryptAesKey(aesKey) { | |
| let rawRsaPublicKey = Buffer.from("-----BEGIN PUBLIC KEY-----.(KEY)..-----END PUBLIC KEY----", 'hex'); | |
| const format = "raw"; | |
| const exportable = false; | |
| const usage = ["wrapKey"]; | |
| let rsaPublicKey = await subtle.importKey(format, rawRsaPublicKey, { | |
| name : "RSASSA-PKCS1-v1_5", | |
| hash : "SHA-256" | |
| }, exportable, usage); | |
| let wrappedKey = await subtle.wrapKey(format, aesKey, rsaPublicKey, { name: "RSA-OAEP" }); | |
| return wrappedKey.toString('base64'); | |
| } | |
| const key = generateKey(); | |
| const encryptedKey = encryptAesKey(key); | |
| console.log(encryptedKey); | |
| // Second Attempt | |
| const {webcrypto} = require('crypto'); | |
| const {subtle} = webcrypto; | |
| function pemToDer(pem) { | |
| const b64 = pem | |
| .replace(/-----BEGIN PUBLIC KEY-----/g, '') | |
| .replace(/-----END PUBLIC KEY-----/g, '') | |
| .replace(/\s+/g, ''); | |
| return Buffer.from(b64, 'base64'); | |
| } | |
| async function generateAesKey() { | |
| return subtle.generateKey( | |
| {name: 'AES-CBC', length: 256}, | |
| /* extractable */ true, // must be true for wrapKey to export it | |
| ['encrypt', 'decrypt'] | |
| ); | |
| } | |
| async function importRsaOaepPublicKeyFromPem(pem) { | |
| const spkiDer = pemToDer(pem); | |
| return subtle.importKey( | |
| 'spki', | |
| spkiDer, // Buffer is fine (ArrayBufferView) | |
| { | |
| name: 'RSA-OAEP', | |
| hash: 'SHA-256', | |
| }, | |
| /* extractable */ false, | |
| ['wrapKey'] | |
| ); | |
| } | |
| async function wrapAesKeyWithRsaOaep(aesKey, rsaPublicKey) { | |
| const wrapped = await subtle.wrapKey( | |
| // Export format for the AES key being wrapped: | |
| 'raw', // could also use 'jwk' if you prefer | |
| aesKey, | |
| rsaPublicKey, | |
| {name: 'RSA-OAEP'} // OAEP with SHA-256 per the imported key | |
| ); | |
| return Buffer.from(new Uint8Array(wrapped)).toString('base64'); | |
| } | |
| // Example usage: | |
| (async () => { | |
| const rsaPublicKeyPem = ` | |
| -----BEGIN PUBLIC KEY----- | |
| (KEY) | |
| -----END PUBLIC KEY-----`.trim(); | |
| let aesKey = await generateAesKey(); | |
| const rsaPub = await importRsaOaepPublicKeyFromPem(rsaPublicKeyPem); | |
| let wrappedBase64 = await wrapAesKeyWithRsaOaep(aesKey, rsaPub); | |
| console.log('AES key:', aesKey); | |
| console.log('Wrapped AES key (base64):', wrappedBase64); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment