const operations = crypto.subtle
var iv = crypto.getRandomValues(new Uint8Array(24))

function stringToArrayBuffer(str) {
    var buf = new ArrayBuffer(str.length);
    var bufView = new Uint8Array(buf);
    for (var i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}


function arrayBufferToString(str) {
    var byteArray = new Uint8Array(str);
    var byteString = '';
    for (var i = 0; i < byteArray.byteLength; i++) {
        byteString += String.fromCodePoint(byteArray[i]);
    }
    return byteString;
}


const encoder = new TextEncoder();
const passwordAsKeyData = encoder.encode('superSecretPassword');

const keyFromPassword = await operations.importKey(
  "raw",
  passwordAsKeyData,
  "PBKDF2",
  false,
  ["deriveKey"]
)

const aes = await operations.deriveKey(
    {
        name: "PBKDF2",
        salt: stringToArrayBuffer("salt"),
        iterations: 250000,
        hash: "SHA-256",
    },
    keyFromPassword,                       
    {
        name: "AES-GCM",
        length: 256
    },
    true,
    ["wrapKey", "unwrapKey"]
)

var keyPair = await crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 4096,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: "SHA-256",
    },
    true,
    ["encrypt", "decrypt"]
)

var wrappedRSAKey = await crypto.subtle.wrapKey(
    "jwk",
    keyPair.privateKey,
    aes, 
    {name: "AES-GCM", iv: iv}
)

const kk = btoa(arrayBufferToString(wrappedRSAKey))
const siv = btoa(arrayBufferToString(iv))

console.log(wrappedRSAKey)
console.log('wrapped key:', kk)
console.log('iv:', siv)

console.log("=================================")
console.log("=================================")
console.log("=================================")

var unwrapped = await crypto.subtle.unwrapKey(
    "jwk",
    stringToArrayBuffer(atob(kk)),
    aes,
    {name: "AES-GCM", iv: stringToArrayBuffer(atob(siv))},
    {
        name: "RSA-OAEP",
        hash: "SHA-256",
    },
    true,
    ["decrypt"]
)

console.log(unwrapped)

const enc = await operations.encrypt(
    { name: "RSA-OAEP" },
    keyPair.publicKey,
    stringToArrayBuffer("asd"),
)

console.log(btoa(arrayBufferToString(enc)))

const dec = await operations.decrypt(
    { name: "RSA-OAEP" },
    unwrapped,
    enc,
)

console.log(arrayBufferToString(dec))
