first commit

This commit is contained in:
didier amyot committed 2016-03-25 17:54:34 -04:00
commit 5a8274a7ef
10 files changed
+651

No files matched your search

+1
View File
@@ -0,0 +1 @@
/node_modules
+1
View File
@@ -0,0 +1 @@
# S
+274
View File
@@ -0,0 +1,274 @@
;(function() {
var util = {};
util.low = function(byte) {
return byte & 0xf;
};
util.high = function(byte) {
return byte >>> 4 & 0xf;
};
util.madd = function(a, b) { // TODO: rename to madd256
return (a + b) % N;
// return (a + b) & 0xff; // when N = 256, 0xff = N - 1
};
util.msub = function(a, b) {// TODO: rename to msub256
return util.madd(N, a - b);
};
util.swap = function(lst, p1, p2) {
var tmp = lst[p1];
lst[p1] = lst[p2];
lst[p2] = tmp;
};
util.gcd = function(a, b){
var t;
while (b !== 0) {
t = b;
b = a % b;
a = t;
}
return a;
};
var N = 256;
var N_OVER_TWO_FLOOR = Math.floor(N / 2);
var TWO_N = 2 * N;
var spritz = {};
spritz._util = util;
spritz._initializeState = function _initializeState() {
var state = {};
state.i = 0;
state.j = 0;
state.k = 0;
state.z = 0;
state.a = 0;
state.w = 1;
state.S = [];
for (var i = 0; i < N; i++) {
state.S[i] = i;
}
return state;
};
spritz._absorb = function _absorb(I, state){
var v;
/*
basic validation of I
consider bounds-checking and deep-checking of each N-value such that they are in the valid range (0 <= x < N)
*/
if(!(Array.isArray(I) && I.length > 0)){
return false;
}
for(v = 0; v < I.length; v++){
spritz._absorbByte(I[v], state);
}
return true;
};
spritz._absorbByte = function _absorbByte(b, state) {
spritz._absorbNibble(util.low(b), state);
spritz._absorbNibble(util.high(b), state);
};
spritz._absorbNibble = function _absorbNibble(x, state) {
if (state.a === N_OVER_TWO_FLOOR){
spritz.shuffle(state);
}
util.swap(state.S, state.a, util.madd(N_OVER_TWO_FLOOR, x));
state.a = util.madd(state.a, 1);
};
spritz._absorbStop = function _absorbStop(state){
if(state.a === N_OVER_TWO_FLOOR){
spritz._shuffle(state);
}
state.a = util.madd(state.a, 1);
};
spritz._shuffle = function _shuffle(state){
spritz._whip(TWO_N, state);
spritz._crush(state);
spritz._whip(TWO_N, state);
spritz._crush(state);
spritz._whip(TWO_N, state);
state.a = 0;
};
spritz._whip = function _whip(r, state) {
for (var i = 0; i < r; i++) {
spritz._update(state);
}
do {
state.w = util.madd(state.w, 1);
} while (util.gcd(state.w, N) !== 1);
// NB. a simple-case assumption is that if N is a power of 2 then one could instead use:
// w = madd(w, 2);
};
spritz._crush = function _crush(state) {
var index;
for (var i = 0; i < N_OVER_TWO_FLOOR; i++) {
index = N - i - 1;
if (state.S[i] > state.S[index]) {
util.swap(state.S, i, index);
}
}
};
spritz._update = function _update(state) { //done
state.i = util.madd(state.i, state.w);
state.j = util.madd(state.k, state.S[util.madd(state.j, state.S[state.i])]);
state.k = util.madd(state.i + state.k, state.S[state.j]);
util.swap(state.S, state.i, state.j);
};
spritz._squeeze = function _squeeze(r, state) {
if (state.a > 0) {
spritz._shuffle(state);
}
var P = [];
for (var i = 0; i < r; i++) {
P[i] = spritz._drip(state);
}
return P;
};
spritz._drip = function _drip(state){
if (state.a > 0) {
spritz._shuffle(state);
}
spritz._update(state);
return spritz._output(state);
};
spritz._output = function _output(state) {
var idx = util.madd(state.z, state.k);
idx = util.madd(state.i, state.S[idx]);
idx = util.madd(state.j, state.S[idx]);
state.z = state.S[idx];
return state.z;
};
spritz._keySetup = function _keySetup(K) {
var state = spritz._initializeState();
spritz._absorb(K, state);
return state;
};
spritz.stringToUtf8ByteArray = function stringToUtf8ByteArray(utf8Array){
var utf8 = unescape(encodeURIComponent(utf8Array));
var arr = [];
for (var i = 0; i < utf8.length; i++) {
arr.push(utf8.charCodeAt(i));
}
return arr;
};
spritz.utf8ByteArrayToString = function utf8ByteArrayToString(utf8Array){
var ret = "";
for(var i = 0; i < utf8Array.length; i++){
ret += String.fromCharCode(utf8Array[i]);
}
return decodeURIComponent(escape(ret));
};
spritz.hash = function hash(M, r){
if(typeof M == 'string'){
return spritz.hash(spritz.stringToUtf8ByteArray(M), r);
}
var state = spritz._initializeState();
spritz._absorb(M, state);
spritz._absorbStop(state);
spritz._absorb([r & 0xff], state); // NB. restricted(!) to 255-byte hashes
return spritz._squeeze(r, state);
};
spritz.encrypt = function encrypt(K, M) {
var C = [], stream , i;
var state = spritz._keySetup(K);
stream = spritz._squeeze(M.length, state);
for (i = 0; i < M.length; i++) {
C[i] = util.madd(M[i], stream[i]);
}
return C;
};
spritz.decrypt = function decrypt(K, C) {
var M = [] , stream , i;
var state = spritz._keySetup(K);
stream = spritz._squeeze(C.length, state);
for (i = 0; i < C.length; i++) {
M[i] = util.msub(C[i], stream[i]);
}
return M;
};
// Export spritz as lodash 4.5.0.
var objectTypes = {
'function': true,
'object': true
};
function checkGlobal(value) {
return (value && value.Object === Object) ? value : null;
}
var freeWindow = checkGlobal(objectTypes[typeof window] && window);
var freeSelf = checkGlobal(objectTypes[typeof self] && self);
var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : undefined;
var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : undefined;
var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports: undefined;
var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
// Expose lodash on the free variable `window` or `self` when available. This
// prevents errors in cases where lodash is loaded by a script tag in the presence
// of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
(freeWindow || freeSelf || {}).spritz = spritz;
// Some AMD build optimizers like r.js check for condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module.
define(function() {
return spritz;
});
}
// Check for `exports` after `define` in case a build optimizer adds an `exports` object.
else if (freeExports && freeModule) {
// Export for Node.js.
if (moduleExports) {
freeModule.exports = spritz;
}
// Export for CommonJS support.
freeExports.spritz = spritz;
}
else {
// Export to the global object.
root.spritz = spritz;
}
}.call(this)); // close the prefix
+12
View File
@@ -0,0 +1,12 @@
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('build', function() {
var scripts = ['./src/prefix.js',
'./src/util.js',
'./src/spritz.js',
'./src/suffix.js'];
return gulp.src(scripts)
.pipe(concat('spritz.js'))
.pipe(gulp.dest('./dist/'));
});
+25
View File
@@ -0,0 +1,25 @@
{
"name": "spritzjs",
"version": "1.0.0",
"description": "Implementation of spritz stream cipher and hash compatible with nodejs, requirejs and browserify.",
"main": "dist/spritz.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "gulp build; mocha"
},
"keywords": [
"spritz",
"stream cipher",
"hash",
"requirejs"
],
"author": "didier amyot <didier.amyot@gmail.com>",
"license": "MIT",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-concat": "^2.6.0",
"mocha": "^2.4.5"
}
}
+1
View File
@@ -0,0 +1 @@
;(function() {
+183
View File
@@ -0,0 +1,183 @@
var N = 256;
var N_OVER_TWO_FLOOR = Math.floor(N / 2);
var TWO_N = 2 * N;
var spritz = {};
spritz._util = util;
spritz._initializeState = function _initializeState() {
var state = {};
state.i = 0;
state.j = 0;
state.k = 0;
state.z = 0;
state.a = 0;
state.w = 1;
state.S = [];
for (var i = 0; i < N; i++) {
state.S[i] = i;
}
return state;
};
spritz._absorb = function _absorb(I, state){
var v;
/*
basic validation of I
consider bounds-checking and deep-checking of each N-value such that they are in the valid range (0 <= x < N)
*/
if(!(Array.isArray(I) && I.length > 0)){
return false;
}
for(v = 0; v < I.length; v++){
spritz._absorbByte(I[v], state);
}
return true;
};
spritz._absorbByte = function _absorbByte(b, state) {
spritz._absorbNibble(util.low(b), state);
spritz._absorbNibble(util.high(b), state);
};
spritz._absorbNibble = function _absorbNibble(x, state) {
if (state.a === N_OVER_TWO_FLOOR){
spritz.shuffle(state);
}
util.swap(state.S, state.a, util.madd(N_OVER_TWO_FLOOR, x));
state.a = util.madd(state.a, 1);
};
spritz._absorbStop = function _absorbStop(state){
if(state.a === N_OVER_TWO_FLOOR){
spritz._shuffle(state);
}
state.a = util.madd(state.a, 1);
};
spritz._shuffle = function _shuffle(state){
spritz._whip(TWO_N, state);
spritz._crush(state);
spritz._whip(TWO_N, state);
spritz._crush(state);
spritz._whip(TWO_N, state);
state.a = 0;
};
spritz._whip = function _whip(r, state) {
for (var i = 0; i < r; i++) {
spritz._update(state);
}
do {
state.w = util.madd(state.w, 1);
} while (util.gcd(state.w, N) !== 1);
// NB. a simple-case assumption is that if N is a power of 2 then one could instead use:
// w = madd(w, 2);
};
spritz._crush = function _crush(state) {
var index;
for (var i = 0; i < N_OVER_TWO_FLOOR; i++) {
index = N - i - 1;
if (state.S[i] > state.S[index]) {
util.swap(state.S, i, index);
}
}
};
spritz._update = function _update(state) { //done
state.i = util.madd(state.i, state.w);
state.j = util.madd(state.k, state.S[util.madd(state.j, state.S[state.i])]);
state.k = util.madd(state.i + state.k, state.S[state.j]);
util.swap(state.S, state.i, state.j);
};
spritz._squeeze = function _squeeze(r, state) {
if (state.a > 0) {
spritz._shuffle(state);
}
var P = [];
for (var i = 0; i < r; i++) {
P[i] = spritz._drip(state);
}
return P;
};
spritz._drip = function _drip(state){
if (state.a > 0) {
spritz._shuffle(state);
}
spritz._update(state);
return spritz._output(state);
};
spritz._output = function _output(state) {
var idx = util.madd(state.z, state.k);
idx = util.madd(state.i, state.S[idx]);
idx = util.madd(state.j, state.S[idx]);
state.z = state.S[idx];
return state.z;
};
spritz._keySetup = function _keySetup(K) {
var state = spritz._initializeState();
spritz._absorb(K, state);
return state;
};
spritz.stringToUtf8ByteArray = function stringToUtf8ByteArray(utf8Array){
var utf8 = unescape(encodeURIComponent(utf8Array));
var arr = [];
for (var i = 0; i < utf8.length; i++) {
arr.push(utf8.charCodeAt(i));
}
return arr;
};
spritz.utf8ByteArrayToString = function utf8ByteArrayToString(utf8Array){
var ret = "";
for(var i = 0; i < utf8Array.length; i++){
ret += String.fromCharCode(utf8Array[i]);
}
return decodeURIComponent(escape(ret));
};
spritz.hash = function hash(M, r){
if(typeof M == 'string'){
return spritz.hash(spritz.stringToUtf8ByteArray(M), r);
}
var state = spritz._initializeState();
spritz._absorb(M, state);
spritz._absorbStop(state);
spritz._absorb([r & 0xff], state); // NB. restricted(!) to 255-byte hashes
return spritz._squeeze(r, state);
};
spritz.encrypt = function encrypt(K, M) {
var C = [], stream , i;
var state = spritz._keySetup(K);
stream = spritz._squeeze(M.length, state);
for (i = 0; i < M.length; i++) {
C[i] = util.madd(M[i], stream[i]);
}
return C;
};
spritz.decrypt = function decrypt(K, C) {
var M = [] , stream , i;
var state = spritz._keySetup(K);
stream = spritz._squeeze(C.length, state);
for (i = 0; i < C.length; i++) {
M[i] = util.msub(C[i], stream[i]);
}
return M;
};
+52
View File
@@ -0,0 +1,52 @@
// Export spritz as lodash 4.5.0.
var objectTypes = {
'function': true,
'object': true
};
function checkGlobal(value) {
return (value && value.Object === Object) ? value : null;
}
var freeWindow = checkGlobal(objectTypes[typeof window] && window);
var freeSelf = checkGlobal(objectTypes[typeof self] && self);
var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : undefined;
var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : undefined;
var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports: undefined;
var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')();
// Expose lodash on the free variable `window` or `self` when available. This
// prevents errors in cases where lodash is loaded by a script tag in the presence
// of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch for more details.
(freeWindow || freeSelf || {}).spritz = spritz;
// Some AMD build optimizers like r.js check for condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module.
define(function() {
return spritz;
});
}
// Check for `exports` after `define` in case a build optimizer adds an `exports` object.
else if (freeExports && freeModule) {
// Export for Node.js.
if (moduleExports) {
freeModule.exports = spritz;
}
// Export for CommonJS support.
freeExports.spritz = spritz;
}
else {
// Export to the global object.
root.spritz = spritz;
}
}.call(this)); // close the prefix
+35
View File
@@ -0,0 +1,35 @@
var util = {};
util.low = function(byte) {
return byte & 0xf;
};
util.high = function(byte) {
return byte >>> 4 & 0xf;
};
util.madd = function(a, b) { // TODO: rename to madd256
return (a + b) % N;
// return (a + b) & 0xff; // when N = 256, 0xff = N - 1
};
util.msub = function(a, b) {// TODO: rename to msub256
return util.madd(N, a - b);
};
util.swap = function(lst, p1, p2) {
var tmp = lst[p1];
lst[p1] = lst[p2];
lst[p2] = tmp;
};
util.gcd = function(a, b){
var t;
while (b !== 0) {
t = b;
b = a % b;
a = t;
}
return a;
};
+67
View File
@@ -0,0 +1,67 @@
var util = require("../dist/spritz.js")._util;
var spritz = require("../dist/spritz.js");
var assert = require('assert');
describe('utility functions', function() {
describe('the low function', function(){
it('should get the low nibble of the input', function () {
assert.equal(util.low(3), 3);
assert.equal(util.low(0), 0);
assert.equal(util.low(255), 15);
});
});
});
describe('the string to array convertion', function(){
it('should be able to convert string to utf-8 array', function(){
var utf8String = "maison-дом-տուն-სახლი";
var expt = [109,97,105,115,111,110,45,208,180,208,190,208,188,45,213,191,213,184,214,130,213,182,45,225,131,161,225,131,144,225,131,174,225,131,154,225,131,152];
assert.deepEqual(spritz.stringToUtf8ByteArray(utf8String), expt);
});
it('should be able to convert utf-8 array to string', function(){
var utf8Array = [109,97,105,115,111,110,45,208,180,208,190,208,188,45,213,191,213,184,214,130,213,182,45,225,131,161,225,131,144,225,131,174,225,131,154,225,131,152];
var expt = "maison-дом-տուն-სახლი";
assert.deepEqual(spritz.utf8ByteArrayToString(utf8Array), expt);
});
});
describe('the hash function', function(){
it('should be able to hash an array', function(){
var M = [65, 66, 67];
var r = 32;
var expt = [2,143,162,180,139,147,74,24,98,184,105,16,81,58,71,103,124,28,45,149,236,62,117,112,120,111,28,50,139,189,74,71];
assert.deepEqual(spritz.hash(M, r), expt);
});
it('should be able to hash a string', function(){
var M = 'ABC';
var r = 32;
var expt = [2,143,162,180,139,147,74,24,98,184,105,16,81,58,71,103,124,28,45,149,236,62,117,112,120,111,28,50,139,189,74,71];
assert.deepEqual(spritz.hash(M, r), expt);
});
});
describe('the encrypt/decrypt function', function(){
it('should be encrypt/decrypt a byte array', function(){
var stringMessage = "maison-дом-տուն-სახლი";
var byteArrMessage = spritz.stringToUtf8ByteArray(stringMessage);
var key = [12, 99, 200, 76, 162, 87, 729, 272, 272, 282, 282];
var cypher = spritz.encrypt(key, byteArrMessage);
var decryptedMessage = spritz.decrypt(key, cypher);
assert.deepEqual(decryptedMessage, byteArrMessage);
});
xit('should encrypt correctly the message', function(){
var stringMessage = "maison-дом-տուն-სახლი";
var byteArrMessage = spritz.stringToUtf8ByteArray(stringMessage);
var key = [12, 55, 12, 12, 87, 89, 81, 17, 27, 89];
var cypher = spritz.encrypt(key, byteArrMessage);
var expt = [125,26,182,7,75,36,178,253,82,46,91,21,218,16,127,41,203,45,90,129,129,47,171,68,221,112,210,6,99,250,91,111,225,27,89,100,189,9];
assert.deepEqual(cypher, expt);
});
});