项目作者: AKASHAorg

项目描述 :
Webcrypto API wrapper for applications that store encrypted data
高级语言: JavaScript
项目地址: git://github.com/AKASHAorg/easy-web-crypto.git
创建时间: 2019-08-29T07:40:50Z
项目社区:https://github.com/AKASHAorg/easy-web-crypto

开源协议:MIT License

下载


Easy-web-crypto

Build Status

This is a wrapper around the WebCrypto API available in modern browsers. It enables fast
development of applications that require storing as well as signing and verifying data.
It is well tested and it comes with no external dependencies.

Huge thanks to @Jopie64 for Typescriptifying the source!

Installing

via npm

Enter this into your terminal with npm installed.

  1. npm install --save easy-web-crypto

via <script> tag

Either host dist/web-crypto.js yourself or use jsDelivr like this:

  1. <script type="application/javascript" src="https://cdn.jsdelivr.net/npm/easy-web-crypto@1.4.0/dist/cjs/web-crypto.js"></script>

You can use globalThis.WebCrypto to access the API after installing.

Usage

Sidenote

Although this wrapper is compatible with SHA-1,
we strongly recommend against using it in modern cryptographic applications unless absolutely necessary.

ECDA public key

genKeyPair

Generates an ECDA key pair for signing and verifying. By default this key can be exported.
It supports the following optional parameters: extractable (defaults to true), namedCurve
that accepts P-256, P-384, and P-521 (defaults to P-256).

  1. // Assuming you have loaded the easy-web-crypto library in your HTML file
  2. const WebCrypto = globalThis.WebCrypto
  3. // generate an ECDA P-256 key pair
  4. const keyPair = await WebCrypto.genKeyPair()

exportPublicKey

Export a public key using base64 format by default. ArrayBuffer is also supported by passing
an optional format parameter with the value raw.

  1. const keyPair = await WebCrypto.genKeyPair()
  2. const exportedPub = await WebCrypto.exportPublicKey(keyPair.publicKey)
  3. // console.log(exported) -> MFkwEwYHKoZ ... UmUXN7Q27txQ==
  4. // to export using raw format
  5. const exportedPub = await WebCrypto.exportPublicKey(keyPair.publicKey, 'raw')

exportPrivateKey

Export a private key using base64 format by default. ArrayBuffer is also supported by passing
an optional format parameter with the value raw.

  1. const keyPair = await WebCrypto.genKeyPair()
  2. const exportedPriv = await WebCrypto.exportPrivateKey(keyPair.privateKey)
  3. // console.log(exported) -> MFkwEwYHKoZ ... UmUXN7Q27txQ==
  4. // to export using raw format
  5. const exportedPriv = await WebCrypto.exportPrivateKey(keyPair.privateKey, 'raw')

importPublicKey

Import a public key using the base64 format by default. It supports the following optional parameters: namedCurve that accepts P-256, P-384, and P-521 (defaults to P-256),
format that can be base64, hex, and raw for ArrayBuffer (defaults to base64).

  1. // using the exported public key above
  2. const importedPub = await WebCrypto.importPublicKey(exportedPub)

importPrivateKey

Import a private key using the base64 format by default. It supports the following optional parameters: namedCurve that accepts P-256, P-384, and P-521 (defaults to P-256),
format that can be base64, hex, and raw for ArrayBuffer (defaults to base64).

  1. // using the exported private key above
  2. const importedPriv = await WebCrypto.importPrivateKey(exportedPriv)

sign

Sign data using the private key. It supports the following optional parameters: format,
that can be base64, hex, and raw for ArrayBuffer (defaults to base64), and hash that
can be of type SHA-1, SHA-256, SHA-384, or SHA-512 (defaults to SHA-256).

  1. const data = { foo: 'bar' }
  2. // generate keys
  3. const keys = await WebCrypto.genKeyPair()
  4. // sign
  5. const sig = await WebCrypto.sign(keys.privateKey, data)
  6. // console.log(sig) -> Cf51pRgxund ... Tvp7hYbiRQvnTnLZLpuw==

verify

Verify a signature over some data using the private key. It supports the following optional
parameters: format that can be base64, hex, and raw for ArrayBuffer (defaults to
base64), and hash that can be of type SHA-1, SHA-256, SHA-384, or SHA-512
(defaults to SHA-256).

  1. // using the signature we got above
  2. const isValid = await WebCrypto.verify(keys.publicKey, data, sig)
  3. // console.log(isValid) -> true

AES

genAESKey

Generates an AES key for encryption. By default this key can be exported. It supports the
following optional parameters: extractable (defaults to true), mode (defaults to AES-GCM), and
keySize with a length of 128, 192, or 256 (defaults to 128).

  1. // genAESKey(extractable, mode = 'AES-GCM', keySize = 128)
  2. const key = await WebCrypto.genAESKey()

encrypt

Encrypt a String|Object using an AES key.

  1. const data = { foo: 'bar' }
  2. // using the key generated above
  3. const encrypted = await WebCrypto.encrypt(key, data)

decrypt

Decrypt an encrypted String|Object using an AES key.

  1. const val = await WebCrypto.decrypt(key, encrypted)
  2. console.log(val) // { foo: 'bar' }

encryptBuffer

Encrypt an ArrayBuffer using an AES key.

  1. const buffer = new ArrayBuffer(8)
  2. // using the key generated above
  3. const encrypted = WebCrypto.encryptBuffer(key, buffer)

decryptBuffer

Dncrypt an ArrayBuffer using an AES key.

  1. WebCrypto.decryptBuffer(key, encrypted).then(val => console.log(val)) // ArrayBuffer {}

