- Notifications
You must be signed in to change notification settings - Fork15
Webcrypto API wrapper for applications that store encrypted data
License
AKASHAorg/easy-web-crypto
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This is a wrapper around the WebCrypto API available in modern browsers. It enables fastdevelopment 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!
Enter this into your terminal with npm installed.
npm install --save easy-web-crypto
Either hostdist/web-crypto.js
yourself or use jsDelivr like this:
<scripttype="application/javascript"src="https://cdn.jsdelivr.net/npm/easy-web-crypto@1.4.0/dist/cjs/web-crypto.js"></script>
You can useglobalThis.WebCrypto
to access the API after installing.
Although this wrapper is compatible with SHA-1,we strongly recommendagainst using it in modern cryptographic applications unless absolutely necessary.
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 acceptsP-256
,P-384
, andP-521
(defaults toP-256
).
// Assuming you have loaded the easy-web-crypto library in your HTML fileconstWebCrypto=globalThis.WebCrypto// generate an ECDA P-256 key pairconstkeyPair=awaitWebCrypto.genKeyPair()
Export a public key using base64 format by default.ArrayBuffer
is also supported by passingan optional format parameter with the valueraw
.
constkeyPair=awaitWebCrypto.genKeyPair()constexportedPub=awaitWebCrypto.exportPublicKey(keyPair.publicKey)// console.log(exported) -> MFkwEwYHKoZ ... UmUXN7Q27txQ==// to export using raw formatconstexportedPub=awaitWebCrypto.exportPublicKey(keyPair.publicKey,'raw')
Export a private key using base64 format by default.ArrayBuffer
is also supported by passingan optional format parameter with the valueraw
.
constkeyPair=awaitWebCrypto.genKeyPair()constexportedPriv=awaitWebCrypto.exportPrivateKey(keyPair.privateKey)// console.log(exported) -> MFkwEwYHKoZ ... UmUXN7Q27txQ==// to export using raw formatconstexportedPriv=awaitWebCrypto.exportPrivateKey(keyPair.privateKey,'raw')
Import a public key using the base64 format by default. It supports the following optional parameters:namedCurve
that acceptsP-256
,P-384
, andP-521
(defaults toP-256
),format
that can bebase64
,hex
, andraw
for ArrayBuffer (defaults tobase64
).
// using the exported public key aboveconstimportedPub=awaitWebCrypto.importPublicKey(exportedPub)
Import a private key using the base64 format by default. It supports the following optional parameters:namedCurve
that acceptsP-256
,P-384
, andP-521
(defaults toP-256
),format
that can bebase64
,hex
, andraw
for ArrayBuffer (defaults tobase64
).
// using the exported private key aboveconstimportedPriv=awaitWebCrypto.importPrivateKey(exportedPriv)
Sign data using the private key. It supports the following optional parameters:format
,that can bebase64
,hex
, andraw
for ArrayBuffer (defaults tobase64
), andhash
thatcan be of typeSHA-1
,SHA-256
,SHA-384
, orSHA-512
(defaults toSHA-256
).
constdata={foo:'bar'}// generate keysconstkeys=awaitWebCrypto.genKeyPair()// signconstsig=awaitWebCrypto.sign(keys.privateKey,data)// console.log(sig) -> Cf51pRgxund ... Tvp7hYbiRQvnTnLZLpuw==
Verify a signature over some data using the private key. It supports the following optionalparameters:format
that can bebase64
,hex
, andraw
for ArrayBuffer (defaults tobase64
), andhash
that can be of typeSHA-1
,SHA-256
,SHA-384
, orSHA-512
(defaults toSHA-256
).
// using the signature we got aboveconstisValid=awaitWebCrypto.verify(keys.publicKey,data,sig)// console.log(isValid) -> true
Generates an AES key for encryption. By default this key can be exported. It supports thefollowing optional parameters:extractable
(defaults to true),mode
(defaults to AES-GCM), andkeySize
with a length of128
,192
, or256
(defaults to128
).
// genAESKey(extractable, mode = 'AES-GCM', keySize = 128)constkey=awaitWebCrypto.genAESKey()
Encrypt a String|Object using an AES key.
constdata={foo:'bar'}// using the key generated aboveconstencrypted=awaitWebCrypto.encrypt(key,data)
Decrypt an encrypted String|Object using an AES key.
constval=awaitWebCrypto.decrypt(key,encrypted)console.log(val)// { foo: 'bar' }
Encrypt an ArrayBuffer using an AES key.
constbuffer=newArrayBuffer(8)// using the key generated aboveconstencrypted=WebCrypto.encryptBuffer(key,buffer)
Dncrypt an ArrayBuffer using an AES key.
WebCrypto.decryptBuffer(key,encrypted).then(val=>console.log(val))// ArrayBuffer {}
Export an AES key into a raw|JWK key (defaults to raw) that can be stored.
constexported=WebCrypto.exportKey(key)
Imports an AES key. It accepts the following optional parameters:type
(defaultsto raw),mode
(defaults to AES-GCM).
// importKey(key, type = 'raw', mode = 'AES-GCM')constkey=WebCrypto.importKey(key)// use this AES key now to encrypt/decrypt as above
UsesPBKDF2
to derive a Key Encryption Key from a passphrase, in order to generate an encryptedAES 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!
// genEncryptedMasterKey(passPhrase, salt = genRandomBuffer(16), iterations = 100000, hashAlgo = 'SHA-256')constpassphrase='your super secure passphrase'constencMasterKey=awaitWebCrypto.genEncryptedMasterKey(passphrase)// you can now safely store the encMasterKey for future use
Decrypt a master key by deriving the encryption key from the provided passphrase and encryptedmaster key.
// use the values from genEncryptedMasterKey exampleconstkey=awaitWebCrypto.decryptMasterKey(passphrase,encMasterKey)// use this AES key now to encrypt/decrypt your data
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 stilldecrypt previously encrypted data. Only the passphrase that is used to encrypt the AES keychanges!
// use the values from genEncryptedMasterKey example + the new passphraseconstnewPassphrase='something different from the last passphrase'// updatePassphraseKey(oldassphrase, newPassphrase, oldEncryptedMasterKey)constupdatedEncMK=awaitWebCrypto.updatePassphraseKey(passphrase,newPassphrase,encMasterKey)// you can now safely store the updatedEncMK for future use
Generate the hash of a string or ArrayBuffer. It accepts the following optional parameters:outputFormat
(defaults to hex), andname
(defaults to SHA-256 but also supports SHA-1, SHA-384, and SHA-512 algorithms).
// hash(data, outputFormat = 'hex', name = 'SHA-256')consthashed=awaitWebCrypto.hash('abc123')console.log(hashed)// 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
Generate a random secure hexadecimal ID based on the provided length. Defaults to a length of 16.
constrandomId=WebCrypto.genId(32)console.log(randomId)// a6d2a143edb8b521645bf5d39c29e401
That's it!
constWebCrypto=require('easy-web-crypto')// generate a new ECDA key pairconstkeyPair=awaitWebCrypto.genKeyPair()// sign some dataconstdata={foo:'bar'}constsig=awaitWebCrypto.sign(keyPair.privateKey,data)// check signatureconstisValid=awaitWebCrypto.verify(keyPair.publicKey,data,sig)console.log(isValid)// -> true// EXPORT// export public keyconstexportedPub=awaitWebCrypto.exportPublicKey(keyPair.publicKey)// export private keyconstexportedPriv=awaitWebCrypto.exportPrivateKey(keyPair.privateKey)// IMPORT// import public keyconstpubKey=awaitWebCrypto.importPublicKey(exportedPub)// import private keyconstprivKey=awaitWebCrypto.importPrivateKey(exportedPriv)// sign some data using imported keysconstdata={foo:'bar'}constsig=awaitWebCrypto.sign(privKey,data)// check signatureconstisValid=awaitWebCrypto.verify(pubKey,data,sig)console.log(isValid)// -> true
constWebCrypto=require('easy-web-crypto')constpassphrase='your super secure passphrase'// derive a new key from passphrase and generate the master AES key// (you can now store this encrypted key for later use)constencMasterKey=awaitWebCrypto.genEncryptedMasterKey(passphrase)// decrypt the (stored) AES key to be able to encrypt/decrypt dataletkey=awaitWebCrypto.decryptMasterKey(passphrase,encMasterKey)// encrypt some dataconstdata={foo:'bar'}// use the decrypted AES key from aboveconstencrypted=awaitWebCrypto.encrypt(key,data)// decrypt the data we just encryptedletval=awaitWebCrypto.decrypt(key,encrypted)console.log(val)// { foo: 'bar' }// change passphraseconstnewPassphrase='something different from the last passphrase'// updated the encrypted master key (for security reasons you should always// rotate keys after a certain period of time)constupdatedEncMasterKey=awaitWebCrypto.updatePassphraseKey(passphrase,newPassphrase,encMasterKey)// decrypt new master keykey=awaitWebCrypto.decryptMasterKey(newPassphrase,updatedEncMasterKey)// decrypt the previous dataval=awaitWebCrypto.decrypt(key,encrypted)console.log(val)// { foo: 'bar' }
About
Webcrypto API wrapper for applications that store encrypted data