Created
September 10, 2023 16:57
-
-
Save Elanza-48/7328b89a965ab9b871728b16b66b2522 to your computer and use it in GitHub Desktop.
Web Crypto Lib for message (object) encryption & decryption using string key using AES.
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
'use strict'; | |
class CryptLib { | |
constructor() {} | |
async arrayBufferToHexString(buffer) { | |
if (!(buffer instanceof ArrayBuffer)) throw "not an ArrayBuffer !"; | |
let view = new DataView(buffer); | |
let hexString = ''; | |
for (let i = 0; i < view.byteLength; i++) { | |
const hexByte = view.getUint8(i).toString(16).padStart(2, '0'); | |
hexString += hexByte; | |
} | |
return hexString; | |
} | |
async hexStringToArrayBuffer(hexString) { | |
if(typeof hexString !== 'string') throw "not a string !"; | |
let buffer = new ArrayBuffer(hexString.length / 2); | |
let view = new DataView(buffer); | |
for (let i = 0; i < hexString.length; i += 2) { | |
const byte = parseInt(hexString.substr(i, 2), 16); | |
view.setUint8(i / 2, byte); | |
} | |
return buffer; | |
} | |
async getHashSha256String(str) { | |
if (!str) { | |
throw 'needs key'; | |
} | |
let digest = ''; | |
try { | |
const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(str)); | |
digest = await this.arrayBufferToHexString(buffer); | |
} catch (e) { | |
console.error(e); | |
} | |
return digest; | |
} | |
async getHashSha512String(str) { | |
if (!str) { | |
throw 'needs key'; | |
} | |
let digest = ''; | |
try { | |
const buffer = await crypto.subtle.digest("SHA-512", new TextEncoder().encode(str)); | |
digest = await this.arrayBufferToHexString(buffer); | |
} catch (e) { | |
console.error(e); | |
} | |
return digest; | |
} | |
async derivePBKDF2(keyString){ | |
let key = null; | |
try{ | |
key = await window.crypto.subtle.importKey( | |
"raw", | |
new TextEncoder().encode(keyString), | |
{"name": "PBKDF2"}, | |
false, | |
["deriveKey"], | |
); | |
} catch (e){ | |
console.error(e); | |
} | |
return key; | |
} | |
async deriveAESCryptoKeyFromPBKDF2(importedKey, salt){ | |
let key = null; | |
try{ | |
key = await window.crypto.subtle.deriveKey( | |
{ | |
name: "PBKDF2", | |
salt: new TextEncoder().encode(salt), | |
iterations: 120000, | |
hash: "SHA-512" | |
}, | |
importedKey, | |
{ | |
name: "AES-GCM", | |
length: 128 | |
}, | |
false, | |
["encrypt", "decrypt"] | |
); | |
} catch (e){ | |
console.error(e); | |
} | |
return key; | |
} | |
async encryptPlainTextWithRandomIV(plainText, keyString) { | |
const enc = new TextEncoder(); | |
const encoded = enc.encode(plainText); | |
// nonce length is 64; | |
const nonce = await this.getHashSha256String(keyString); | |
let key = await this.derivePBKDF2(keyString); | |
key = await this.deriveAESCryptoKeyFromPBKDF2(key, nonce); | |
let cipher = ""; | |
try { | |
let buffer = await window.crypto.subtle.encrypt( | |
{ | |
name: "AES-GCM", | |
length: 128, | |
iv: new TextEncoder().encode(nonce), | |
}, | |
key, | |
encoded, | |
); | |
cipher = await this.arrayBufferToHexString(buffer); | |
} catch (e){ | |
console.error(e); | |
} | |
return cipher; | |
} | |
async decryptCipherTextWithRandomIV(cipherText, keyString) { | |
const buffer = await this.hexStringToArrayBuffer(cipherText); | |
const nonce = await this.getHashSha256String(keyString); | |
let key = await this.derivePBKDF2(keyString); | |
key = await this.deriveAESCryptoKeyFromPBKDF2(key, nonce); | |
let data = null; | |
try { | |
const cipher = await window.crypto.subtle.decrypt( | |
{ | |
name: "AES-GCM", | |
length: 128, | |
iv: new TextEncoder().encode(nonce), | |
}, | |
key, | |
buffer, | |
); | |
const dec = new TextDecoder(); | |
data = dec.decode(cipher); | |
} catch (e){ | |
console.error(e); | |
} | |
return data; | |
} | |
} | |
const cryptLib = new CryptLib(); | |
export default cryptLib; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
📌 Anyone can directly test this code in browser console.