Advertisement
Guest User

Untitled

a guest
Apr 25th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.72 KB | None | 0 0
  1. /**
  2. * Encrypts plaintext using AES-GCM with supplied password, for decryption with aesGcmDecrypt().
  3. * (c) Chris Veness MIT Licence
  4. *
  5. * @param {String} plaintext - Plaintext to be encrypted.
  6. * @param {String} password - Password to use to encrypt plaintext.
  7. * @returns {String} Encrypted ciphertext.
  8. *
  9. * @example
  10. * const ciphertext = await aesGcmEncrypt('my secret text', 'pw');
  11. * aesGcmEncrypt('my secret text', 'pw').then(function(ciphertext) { console.log(ciphertext); });
  12. */
  13. async function aesGcmEncrypt(plaintext, password) {
  14. const pwUtf8 = new TextEncoder().encode(password); // encode password as UTF-8
  15. const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8); // hash the password
  16.  
  17. const iv = crypto.getRandomValues(new Uint8Array(12)); // get 96-bit random iv
  18.  
  19. const alg = { name: 'AES-GCM', iv: iv }; // specify algorithm to use
  20.  
  21. const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['encrypt']); // generate key from pw
  22.  
  23. const ptUint8 = new TextEncoder().encode(plaintext); // encode plaintext as UTF-8
  24. const ctBuffer = await crypto.subtle.encrypt(alg, key, ptUint8); // encrypt plaintext using key
  25.  
  26. const ctArray = Array.from(new Uint8Array(ctBuffer)); // ciphertext as byte array
  27. const ctStr = ctArray.map(byte => String.fromCharCode(byte)).join(''); // ciphertext as string
  28. const ctBase64 = btoa(ctStr); // encode ciphertext as base64
  29.  
  30. const ivHex = Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join(''); // iv as hex string
  31.  
  32. return ivHex+ctBase64; // return iv+ciphertext
  33. }
  34.  
  35.  
  36. /**
  37. * Decrypts ciphertext encrypted with aesGcmEncrypt() using supplied password.
  38. * (c) Chris Veness MIT Licence
  39. *
  40. * @param {String} ciphertext - Ciphertext to be decrypted.
  41. * @param {String} password - Password to use to decrypt ciphertext.
  42. * @returns {String} Decrypted plaintext.
  43. *
  44. * @example
  45. * const plaintext = await aesGcmDecrypt(ciphertext, 'pw');
  46. * aesGcmDecrypt(ciphertext, 'pw').then(function(plaintext) { console.log(plaintext); });
  47. */
  48. async function aesGcmDecrypt(ciphertext, password) {
  49. const pwUtf8 = new TextEncoder().encode(password); // encode password as UTF-8
  50. const pwHash = await crypto.subtle.digest('SHA-256', pwUtf8); // hash the password
  51.  
  52. const iv = ciphertext.slice(0,24).match(/.{2}/g).map(byte => parseInt(byte, 16)); // get iv from ciphertext
  53.  
  54. const alg = { name: 'AES-GCM', iv: new Uint8Array(iv) }; // specify algorithm to use
  55.  
  56. const key = await crypto.subtle.importKey('raw', pwHash, alg, false, ['decrypt']); // use pw to generate key
  57.  
  58. const ctStr = atob(ciphertext.slice(24)); // decode base64 ciphertext
  59. const ctUint8 = new Uint8Array(ctStr.match(/[\s\S]/g).map(ch => ch.charCodeAt(0))); // ciphertext as Uint8Array
  60. // note: why doesn't ctUint8 = new TextEncoder().encode(ctStr) work?
  61.  
  62. const plainBuffer = await crypto.subtle.decrypt(alg, key, ctUint8); // decrypt ciphertext using key
  63. const plaintext = new TextDecoder().decode(plainBuffer); // decode password from UTF-8
  64.  
  65. return plaintext; // return the plaintext
  66. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement