Skip to content

Instantly share code, notes, and snippets.

@sitek94
Created February 9, 2024 21:51
Show Gist options
  • Save sitek94/7602f8384bd53e5b1e7348100c1b776e to your computer and use it in GitHub Desktop.
Save sitek94/7602f8384bd53e5b1e7348100c1b776e to your computer and use it in GitHub Desktop.
Web Crypto API Experiments
console.clear()
const PRIVATE_KEY_FORMAT = 'pkcs8'
const PUBLIC_KEY_FORMAT = 'spki'
const ENCRYPTION_ALGORITHM_NAME = 'RSA-OAEP'
const HASH_ALGORITHM_NAME = 'SHA-256'
const user = await generateKeyPair()
const leader = await generateKeyPair()
console.log('Generate key-pairs')
console.log({user, leader})
console.log('\n')
const symmetricKey = user.privateKey
const serializedSymmetricKey = await serialize(symmetricKey, 'pkcs8')
console.log('Serialize symmetric key')
console.log({serializedSymmetricKey})
console.log('\n')
const encryptedSymmetricKeyAsCiphertext = await encrypt(leader.publicKey)
console.log(`Encrypt symmetric key with leader's public key`)
console.log({encryptedSymmetricKeyAsCiphertext})
console.log('\n')
const encryptedSymmetricKeyAsString = await arrayBufferToBase64(encryptedSymmetricKeyAsCiphertext)
console.log(`Convert encrypted symmetric key from ciphertext to string`)
console.log({encryptedSymmetricKeyAsString})
console.log('\n')
const encryptedSymmetricConvertedBackToCiphertext = str2ab(encryptedSymmetricKeyAsString)
console.log(`Convert encrypted symmetric key back from string to ciphertext`)
console.log({encryptedSymmetricConvertedBackToCiphertext})
console.log('\n')
function decryptMessage(privateKey, ciphertext) {
return window.crypto.subtle.decrypt(
{ name: "RSA-OAEP" },
privateKey,
ciphertext,
);
}
function encrypt(publicKey, message) {
let encoded = getMessageEncoding(message);
return window.crypto.subtle.encrypt(
{
name: ENCRYPTION_ALGORITHM_NAME,
},
publicKey,
encoded,
);
}
function getMessageEncoding(message) {
let enc = new TextEncoder();
return enc.encode(message);
}
async function deserialize(keyAsBase64, type, usages) {
const binaryDerString = window.atob(keyAsBase64);
const binaryDer = str2ab(binaryDerString);
const imported = await window.crypto.subtle.importKey(
type,
binaryDer,
{
name: ENCRYPTION_ALGORITHM_NAME,
hash: "SHA-256",
},
true,
usages
);
return imported
}
async function serialize(cryptoKey, type) {
const exported = await window.crypto.subtle.exportKey(type, cryptoKey)
const exportedAsString = ab2str(exported);
const exportedAsBase64 = window.btoa(exportedAsString);
return exportedAsBase64
}
async function generateKeyPair() {
return window.crypto.subtle.generateKey(
{
name: ENCRYPTION_ALGORITHM_NAME,
modulusLength: 2048, // Can be 1024, 2048, or 4096
publicExponent: new Uint8Array([1, 0, 1]), // 24-bit representation of 65537
hash: HASH_ALGORITHM_NAME, // Can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
true, // whether the key is extractable (i.e., can be used in exportKey)
['encrypt', 'decrypt'], // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function arrayBufferToBase64(buffer) {
let binary = ''
const bytes = new Uint8Array(buffer)
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i])
}
return window.btoa(binary)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment