@scft.dev/easycrypto
v1.0.1
Published
EasyCrypto is first part of the scft utils set. It is a lightweight TypeScript wrapper around the crypto package, exposing certain basic hashing and cryptographic functions in a simplified, easy to use manner. It's probably just meaningful for our ow
Downloads
12
Readme
EasyCrypto
EasyCrypto is first part of the scft utils set. It is a lightweight TypeScript wrapper around the crypto package, exposing certain basic hashing and cryptographic functions in a simplified, easy to use manner. It's probably just meaningful for our own internal projects, but if others find it useful, then that's excellent!
It allows for quick and easy encryption with or without a supplied passphrase, generating a random one if needed.
It will supply a hash of the supplied or generated passphrase (but will not supply a generated passphrase itself).
The hash, provided as a Buffer, can be used to generate a new KeyInfo object which will enable the successful
decryption of encrypted data.
The decryptor should be able to decrypt any data encrypted with supported algorithms/modes, but if the encrypted package does not include the authTag (for gcm) and iv in appropriate positions at the end of the stream, then they will need to be manually concatenated prior to to successful decryption.
[encrypted data {n bytes}] + [authTag {0-16 bytes}] + [iv {12-16 bytes}]
Primary Functionality
- Supports aes-256-cbc and aes-256-gcm algs/modes
- Generates a passphrase-based or randomized key hash
- Encrypts using cbc or gcm
- Decrypts using cbc or gcm respectively
- Concats iv (and authTag for gcm) to end of encrypted stream in third-party deconstructable manner.
- Derives iv (and authTag for gcm) from end of encrypted stream
- Hashes a given string
Notable Missing Functionality
- cbc mode does not support mac/hmac authentication (the original cbc functionality is left in for backwards compatibility with early use) (recommed using gcm with authTag rather than cbc for new use cases)
Example 1 - Defaults, Generated Secret
(No comments or outputs)
import { EasyCrypto } from "EasyCrypto";
// Encrypt Data
const msg = Buffer.from('A test string for gcm encryption.');
const ci = EasyCrypto.generateAESCipherInfo();
const encrypted = EasyCrypto.encryptWith.aes256gcm(ci, msg);
const keyBytes = EasyCrypto.exportKey(ci.keyInfo.key);
const keyString = keyBytes.toString('hex');
// Decrypt Data (using key generated above)
const keyString2 = keyString;
const keyBytes2 = Buffer.from(keyString2, 'hex');
const keyInfo = EasyCrypto.generateKeyInfo(EasyCrypto.default_ha, keyBytes2);
const ci2 = EasyCrypto.generateAESCipherInfo(EasyCrypto.default_ea, keyInfo);
const shared1 = EasyCrypto.decryptWith.aes256gcm(ci2, encrypted).toString();
(Comments and outputs)
import { EasyCrypto } from "EasyCrypto";
// Provide some data to be encrypted via a Buffer. User manages any string
// encoding options outside of EasyCrypto (which uses crypto defaults).
const msg = Buffer.from('A test string for gcm encryption.');
// You can generate a CipherInfo object from defaults, an exportable secret
// key object will be generated from a psuedo-randomized hash.
const ci = EasyCrypto.generateAESCipherInfo();
const encrypted = EasyCrypto.encryptWith.aes256gcm(ci, msg);
// That's it for encrypting, just need to grab a copy of that generated key.
const keyBytes = EasyCrypto.exportKey(ci.keyInfo.key);
const keyString = keyBytes.toString('hex');
// When we're ready to decrypt, we pretty much just run it backwards.
const keyString2 = keyString;
const keyBytes2 = Buffer.from(keyString2, 'hex');
const keyInfo = EasyCrypto.generateKeyInfo(EasyCrypto.default_ha, keyBytes2);
const ci2 = EasyCrypto.generateAESCipherInfo(EasyCrypto.default_ea, keyInfo);
const shared1 = EasyCrypto.decryptWith.aes256gcm(ci2, encrypted).toString();
console.log(`${ci.algorithm}\n` +
`${ci.period}\n` +
`${ci.keyInfo.hashAlgorithm}\n` +
`${EasyCrypto.exportKey(ci.keyInfo.key).toString('hex')}\n` +
`${ci.authTag?.toString('hex')}\n` +
`${ci.iv?.toString('hex')}`);
/* output:
aes-256-gcm
7889443200
sha256
2c7ed0f3786b17cd51e2b08235a4d60a702ff8ee55c64d51faddf94927a91ba3
e399315960282d752b2753c513e2db3f
34646561a82bc7f830a695d2
*/
console.log(keyString);
// output: 88cd39e3fc7183b5ecb85799ebfb6cad8070cf1bd56688e40a66c92d3ff0967c
console.log(keyInfo);
/* output:
{
hashAlgorithm: 'sha256',
key: SecretKeyObject [KeyObject] { [Symbol(kKeyType)]: 'secret' }
}
*/
console.log(`${ci2.algorithm}\n` +
`${ci2.period}\n` +
`${ci2.keyInfo.hashAlgorithm}\n` +
`${EasyCrypto.exportKey(ci2.keyInfo.key).toString('hex')}\n` +
`${ci2.authTag?.toString('hex')}\n` +
`${ci2.iv?.toString('hex')}`);
/* output
aes-256-gcm
7889443200
sha256
2c7ed0f3786b17cd51e2b08235a4d60a702ff8ee55c64d51faddf94927a91ba3
e399315960282d752b2753c513e2db3f
34646561a82bc7f830a695d2
*/
console.log(shared1);
// output: A test string for gcm encryption.
Example 2 - Customized Settings, Supplied Secret
(No comments or outputs)
import { EasyCrypto } from "EasyCrypto";
const eAlg = EasyCrypto.EncryptionAlgorithm.aes_256_gcm;
const hAlg = EasyCrypto.HashAlgorithm.sha256;
const message = Buffer.from('A test string for gcm encryption.');
const secret = 'S0M3-SH@R3D-S3CR3T-K3Y!';
const keyInfo1 = {key: secret, hashAlgorithm: EasyCrypto.HashAlgorithm.sha256};
const ci1 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo1);
const encrypted = EasyCrypto.encryptWith.aes256gcm(ci1, message);
const ci2 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo1);
const shared1 = EasyCrypto.decryptWith.aes256gcm(ci2, encrypted).toString();
const hashOfSecret1 = EasyCrypto.exportKey(ci1.keyInfo.key).toString('hex');
const hashedKey = Buffer.from(hashOfSecret1, 'hex');
const keyInfo3 = {key: hashedKey, hashAlgorithm: EasyCrypto.HashAlgorithm.sha256};
const ci3 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo3);
const shared2 = EasyCrypto.decryptWith.aes256gcm(ci3, encrypted).toString();
(Comments and outputs)
import { EasyCrypto } from "EasyCrypto";
const eAlg = EasyCrypto.EncryptionAlgorithm.aes_256_gcm;
const hAlg = EasyCrypto.HashAlgorithm.sha256;
const message = Buffer.from('A test string for gcm encryption.');
const secret = 'S0M3-SH@R3D-S3CR3T-K3Y!';
const keyInfo1 = {key: secret, hashAlgorithm: EasyCrypto.HashAlgorithm.sha256};
// Get a new CipherInfo object.
const ci1 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo1);
// It will populate the ci object's iv property.
// Since it's gcm, it will populate ci object's authTag property.
// Returned Buffer will have 12-byte iv and 16-byte authTag
// values appended to the end of the encrypted bytes Buffer.
const encrypted = EasyCrypto.encryptWith.aes256gcm(ci1, message);
// Use new CipherInfo object constructed with same secret to
// emulate running later on some other environment.
const ci2 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo1);
const shared1 = EasyCrypto.decryptWith.aes256gcm(ci2, encrypted).toString();
// Keep a copy of our hashed key to share
const hashOfSecret1 = EasyCrypto.exportKey(ci1.keyInfo.key).toString('hex');
const hashedKey = Buffer.from(hashOfSecret1, 'hex');
const keyInfo3 = {key: hashedKey, hashAlgorithm: EasyCrypto.HashAlgorithm.sha256};
const ci3 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo3);
const shared2 = EasyCrypto.decryptWith.aes256gcm(ci3, encrypted).toString();
// Try it again, make sure everything is staying reusable.
const hashOfSecret2 = EasyCrypto.exportKey(ci3.keyInfo.key).toString('hex');
const hashedKey2 = Buffer.from(hashOfSecret2, 'hex');
const keyInfo4 = {key: hashedKey2, hashAlgorithm: EasyCrypto.HashAlgorithm.sha256};
const ci4 = EasyCrypto.getAESCipherInfo(eAlg, keyInfo4);
const shared3 = EasyCrypto.decryptWith.aes256gcm(ci4, encrypted).toString();
console.log(encrypted.toString('base64'));
//output <like>: S0m3B4s3643nc0D3DV3rS10N0fTh33NcryPt3Dm3sS4g36i/730s7jc5mfsjRkZWHtHIkcF7LjCw==
console.log((ci2.keyInfo.key as crypto.KeyObject).export().toString('hex'));
//output:
console.log(shared1);
//output: A test string for gcm encryption.
console.log(EasyCrypto.exportKey(ci3.keyInfo.key).toString('hex'));
//output: 81bda621ea63758f98644aa7ee9550129f1d6933e6f812da856bbedb4da53a1c
console.log(shared2);
//output: A test string for gcm encryption.
console.log(EasyCrypto.exportKey(ci4.keyInfo.key).toString('hex'));
//output: 81bda621ea63758f98644aa7ee9550129f1d6933e6f812da856bbedb4da53a1c
console.log(shared3);
//output: A test string for gcm encryption.