exportKey

Export an AES key into a raw|JWK key (defaults to raw) that can be stored.

  1. const exported = WebCrypto.exportKey(key)

importKey

Imports an AES key. It accepts the following optional parameters: type (defaults
to raw), mode (defaults to AES-GCM).

  1. // importKey(key, type = 'raw', mode = 'AES-GCM')
  2. const key = WebCrypto.importKey(key)
  3. // use this AES key now to encrypt/decrypt as above

Passphrase-based key derivation

genEncryptedMasterKey

Uses PBKDF2 to derive a Key Encryption Key from a passphrase, in order to generate an encrypted
AES symmetric key that can be safely stored. It accepts the following optional parameters:
salt (defaults to a random ArrayBuffer(16)), iterations (defaults to 10000), hashAlgo
(defaults to SHA-256).

Please make sure you use a sufficiently secure passphrase as well as a minimum of 10000 iterations!

  1. // genEncryptedMasterKey(passPhrase, salt = genRandomBuffer(16), iterations = 100000, hashAlgo = 'SHA-256')
  2. const passphrase = 'your super secure passphrase'
  3. const encMasterKey = await WebCrypto.genEncryptedMasterKey(passphrase)
  4. // you can now safely store the encMasterKey for future use

decryptMasterKey

Decrypt a master key by deriving the encryption key from the provided passphrase and encrypted
master key.

  1. // use the values from genEncryptedMasterKey example
  2. const key = await WebCrypto.decryptMasterKey(passphrase, encMasterKey)
  3. // use this AES key now to encrypt/decrypt your data

updatePassphraseKey

Update the derived key encryption key (KEK) based on the new passphrase.

Please note that the actual AES key used for encryption does not change, so you can still
decrypt previously encrypted data. Only the passphrase that is used to encrypt the AES key
changes!

  1. // use the values from genEncryptedMasterKey example + the new passphrase
  2. const newPassphrase = 'something different from the last passphrase'
  3. // updatePassphraseKey(oldassphrase, newPassphrase, oldEncryptedMasterKey)
  4. const updatedEncMK = await WebCrypto.updatePassphraseKey(passphrase, newPassphrase, encMasterKey)
  5. // you can now safely store the updatedEncMK for future use

Utility

hash

Generate the hash of a string or ArrayBuffer. It accepts the following optional parameters:
outputFormat (defaults to hex), and name (defaults to SHA-256 but also supports SHA-1, SHA-384, and SHA-512 algorithms).

  1. // hash(data, outputFormat = 'hex', name = 'SHA-256')
  2. const hashed = await WebCrypto.hash('abc123')
  3. console.log(hashed)
  4. // 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090

genId

Generate a random secure hexadecimal ID based on the provided length. Defaults to a length of 16.

  1. const randomId = WebCrypto.genId(32)
  2. console.log(randomId) // a6d2a143edb8b521645bf5d39c29e401

That’s it!

Full example for signing / verifying data

  1. const WebCrypto = require('easy-web-crypto')
  2. // generate a new ECDA key pair
  3. const keyPair = await WebCrypto.genKeyPair()
  4. // sign some data
  5. const data = { foo: 'bar' }
  6. const sig = await WebCrypto.sign(keyPair.privateKey, data)
  7. // check signature
  8. const isValid = await WebCrypto.verify(keyPair.publicKey, data, sig)
  9. console.log(isValid) // -> true
  10. // EXPORT
  11. // export public key
  12. const exportedPub = await WebCrypto.exportPublicKey(keyPair.publicKey)
  13. // export private key
  14. const exportedPriv = await WebCrypto.exportPrivateKey(keyPair.privateKey)
  15. // IMPORT
  16. // import public key
  17. const pubKey = await WebCrypto.importPublicKey(exportedPub)
  18. // import private key
  19. const privKey = await WebCrypto.importPrivateKey(exportedPriv)
  20. // sign some data using imported keys
  21. const data = { foo: 'bar' }
  22. const sig = await WebCrypto.sign(privKey, data)
  23. // check signature
  24. const isValid = await WebCrypto.verify(pubKey, data, sig)
  25. console.log(isValid) // -> true

Full example for encrypting / decrypting data

  1. const WebCrypto = require('easy-web-crypto')
  2. const passphrase = 'your super secure passphrase'
  3. // derive a new key from passphrase and generate the master AES key
  4. // (you can now store this encrypted key for later use)
  5. const encMasterKey = await WebCrypto.genEncryptedMasterKey(passphrase)
  6. // decrypt the (stored) AES key to be able to encrypt/decrypt data
  7. let key = await WebCrypto.decryptMasterKey(passphrase, encMasterKey)
  8. // encrypt some data
  9. const data = { foo: 'bar' }
  10. // use the decrypted AES key from above
  11. const encrypted = await WebCrypto.encrypt(key, data)
  12. // decrypt the data we just encrypted
  13. let val = await WebCrypto.decrypt(key, encrypted)
  14. console.log(val) // { foo: 'bar' }
  15. // change passphrase
  16. const newPassphrase = 'something different from the last passphrase'
  17. // updated the encrypted master key (for security reasons you should always
  18. // rotate keys after a certain period of time)
  19. const updatedEncMasterKey = await WebCrypto.updatePassphraseKey(passphrase,
  20. newPassphrase, encMasterKey)
  21. // decrypt new master key
  22. key = await WebCrypto.decryptMasterKey(newPassphrase, updatedEncMasterKey)
  23. // decrypt the previous data
  24. val = await WebCrypto.decrypt(key, encrypted)
  25. console.log(val) // { foo: 'bar' }