triplesec
Version:
A CommonJS-compliant system for secure encryption of smallish secrets
853 lines (808 loc) • 29.2 kB
JavaScript
// Generated by IcedCoffeeScript 108.0.8
(function() {
var AES, Base, CURRENT_VERSION, Concat, Encryptor, HMAC_SHA256, KECCAK, PBKDF2, SHA3STD, SHA512, Scrypt, TwoFish, V, WordArray, XOR, ctr, encrypt, iced, make_esc, prng, salsa20, util, __iced_k, __iced_k_noop, _ref,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
iced = require('iced-runtime');
__iced_k = __iced_k_noop = function() {};
WordArray = require('./wordarray').WordArray;
salsa20 = require('./salsa20');
AES = require('./aes').AES;
TwoFish = require('./twofish').TwoFish;
ctr = require('./ctr');
_ref = require('./combine'), XOR = _ref.XOR, Concat = _ref.Concat;
SHA512 = require('./sha512').SHA512;
SHA3STD = require('./sha3std').SHA3STD;
KECCAK = require('./keccak').KECCAK;
PBKDF2 = require('./pbkdf2').PBKDF2;
Scrypt = require('./scrypt').Scrypt;
util = require('./util');
prng = require('./prng');
make_esc = require('iced-error').make_esc;
HMAC_SHA256 = require('./hmac').HMAC_SHA256;
V = {
"1": {
header: [0x1c94d7de, 1],
salt_size: 8,
xsalsa20_rev: true,
kdf: {
klass: PBKDF2,
opts: {
c: 1024,
klass: XOR
}
},
use_twofish: true,
hmac_hashes: [SHA512, KECCAK],
hmac_key_size: 768 / 8,
version: 1
},
"2": {
header: [0x1c94d7de, 2],
salt_size: 16,
xsalsa20_rev: true,
kdf: {
klass: Scrypt,
opts: {
c: 64,
klass: XOR,
N: 12,
r: 8,
p: 1
}
},
use_twofish: true,
hmac_hashes: [SHA512, KECCAK],
hmac_key_size: 768 / 8,
version: 2
},
"3": {
header: [0x1c94d7de, 3],
salt_size: 16,
xsalsa20_rev: false,
kdf: {
klass: Scrypt,
opts: {
c: 1,
klass: HMAC_SHA256,
N: 15,
r: 8,
p: 1
}
},
use_twofish: true,
hmac_hashes: [SHA512, KECCAK],
hmac_key_size: 768 / 8,
version: 3
},
"4": {
header: [0x1c94d7de, 4],
salt_size: 16,
xsalsa20_rev: false,
kdf: {
klass: Scrypt,
opts: {
c: 1,
klass: HMAC_SHA256,
N: 15,
r: 8,
p: 1
}
},
hmac_key_size: 768 / 8,
use_twofish: false,
hmac_hashes: [SHA512, SHA3STD],
version: 4
}
};
exports.CURRENT_VERSION = CURRENT_VERSION = 4;
Base = (function() {
function Base(_arg) {
var key, version;
key = _arg.key, version = _arg.version;
this.version = V[version != null ? version : CURRENT_VERSION];
if (this.version == null) {
throw new Error("unknown version: " + version);
}
this.set_key(key);
this.derived_keys = {};
}
Base.prototype.kdf = function(_arg, cb) {
var args, dkLen, end, extra_keymaterial, i, k, key, keys, len, lens, order, progress_hook, raw, salt, salt_hex, v, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
salt = _arg.salt, extra_keymaterial = _arg.extra_keymaterial, progress_hook = _arg.progress_hook;
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.kdf"
});
_this._check_scrubbed(_this.key, "in KDF", cb, __iced_deferrals.defer({
lineno: 121
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
salt_hex = salt.to_hex();
key = _this.key.clone();
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.kdf"
});
_this._check_scrubbed(key, "KDF", cb, __iced_deferrals.defer({
lineno: 129
}));
__iced_deferrals._fulfill();
})(function() {
(function(__iced_k) {
if ((keys = _this.derived_keys[salt_hex]) == null) {
_this._kdf = new _this.version.kdf.klass(_this.version.kdf.opts);
lens = {
hmac: _this.version.hmac_key_size,
aes: AES.keySize,
salsa20: salsa20.Salsa20.keySize
};
if (_this.version.use_twofish) {
lens.twofish = TwoFish.keySize;
}
if (_this.version.use_twofish) {
order = ['hmac', 'aes', 'twofish', 'salsa20'];
} else {
order = ['hmac', 'aes', 'salsa20'];
}
dkLen = extra_keymaterial || 0;
for (k in lens) {
v = lens[k];
dkLen += v;
}
args = {
dkLen: dkLen,
key: key,
progress_hook: progress_hook,
salt: salt
};
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.kdf"
});
_this._kdf.run(args, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return raw = arguments[0];
};
})(),
lineno: 152
}));
__iced_deferrals._fulfill();
})(function() {
var _i, _len;
keys = {};
i = 0;
for (_i = 0, _len = order.length; _i < _len; _i++) {
k = order[_i];
v = lens[k];
len = v / 4;
end = i + len;
keys[k] = new WordArray(raw.words.slice(i, end));
i = end;
}
keys.extra = (new WordArray(raw.words.slice(end))).to_buffer();
return __iced_k(_this.derived_keys[salt_hex] = keys);
});
} else {
return __iced_k();
}
})(function() {
return cb(null, keys);
});
});
};
})(this));
};
Base.prototype.set_key = function(key) {
var wakey;
if (key != null) {
wakey = WordArray.from_buffer(key);
if (!this.key || !this.key.equal(wakey)) {
this.scrub();
return this.key = wakey;
}
} else {
return this.scrub();
}
};
Base.prototype._check_scrubbed = function(key, where, ecb, okcb) {
if ((key != null) && !key.is_scrubbed()) {
return okcb();
} else {
return ecb(new Error("" + where + ": Failed due to scrubbed key!"), null);
}
};
Base.prototype.sign = function(_arg, cb) {
var combine_klasses, input, key, out, progress_hook, salt, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
input = _arg.input, key = _arg.key, salt = _arg.salt, progress_hook = _arg.progress_hook;
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.sign"
});
_this._check_scrubbed(key, "HMAC", cb, __iced_deferrals.defer({
lineno: 210
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
input = (new WordArray(_this.version.header)).concat(salt).concat(input);
combine_klasses = _this.version.hmac_hashes;
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.sign"
});
Concat.bulk_sign({
key: key,
input: input,
progress_hook: progress_hook,
combine_klasses: combine_klasses
}, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return out = arguments[0];
};
})(),
lineno: 213
}));
__iced_deferrals._fulfill();
})(function() {
input.scrub();
return cb(null, out);
});
};
})(this));
};
Base.prototype.run_salsa20 = function(_arg, cb) {
var args, ct, input, iv, key, output_iv, progress_hook, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
input = _arg.input, key = _arg.key, iv = _arg.iv, output_iv = _arg.output_iv, progress_hook = _arg.progress_hook;
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_salsa20"
});
_this._check_scrubbed(key, "Salsa20", cb, __iced_deferrals.defer({
lineno: 229
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
args = {
input: input,
progress_hook: progress_hook,
key: key,
iv: iv
};
if (_this.version.xsalsa20_rev) {
args.key = key.clone().endian_reverse();
args.iv = iv.clone().endian_reverse();
}
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_salsa20"
});
salsa20.bulk_encrypt(args, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return ct = arguments[0];
};
})(),
lineno: 241
}));
__iced_deferrals._fulfill();
})(function() {
if (output_iv) {
ct = iv.clone().concat(ct);
}
if (_this.version.xsalsa20_rev) {
args.key.scrub();
args.iv.scrub();
}
return cb(null, ct);
});
};
})(this));
};
Base.prototype.run_twofish = function(_arg, cb) {
var block_cipher, ct, input, iv, key, progress_hook, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
input = _arg.input, key = _arg.key, iv = _arg.iv, progress_hook = _arg.progress_hook;
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_twofish"
});
_this._check_scrubbed(key, "TwoFish", cb, __iced_deferrals.defer({
lineno: 264
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
block_cipher = new TwoFish(key);
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_twofish"
});
ctr.bulk_encrypt({
block_cipher: block_cipher,
iv: iv,
input: input,
progress_hook: progress_hook,
what: "twofish"
}, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return ct = arguments[0];
};
})(),
lineno: 266
}));
__iced_deferrals._fulfill();
})(function() {
block_cipher.scrub();
return cb(null, iv.clone().concat(ct));
});
};
})(this));
};
Base.prototype.run_aes = function(_arg, cb) {
var block_cipher, ct, input, iv, key, progress_hook, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
input = _arg.input, key = _arg.key, iv = _arg.iv, progress_hook = _arg.progress_hook;
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_aes"
});
_this._check_scrubbed(key, "AES", cb, __iced_deferrals.defer({
lineno: 281
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
block_cipher = new AES(key);
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Base.run_aes"
});
ctr.bulk_encrypt({
block_cipher: block_cipher,
iv: iv,
input: input,
progress_hook: progress_hook,
what: "aes"
}, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return ct = arguments[0];
};
})(),
lineno: 283
}));
__iced_deferrals._fulfill();
})(function() {
block_cipher.scrub();
return cb(null, iv.clone().concat(ct));
});
};
})(this));
};
Base.prototype.scrub = function() {
var algo, key, key_ring, salt, _ref1;
if (this.key != null) {
this.key.scrub();
}
if (this.derived_keys != null) {
_ref1 = this.derived_keys;
for (salt in _ref1) {
key_ring = _ref1[salt];
for (algo in key_ring) {
key = key_ring[algo];
if (algo !== 'extra') {
key.scrub();
}
}
}
}
this.derived_keys = {};
if (this.salt != null) {
this.salt.scrub();
}
this.salt = null;
return this.key = null;
};
Base.prototype.clone_derived_keys = function() {
var algo, key, key_ring, ret, salt, _ref1;
ret = null;
if (this.derived_keys != null) {
ret = {};
_ref1 = this.derived_keys;
for (salt in _ref1) {
key_ring = _ref1[salt];
ret[salt] = {};
for (algo in key_ring) {
key = key_ring[algo];
ret[salt][algo] = algo === 'extra' ? key : key.clone();
}
}
}
return ret;
};
return Base;
})();
Encryptor = (function(_super) {
__extends(Encryptor, _super);
function Encryptor(_arg) {
var key, rng, version;
key = _arg.key, rng = _arg.rng, version = _arg.version;
Encryptor.__super__.constructor.call(this, {
key: key,
version: version
});
this.rng = rng || prng.generate;
}
Encryptor.prototype.pick_random_ivs = function(_arg, cb) {
var iv_lens, ivs, k, progress_hook, v, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
progress_hook = _arg.progress_hook;
iv_lens = [];
iv_lens.push(['aes', AES.ivSize]);
if (this.version.use_twofish) {
iv_lens.push(['twofish', TwoFish.ivSize]);
}
iv_lens.push(['salsa20', salsa20.Salsa20.ivSize]);
ivs = {};
(function(_this) {
return (function(__iced_k) {
var _i, _len, _ref1, _results, _while;
_ref1 = iv_lens;
_len = _ref1.length;
_i = 0;
_while = function(__iced_k) {
var _break, _continue, _next, _ref2;
_break = __iced_k;
_continue = function() {
return iced.trampoline(function() {
++_i;
return _while(__iced_k);
});
};
_next = _continue;
if (!(_i < _len)) {
return _break();
} else {
_ref2 = _ref1[_i], k = _ref2[0], v = _ref2[1];
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.pick_random_ivs"
});
_this.rng(v, __iced_deferrals.defer({
assign_fn: (function(__slot_1, __slot_2) {
return function() {
return __slot_1[__slot_2] = arguments[0];
};
})(ivs, k),
lineno: 407
}));
__iced_deferrals._fulfill();
})(_next);
}
};
_while(__iced_k);
});
})(this)((function(_this) {
return function() {
return cb(ivs);
};
})(this));
};
Encryptor.prototype.resalt = function(_arg, cb) {
var err, extra_keymaterial, progress_hook, salt, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
salt = _arg.salt, extra_keymaterial = _arg.extra_keymaterial, progress_hook = _arg.progress_hook;
err = null;
(function(_this) {
return (function(__iced_k) {
if (salt == null) {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.resalt"
});
_this.rng(_this.version.salt_size, __iced_deferrals.defer({
assign_fn: (function(__slot_1) {
return function() {
return __slot_1.salt = arguments[0];
};
})(_this),
lineno: 423
}));
__iced_deferrals._fulfill();
})(__iced_k);
} else {
return __iced_k(salt.length !== _this.version.salt_size ? err = new Error("Need a salt of exactly " + _this.version.salt_size + " bytes (got " + salt.length + ")") : _this.salt = WordArray.alloc(salt));
}
});
})(this)((function(_this) {
return function() {
(function(__iced_k) {
if (err == null) {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.resalt"
});
_this.kdf({
extra_keymaterial: extra_keymaterial,
progress_hook: progress_hook,
salt: _this.salt
}, __iced_deferrals.defer({
assign_fn: (function(__slot_1) {
return function() {
err = arguments[0];
return __slot_1.keys = arguments[1];
};
})(_this),
lineno: 429
}));
__iced_deferrals._fulfill();
})(__iced_k);
} else {
return __iced_k();
}
})(function() {
return cb(err, _this.keys);
});
};
})(this));
};
Encryptor.prototype.run = function(_arg, cb) {
var ct3, data, esc, extra_keymaterial, ivs, mid, progress_hook, pt, ret, salt, sig, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
data = _arg.data, salt = _arg.salt, extra_keymaterial = _arg.extra_keymaterial, progress_hook = _arg.progress_hook;
esc = make_esc(cb, "Encryptor::run");
(function(_this) {
return (function(__iced_k) {
if ((salt != null) || (_this.salt == null)) {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.resalt({
salt: salt,
extra_keymaterial: extra_keymaterial,
progress_hook: progress_hook
}, esc(__iced_deferrals.defer({
lineno: 460
})));
__iced_deferrals._fulfill();
})(__iced_k);
} else {
return __iced_k();
}
});
})(this)((function(_this) {
return function() {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.pick_random_ivs({
progress_hook: progress_hook
}, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
return ivs = arguments[0];
};
})(),
lineno: 461
}));
__iced_deferrals._fulfill();
})(function() {
pt = WordArray.from_buffer(data);
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.run_salsa20({
input: pt,
key: _this.keys.salsa20,
progress_hook: progress_hook,
iv: ivs.salsa20,
output_iv: true
}, esc(__iced_deferrals.defer({
assign_fn: (function() {
return function() {
return mid = arguments[0];
};
})(),
lineno: 463
})));
__iced_deferrals._fulfill();
})(function() {
(function(__iced_k) {
if (_this.version.use_twofish) {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.run_twofish({
input: mid,
key: _this.keys.twofish,
progress_hook: progress_hook,
iv: ivs.twofish
}, esc(__iced_deferrals.defer({
assign_fn: (function() {
return function() {
return mid = arguments[0];
};
})(),
lineno: 465
})));
__iced_deferrals._fulfill();
})(__iced_k);
} else {
return __iced_k();
}
})(function() {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.run_aes({
input: mid,
key: _this.keys.aes,
progress_hook: progress_hook,
iv: ivs.aes
}, esc(__iced_deferrals.defer({
assign_fn: (function() {
return function() {
return ct3 = arguments[0];
};
})(),
lineno: 466
})));
__iced_deferrals._fulfill();
})(function() {
(function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced",
funcname: "Encryptor.run"
});
_this.sign({
input: ct3,
key: _this.keys.hmac,
progress_hook: progress_hook,
salt: _this.salt
}, esc(__iced_deferrals.defer({
assign_fn: (function() {
return function() {
return sig = arguments[0];
};
})(),
lineno: 467
})));
__iced_deferrals._fulfill();
})(function() {
ret = (new WordArray(_this.version.header)).concat(_this.salt).concat(sig).concat(ct3).to_buffer();
util.scrub_buffer(data);
return cb(null, ret);
});
});
});
});
});
};
})(this));
};
Encryptor.prototype.clone = function() {
var ret, _ref1, _ref2;
ret = new Encryptor({
key: (_ref1 = this.key) != null ? _ref1.to_buffer() : void 0,
rng: this.rng,
version: (_ref2 = this.version) != null ? _ref2.version : void 0
});
ret.derived_keys = this.clone_derived_keys();
return ret;
};
return Encryptor;
})(Base);
encrypt = function(_arg, cb) {
var data, enc, err, key, progress_hook, ret, rng, version, ___iced_passed_deferral, __iced_deferrals, __iced_k;
__iced_k = __iced_k_noop;
___iced_passed_deferral = iced.findDeferral(arguments);
key = _arg.key, data = _arg.data, rng = _arg.rng, progress_hook = _arg.progress_hook, version = _arg.version;
enc = new Encryptor({
key: key,
rng: rng,
version: version
});
(function(_this) {
return (function(__iced_k) {
__iced_deferrals = new iced.Deferrals(__iced_k, {
parent: ___iced_passed_deferral,
filename: "/Users/max/src/keybase/triplesec/src/enc.iced"
});
enc.run({
data: data,
progress_hook: progress_hook
}, __iced_deferrals.defer({
assign_fn: (function() {
return function() {
err = arguments[0];
return ret = arguments[1];
};
})(),
lineno: 506
}));
__iced_deferrals._fulfill();
});
})(this)((function(_this) {
return function() {
enc.scrub();
return cb(err, ret);
};
})(this));
};
exports.V = V;
exports.encrypt = encrypt;
exports.Base = Base;
exports.Encryptor = Encryptor;
}).call(this);