GithubHelp home page GithubHelp logo

csquared / fernet.js Goto Github PK

View Code? Open in Web Editor NEW
72.0 3.0 31.0 240 KB

Javascript implementation of Fernet symmetric encryption https://github.com/kr/fernet-spec

License: MIT License

JavaScript 99.81% HTML 0.19%

fernet.js's Introduction

Fernet.js

ci status

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.

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 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

var fernet = require('./fernet');

browser

<script src="fernetBrowser.js"></script>

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)

  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

//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

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.

fernet.js's People

Contributors

cgamesplay avatar csquared avatar dependabot[bot] avatar entequak avatar kennyp avatar robertjkeck2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fernet.js's Issues

Use with Node streams

I have a project where I want to encrypt a streaming input to a streaming output, without having to hold the entire large buffer in memory at any given time. I noticed that this fernet library does not seem to support this currently (though please correct me if I am wrong on this).

I plan to hack together a solution that uses this library as much as possible, but does support streaming encryption. If I do so, are you interested in considering such a feature for merging back into the main library?

If so, I can try to put together a pull request for it. If not, I'll save my time and just get my own application working.

Invalid Token: TTL

Hi,
First, thanks for your work releasing this lib.

I have a problem when decoding, it work for a few minutes (not exactly sure how much) but then after a while I got an TTL error. I am decoding a password multiple time so it may be the cause?

Here is my code :

let fernet_secret = new fernet.Secret(decryption_key),
        token = new fernet.Token({
            secret: fernet_secret,
            token: encrypted_password,
            ttl: ttl
        });

(at first I didn't set the ttl but I did it to test)
Here is the console log of the token after I created it :

token :  { secret:
   Secret {
     signingKeyHex: '22ed0b5d53898da008764e3351446b82',
     signingKey: { words: [Array], sigBytes: 16 },
     encryptionKeyHex: 'b74e36fa19fb0e1b3d87f7a36367c839',
     encryptionKey: { words: [Array], sigBytes: 16 } },
  ttl: 1652,
  message: undefined,
  cipherText: undefined,
  token: 'gAAAAABcRvXJncYHU1x5WsOQdoq0F5b5x0bAonutMiDqxS7IbZHBHUGWt3BukIhSAZp8tzfzMSRcUJMvjHiM_e-8hrViBYFrFw==',
  version: 128,
  optsIV: undefined,
  maxClockSkew: 60,
  time: { words: [ 0, 1548156260 ], sigBytes: 8 } }

And here is the error on the decode:

Error: Invalid Token: TTL
    at Token.decodeToken [as decode] (/project/node_modules/fernet/lib/token.js:65:15)
    at decrypt (/project/dist/functions.js:123:18)
    at Object.exports.get_password (/project/dist/functions.js:171:40)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:118:7)
/project/node_modules/fernet/lib/token.js:6

Can you tell me more about the ttl? What is it's purpose? The duration of the validity for the Token just created? The duration for a password to be decoded? (which is why I tried to add the TTL manually, same TTL as the one I choose for this password).

Cheer

Malformed utf-8 error thrown when decrypting large tokens encrypted in Python

I encrypted some data using Fernet from Cryptography Python package. I was able to decrypt some short messages, but for larger messages I got a "Error: Malformed UTF-8 data" error raised from Object.stringify in crypto-js core.js.

As a workaround I had to abandon the fernet.js library and wrote a decrypt function myself. Its totally untested, but seems to decrypt. I tried to follow the pattern outlined in Python's implementation. For anyone else working around the same issue here is a gist with my node Fernet decrypt function

Typescript type definitions

Are you interested in a contribution to add an index.d.ts to this package to include Typescript types, so that Typescript users can use your library out of the box?

If so, I can try to contribute some Typescript definitions back here after I write them.

Improvement: use non-blocking version of `randomBytes`

Hello there

I audited the code because the interface is weird; generally, generating a secure random in javascript is a blocking operation, and fernet.js generate IVs without exposing the async interface.

Turns out you are using the blocking version of randomBytes (https://github.com/csquared/fernet.js/blob/2eaa1c/fernet.js#L49).

Consider switching to the promisified version.

const asyncRandomBytes = promisify(randomBytes); // declaration
await asyncRandomBytes(128 / 8); // usage

But probably require a major version bump because the interface will be changed.
What are your takes on this?

check version byte

It looks like this implementation parses the version byte
and then ignores it. It should reject an otherwise valid
token if the version byte is not 0x80.

Decrypting issue

Hello,
I am using Fernet for Python but im trying to decrypt it from angular2 app. The decryption is not working and it gives me error

handleError TypeError: Cannot read property 'sigBytes' of undefined
    at Object.init (http://localhost:8100/build/js/app.bundle.js:68362:21)
    at http://localhost:8100/build/js/app.bundle.js:67958:25
    at Function.createHmac (http://localhost:8100/build/js/app.bundle.js:74924:12)
    at Object.decodeToken [as decode] (http://localhost:8100/build/js/app.bundle.js:75037:32)
    at FeedRequestProvider.ApiHelper.decrypt (http://localhost:8100/build/js/app.bundle.js:3925:28)
    at MapSubscriber.project (http://localhost:8100/build/js/app.bundle.js:4083:27)
    at MapSubscriber._next (http://localhost:8100/build/js/app.bundle.js:143244:35)
    at MapSubscriber.Subscriber.next (http://localhost:8100/build/js/app.bundle.js:136995:18)
    at XMLHttpRequest.onLoad (http://localhost:8100/build/js/app.bundle.js:46134:38)
    at ZoneDelegate.invokeTask (http://localhost:8100/build/js/zone.js:356:38)

This is the code im using to decrypt,

decrypt(response):string {
        console.log('DECRYPTING...');
        console.log(response.text());
        var token = new this.fernet.Token({
            secret: this.key,
            token: response.text()
        })

        let buffer = token.decode();
        console.log('fernet', buffer);

Can you please let me know where i am doing this wrong?

Thanks

use constant-time hmac comparison

https://github.com/csquared/fernet.js/blob/7bc5801/lib/token.js#L64
appears to be a short-circuit comparison. The spec requires the
comparison to be done in constant time, independent of the
contents of the inputs.

The go implementation does this with a library function:
https://github.com/fernet/fernet-go/blob/54c3c8f/fernet.go#L76
and the ruby implementation does it with a loop:
https://github.com/fernet/fernet-rb/blob/9190f48/lib/fernet/verifier.rb#L69

cc @tmaher @hgmnz @will

Implement in react

Hello, I am trying to implement fernet js into my react application but I get errors.

Uncaught (in promise) ReferenceError: Buffer is not defined
at Object.validate [as decode] (urlsafe-base64.js:61:1)
at Function.decode64 [as decode64toHex] (fernet.js:35:1)
at new Secret (secret.js:4:1

Thanks!

Can the new version be published to npm?

Hey @csquared, thanks for doing MR #13 -- can you also publish the update to NPM? I think the package.json is already bumped, so just publishing should be sufficient.

Thanks, and thanks for the node implementation of this. =)

Browser-usable code?

Hello,
I see that fernet.js (as well as fernetBrowser.js) contains require, etc. so this won't be accepted by the browsers if I just do

<script src="fernetBrowser.js"></script>

and copy the fernetBrowser.js file...

Could you just add a few lines in the README to explain how to "compile" / "transpile" / "pack" (?) the code (if needed?), and which tools are required for that.

Thank you in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.