kbpgp
Version:
Keybase's PGP Implementation
203 lines (178 loc) • 5.83 kB
JavaScript
// Generated by IcedCoffeeScript 108.0.11
(function() {
var C, S2K, SHA256, SecretKeyMaterial, alloc, iterated_s2k, streamers, triplesec, _iterated_s2k_cache, _ref;
triplesec = require('triplesec');
C = require('../const').openpgp;
_ref = require('../hash'), alloc = _ref.alloc, SHA256 = _ref.SHA256, streamers = _ref.streamers;
S2K = (function() {
S2K.prototype._count = function(c, bias) {
return (16 + (c & 15)) << ((c >> 4) + bias);
};
function S2K() {
this.hash = SHA256;
this.streamer = streamers.SHA256();
}
S2K.prototype.set_hash_algorithm = function(which) {
if ((this.hash = alloc(which)) != null) {
return this.streamer = streamers[this.hash.algname]();
} else {
console.warn("No such hash: " + which + "; defaulting to SHA-256");
this.hash = SHA256;
return this.streamer = streamers.SHA256();
}
};
S2K.prototype.read = function(slice) {
var c;
this.type = slice.read_uint8();
switch (this.type) {
case C.s2k.plain:
this.set_hash_algorithm(slice.read_uint8());
break;
case C.s2k.salt:
this.set_hash_algorithm(slice.read_uint8());
this.salt = slice.read_buffer(8);
break;
case C.s2k.salt_iter:
this.set_hash_algorithm(slice.read_uint8());
this.salt = slice.read_buffer(8);
this.EXPBIAS = 6;
c = slice.read_uint8();
this.count = this._count(c, this.EXPBIAS);
break;
case C.s2k.gnu:
this.read_gnu_extensions(slice);
break;
default:
throw new Error("unknown s2k type! " + this.type);
}
return this;
};
S2K.prototype.read_gnu_extensions = function(slice) {
var buf, gnu_ext_type, id, version;
version = slice.read_uint8();
if ((id = (buf = slice.read_buffer(3)).toString('utf8')) === "GNU") {
gnu_ext_type = slice.read_uint8() + 1000;
switch (gnu_ext_type) {
case 1001:
return this.type = C.s2k.gnu_dummy;
default:
throw new Error("unknown s2k gnu protection mode: " + gnu_ext_type);
}
} else {
throw new Error("Malformed GNU-extension: " + ext);
}
};
S2K.prototype.write = function(passphrase, salt, c, keysize) {
var type;
this.type = type = 3;
this.salt = salt;
this.count = this._count(c, 6);
this.s2kLength = 10;
return this.produce_key(passphrase, keysize);
};
S2K.prototype.is_dummy = function() {
return this.type === C.s2k.gnu_dummy;
};
S2K.prototype.produce_key = function(passphrase, numBytes) {
var key, key2, prefix, ret, seed;
if (numBytes == null) {
numBytes = 16;
}
ret = (function() {
switch (this.type) {
case C.s2k.plain:
return this.hash(passphrase);
case C.s2k.salt:
return this.hash(Buffer.concat([this.salt, passphrase]));
case C.s2k.salt_iter:
seed = Buffer.concat([this.salt, passphrase]);
key = iterated_s2k({
alg: this.hash.algname,
seed: seed,
count: this.count
});
if ((numBytes != null) && (numBytes === 24 || numBytes === 32)) {
prefix = Buffer.from([0]);
key2 = iterated_s2k({
alg: this.hash.algname,
seed: seed,
count: this.count,
prefix: prefix
});
return Buffer.concat([key, key2]);
} else {
return key;
}
break;
default:
return null;
}
}).call(this);
return ret.slice(0, numBytes);
};
return S2K;
})();
_iterated_s2k_cache = {};
iterated_s2k = function(_arg) {
var alg, bigbuf, count, i, k, n, prefix, rem, rembuf, ret, seed, streamer, tot, val;
alg = _arg.alg, seed = _arg.seed, count = _arg.count, prefix = _arg.prefix;
k = "" + alg + "-" + (seed.toString('base64')) + "-" + count;
if (prefix != null) {
k += "-" + (prefix.toString('base64'));
}
if ((val = _iterated_s2k_cache[k]) != null) {
return val;
}
streamer = streamers[alg]();
if (prefix != null) {
streamer.update(prefix);
}
bigbuf = Buffer.concat((function() {
var _i, _results;
_results = [];
for (i = _i = 0; _i < 4096; i = ++_i) {
_results.push(seed);
}
return _results;
})());
tot = 0;
while (tot + bigbuf.length <= count) {
streamer.update(bigbuf);
tot += bigbuf.length;
}
rem = count - tot;
n = Math.ceil(rem / seed.length);
rembuf = Buffer.concat((function() {
var _i, _results;
_results = [];
for (i = _i = 0; 0 <= n ? _i < n : _i > n; i = 0 <= n ? ++_i : --_i) {
_results.push(seed);
}
return _results;
})());
ret = streamer(rembuf.slice(0, rem));
_iterated_s2k_cache[k] = ret;
return ret;
};
SecretKeyMaterial = (function() {
function SecretKeyMaterial() {
this.s2k_convention = null;
this.s2k = null;
this.iv = null;
this.cipher = null;
this.payload = null;
}
SecretKeyMaterial.prototype.is_dummy = function() {
return (this.s2k != null) && this.s2k.is_dummy();
};
SecretKeyMaterial.prototype.has_private = function() {
return !this.is_dummy();
};
SecretKeyMaterial.prototype.is_locked = function() {
return (this.s2k_convention !== C.s2k_convention.none) && !(this.is_dummy());
};
return SecretKeyMaterial;
})();
exports.S2K = S2K;
exports.SecretKeyMaterial = SecretKeyMaterial;
}).call(this);