# Fernet.js Javascript implementation of Fernet symmetric encryption. Fernet is an opinionated way of using AES and HMAC authentication that makes shared-secret symmetric encryption simpler for communicating applications. Fernet.js uses browserify to provide a library that works in both node and the browser. Instead of using TypedArrays I use Hex Strings and CryptoJS's `Hex.parse` to build up `CryptoJs.lib.WordArray` objects. ## WARNING [It's generally *never* considered safe to encrypt data in the browser.](http://www.matasano.com/articles/javascript-cryptography/) However, you can use this library to encrypt/decrypt data server-side and decrypt data on a client. That being said, the only randomness used by this library without your control is a call to `crypto.randomBytes` to generate IVs. This function defaults to OpenSSL server-side and [browserify's random number generator implementation](https://github.com/crypto-browserify/crypto-browserify/blob/master/index.js) client-side. The browserify implementation only uses real browser crypto or throws an error. (IE: no calls to `Math.random()`) If you're planning on generating the secrets in the browser do yourself a favor and get an audit. ## Use ### node.js ```javascript var fernet = require('./fernet'); ``` ### browser ```html ``` ## Fernet ### fernet.setSecret(string) Sets the `secret` at the top level for all further Tokens made from this instance of Fernet. ### fernet.ttl = seconds Sets the `ttl` at the top level for all further Tokens made from this instance of Fernet. ## Secret ### Generating a secret Generating appropriate secrets is beyond the scope of `Fernet`, but you should generate it using `/dev/random` in a *nix. To generate a base64-encoded 256 bit (32 byte) random sequence, try: dd if=/dev/urandom bs=32 count=1 2>/dev/null | openssl base64 ### new fernet.Secret(string) ```javascript var secret = new fernet.Secret("cw_0x689RpI-jtRR7oE8h_eQsKImvJapLeSbXpwF4e4="); /* { signingKeyHex: '730ff4c7af3d46923e8ed451ee813c87', signingKey: [CryptoJS.lib.WordArray], encryptionKeyHex: 'f790b0a226bc96a92de49b5e9c05e1ee', encryptionKey: [CryptoJS.lib.WordArray] } */ ``` ## Token ## new fernet.Token(options) Options: - `secret`: a `fernet.Secret` object - `token`: a Fernet-encoded String - `ttl`: seconds of ttl For testing: - `time`: Date object - `iv`: Array of Integers ### Token.prototype.encode ```javascript //Have to include time and iv to make it deterministic. //Normally time would default to (new Date()) and iv to something random. var token = new fernet.Token({ secret: secret, time: Date.parse(1), iv: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] }) token.encode("Message") /* 'gAAAAABSO_yhAAECAwQFBgcICQoLDA0OD1PGoFV6wgWZG6AOBfQqevwJT2qKtCZ0EjKy1_TvyxTseR_3ebIF6Ph-xa2QT_tEvg==' */ ``` ### Token.prototype.decode Include tt ```javascript var token = new fernet.Token({ secret: secret, token: 'gAAAAABSO_yhAAECAwQFBgcICQoLDA0OD1PGoFV6wgWZG6AOBfQqevwJT2qKtCZ0EjKy1_TvyxTseR_3ebIF6Ph-xa2QT_tEvg==', ttl: 0 }) token.decode(); /* "Message" */ ``` ## Test > npm test Compiles new fernetBrowser.js via `browserify`, tests node lib with `mocha`, then opens test.html via `open`.