Created
February 9, 2024 21:51
-
-
Save sitek94/7602f8384bd53e5b1e7348100c1b776e to your computer and use it in GitHub Desktop.
Web Crypto API Experiments
This file contains 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
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