Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Javascript Node CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:7.10

working_directory: ~/paseto.js

steps:
- checkout

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

- run: npm install

- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}

# run tests!
- run: npm test
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ build/Release
# Dependency directories
node_modules/
jspm_packages/
package-lock.json

# Typescript v1 declaration files
typings/
Expand All @@ -60,10 +61,10 @@ typings/

# dotenv environment variables file
.env

.nvmrc


# End of https://www.gitignore.io/api/node

# for c++ addons building
build/
build/
34 changes: 30 additions & 4 deletions lib/protocol/V2.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ function sklength() {
return this._constants.SYMMETRIC_KEY_BYTES;
}

/***
* binary
*
* specify that the message in the token is binary data
*
* @function
* @api public
*
* @returns {V2}
*/
V2.prototype.binary = binary;
function binary() {
this._binary = true;
return this;
}


/***
* __encrypt
Expand Down Expand Up @@ -137,7 +153,12 @@ function __encrypt(data, key, footer, nonce, cb) {

const header = utils.local(self);

[ data, footer, nonce ] = (utils.parse('utf-8'))(data, footer, nonce);
if (this._binary) {
[ data ] = (utils.parse('utf-8'))(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be "binary" rather than "utf-8"?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I have no idea how the test was passing.

[ footer, nonce ] = (utils.parse('utf-8'))(footer, nonce);
} else {
[ data, footer, nonce ] = (utils.parse('utf-8'))(data, footer, nonce);
}

let token;
try {
Expand Down Expand Up @@ -239,7 +260,12 @@ function sign(data, key, footer, cb) {

const header = utils.public(self);

[ data, footer ] = (utils.parse('utf-8'))(data, footer);
if (this._binary) {
[ data ] = (utils.parse('binary'))(data);
[ footer ] = (utils.parse('utf-8'))(footer);
} else {
[ data, footer ] = (utils.parse('utf-8'))(data, footer);
}

// sign

Expand Down Expand Up @@ -317,8 +343,8 @@ function verify(token, key, footer, cb) {
if (!valid) { return done(new PasetoError('Invalid signature for this message')); }

// format

return done(null, data.toString('utf-8'));
const format = this._binary ? 'binary' : 'utf-8'
return done(null, data.toString(format));
});
}

Expand Down
2 changes: 1 addition & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function hkdf(alg) {
module.exports.parse = parse;
function parse(as) {

if ([ 'hex', 'base64', 'utf-8' ].indexOf(as) === -1) { throw new Error('Unknown format'); }
if ([ 'hex', 'base64', 'utf-8', 'binary' ].indexOf(as) === -1) { throw new Error('Unknown format'); }
const parser = (as === 'base64') ? fromB64URLSafe : (i) => { return Buffer.from(i, as); }

/***
Expand Down
178 changes: 178 additions & 0 deletions test/V2.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const assert = require('assert');
const sodium = require('libsodium-wrappers-sumo');
const zlib = require('zlib');

const Paseto = require('../lib/paseto');

Expand Down Expand Up @@ -224,6 +225,95 @@ describe('Protocol V2', () => {
});
});

describe('binary', () => {

before(() => {
message = zlib.gzipSync(Buffer.from('test')).toString('binary');
});

it('should encrypt and decrypt successfully - callback api', (done) => {

V2.binary().encrypt(message, key, '', (err, token) => {
if (err) { return done(err); }

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 9), 'v2.local.');

V2.binary().decrypt(token, key, '', (err, data) => {
if (err) { return done(err); }

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

done();
});
});
});

it('should encrypt and decrypt successfully - promise api', (done) => {

V2.binary().encrypt(message, key, '')
.then((token) => {

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 9), 'v2.local.');

return V2.binary().decrypt(token, key, '');
})
.then((data) => {

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

return done();
})
.catch((err) => {
return done(err);
});
});

it('should encrypt and decrypt successfully with footer - callback api', (done) => {

V2.binary().encrypt(message, key, footer, (err, token) => {
if (err) { return done(err); }

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 9), 'v2.local.');

V2.binary().decrypt(token, key, footer, (err, data) => {
if (err) { return done(err); }

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

done();
});
});
});

it('should encrypt and decrypt successfully with footer - promise api', (done) => {

V2.binary().encrypt(message, key, footer)
.then((token) => {

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 9), 'v2.local.');

return V2.binary().decrypt(token, key, footer);
})
.then((data) => {

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

return done();
})
.catch((err) => {
return done(err);
});
});
});

describe('errors', () => {

const InvalidVersionError = require('../lib/error/InvalidVersionError');
Expand Down Expand Up @@ -501,6 +591,94 @@ describe('Protocol V2', () => {
});
});

describe('binary', () => {

before(() => {
message = zlib.gzipSync(Buffer.from('test')).toString('binary');
});

it('should sign and verify successfully - callback api', (done) => {

V2.binary().sign(message, sk, '', (err, token) => {
if (err) { return done(err); }

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 10), 'v2.public.');

V2.binary().verify(token, pk, '', (err, data) => {
if (err) { return done(err); }

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

done();
});
});
});

it('should sign and verify successfully - promise api', (done) => {

V2.binary().sign(message, sk, '')
.then((token) => {

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 10), 'v2.public.');

return V2.binary().verify(token, pk, '');
})
.then((data) => {
assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

return done();
})
.catch((err) => {
return done(err);
});
});

it('should sign and verify successfully with footer - callback api', (done) => {

V2.binary().sign(message, sk, footer, (err, token) => {
if (err) { return done(err); }

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 10), 'v2.public.');

V2.binary().verify(token, pk, footer, (err, data) => {
if (err) { return done(err); }

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

done();
});
});
});

it('should sign and verify successfully with footer - promise api', (done) => {

V2.binary().sign(message, sk, footer)
.then((token) => {

assert.equal(typeof token, 'string');
assert.equal(token.substring(0, 10), 'v2.public.');

return V2.binary().verify(token, pk, footer);
})
.then((data) => {

assert.equal(typeof data, 'string');
assert.equal(zlib.gunzipSync(Buffer.from(data, 'binary')).toString(), 'test');

return done();
})
.catch((err) => {
return done(err);
});
});
});

describe('errors', () => {

const InvalidVersionError = require('../lib/error/InvalidVersionError');
Expand Down