pgp-utils
Version:
Simple PGP utils
447 lines (398 loc) • 16.7 kB
JavaScript
// Generated by IcedCoffeeScript 108.0.11
(function() {
var Encoder, Message, Parser, bufeq_fast, clearsign, compute_crc24, crc24_to_base64, crc_table, decode, encode, formatCheckSum, getCheckSum, katch, make_line, strip, trim, uint_to_buffer, verifyCheckSum, _ref;
_ref = require('./util'), trim = _ref.trim, strip = _ref.strip, katch = _ref.katch, bufeq_fast = _ref.bufeq_fast, uint_to_buffer = _ref.uint_to_buffer;
make_line = function(x) {
if (x == null) {
x = "";
}
return "" + x + "\n";
};
exports.Encoder = Encoder = (function() {
function Encoder(C) {
this.C = C;
}
Encoder.prototype.frame = function(t) {
var dash, i;
dash = ((function() {
var _i, _results;
_results = [];
for (i = _i = 0; _i < 5; i = ++_i) {
_results.push("-");
}
return _results;
})()).join('');
return {
begin: make_line(dash + ("BEGIN PGP " + t) + dash),
end: make_line(dash + ("END PGP " + t) + dash)
};
};
Encoder.prototype.b64e = function(d) {
var end, i, parts, raw, w;
raw = d.toString('base64');
w = 64;
parts = (function() {
var _i, _ref1, _results;
_results = [];
for (i = _i = 0, _ref1 = raw.length; w > 0 ? _i < _ref1 : _i > _ref1; i = _i += w) {
end = Math.min(i + w, raw.length);
_results.push(raw.slice(i, end));
}
return _results;
})();
return make_line(parts.join("\n"));
};
Encoder.prototype.header = function() {
var x;
return ((function() {
var _i, _len, _ref1, _results;
_ref1 = ["Version: " + this.C.header.version, "Comment: " + this.C.header.comment];
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
x = _ref1[_i];
_results.push(make_line(x));
}
return _results;
}).call(this)).join('');
};
Encoder.prototype.encode = function(type, data) {
var f;
f = this.frame(type);
return f.begin.concat(this.header(), make_line(), this.b64e(data), formatCheckSum(data), f.end);
};
return Encoder;
})();
exports.clearsign_header = clearsign = function(C, data, hasher_name) {
var enc, f;
enc = new Encoder(C);
f = enc.frame("SIGNED MESSAGE").begin;
return f.concat(make_line("Hash: " + hasher_name), make_line(), data);
};
exports.encode = encode = function(C, type, data) {
return (new Encoder(C)).encode(type, data);
};
crc_table = [0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c, 0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538];
compute_crc24 = function(input, initval) {
var crc, index, j, _i, _ref1;
if (initval == null) {
initval = 0xB704CE;
}
crc = initval;
index = 0;
while ((input.length - index) > 16) {
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 0)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 1)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 2)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 3)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 4)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 5)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 6)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 7)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 8)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 9)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 10)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 11)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 12)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 13)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 14)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index + 15)) & 0xff];
index += 16;
}
for (j = _i = index, _ref1 = input.length; index <= _ref1 ? _i < _ref1 : _i > _ref1; j = index <= _ref1 ? ++_i : --_i) {
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.readUInt8(index++)) & 0xff];
}
return crc & 0xffffff;
};
getCheckSum = function(data, pad) {
var ret;
ret = crc24_to_base64(compute_crc24(data), pad);
return ret;
};
exports.crc24_to_base64 = crc24_to_base64 = function(c, pad) {
if (pad == null) {
pad = true;
}
return (pad ? "=" : '') + uint_to_buffer(32, c).slice(1, 4).toString('base64');
};
formatCheckSum = function(data) {
return make_line(getCheckSum(data, true));
};
verifyCheckSum = function(data, checksum) {
return getCheckSum(data, false) === checksum;
};
exports.Message = Message = (function() {
function Message(_arg) {
this.body = _arg.body, this.type = _arg.type, this.comment = _arg.comment, this.version = _arg.version, this.pre = _arg.pre, this.post = _arg.post;
this.lines = [];
this.fields = {};
this.payload = null;
}
Message.prototype.unsplit = function(lines) {
return lines.join("\n");
};
Message.prototype.raw = function() {
return this.unsplit(this.lines);
};
Message.prototype.finish_unframe = function(_arg) {
var post, pre;
pre = _arg.pre, post = _arg.post;
this.pre = this.unsplit(pre);
this.post = this.unsplit(post);
if (this.clearsign != null) {
return this.clearsign.body = this.unsplit(this.clearsign.lines);
}
};
Message.prototype.make_clearsign = function() {
return this.clearsign = {
headers: {},
lines: [],
body: null
};
};
return Message;
})();
exports.Parser = Parser = (function() {
function Parser(data, _arg) {
this.strict = (_arg != null ? _arg : {}).strict;
this.init(data);
}
Parser.prototype.init = function(data) {
this.data = Buffer.isBuffer(data) ? data.toString('utf8') : data;
this.lines = this.data.split(/\r?\n/);
this.checksum = null;
this.body = null;
this.type = null;
this.ret = null;
return this.last_type = null;
};
Parser.prototype.parse = function() {
this.ret = new Message({});
this.unframe();
this.check_charset();
this.pop_headers();
this.parse_type();
this.strip_empties_in_footer();
if (this.strict) {
this.verify_base64_lines();
}
this.trim_lines();
this.find_checksum();
this.read_body();
this.check_checksum();
return this.ret;
};
Parser.prototype.parse_type = function() {
return this.ret.type = this.ret.fields.type = this.type;
};
Parser.prototype.last_line = function() {
return this.payload.slice(-1)[0];
};
Parser.prototype.mparse = function() {
var go, obj, out;
out = [];
go = true;
while (go) {
this.skip();
if (this.lines.length) {
obj = this.parse();
out.push(obj);
this.init(obj.post);
} else {
go = false;
}
}
return out;
};
Parser.prototype.skip = function() {
var _results;
_results = [];
while (this.lines.length) {
if (this.lines[0].match(/\S+/)) {
break;
}
_results.push(this.lines.shift());
}
return _results;
};
Parser.prototype.read_body = function() {
var dat;
this.ret.payload = this.payload.join("\n");
dat = this.payload.join('');
return this.ret.body = Buffer.from(dat, 'base64');
};
Parser.prototype.check_checksum = function() {
this.ret.fields.checksum = this.checksum;
if ((this.checksum != null) && !verifyCheckSum(this.ret.body, this.checksum)) {
throw new Error("checksum mismatch");
}
};
Parser.prototype.pop_headers = function() {
var l, m, _results;
_results = [];
while (this.payload.length) {
l = this.payload.shift();
if ((m = l.match(/^Version: (.*)/))) {
_results.push(this.ret.version = m[1]);
} else if ((m = l.match(/^Comment: (.*)/)) != null) {
_results.push(this.ret.comment = m[1]);
} else if ((l == null) || (l.length === 0) || (l.match(/^\s+$/))) {
break;
} else if (l.match(/^\S+: .+$/)) {
} else {
throw new Error("bad PGP armor found; expected a newline");
}
}
return _results;
};
Parser.prototype.strip_empties_in_footer = function() {
var _ref1, _results;
_results = [];
while ((_ref1 = this.last_line()) != null ? _ref1.match(/^\s*$/) : void 0) {
_results.push(this.payload.pop());
}
return _results;
};
Parser.prototype.verify_base64_lines = function() {
var line, max_line_length, rxx_b64, _i, _len, _ref1, _results;
rxx_b64 = /^[a-zA-Z0-9\/+=]+$/;
max_line_length = 80;
_ref1 = this.payload;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
line = _ref1[_i];
if (!line.match(rxx_b64)) {
throw new Error("line \"" + line + "\" has characters that are not part of base64");
}
if (line.length > max_line_length) {
throw new Error("armor line longer than " + max_line_length + " characters");
} else {
_results.push(void 0);
}
}
return _results;
};
Parser.prototype.trim_lines = function() {
var p;
return this.payload = (function() {
var _i, _len, _ref1, _results;
_ref1 = this.payload;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
p = _ref1[_i];
_results.push(trim(p));
}
return _results;
}).call(this);
};
Parser.prototype.find_checksum = function() {
var l;
if (((l = this.last_line()) != null) && l[0] === '=') {
return this.checksum = this.payload.pop().slice(1);
}
};
Parser.prototype.v_unframe = function(pre) {
return true;
};
Parser.prototype.unframe = function() {
var found_pre, found_pre_clearsign, found_pre_std, go, line, m, payload, post, pre, ret, rxx, rxx_b, rxx_e, stage, type;
rxx_b = /^(-{5}BEGIN PGP (.*?)-{5}\s*$)/;
rxx_e = /^(-{5}END PGP (.*?)-{5})(.*)$/m;
rxx = rxx_b;
payload = [];
stage = 0;
type = null;
ret = null;
go = true;
pre = [];
post = [];
found_pre_std = function(l, is_last) {
return pre.push(l);
};
found_pre_clearsign = (function(_this) {
return function(l, is_last) {
return _this.ret.clearsign.lines.push(l);
};
})(this);
found_pre = found_pre_std;
while (this.lines.length && go) {
line = this.lines.shift();
switch (stage) {
case -1:
if ((m = line.match(/^([^:]+): (.*)$/))) {
this.ret.clearsign.headers[m[1].toLowerCase()] = m[2];
} else if (line.match(/^\s*$/)) {
stage++;
found_pre = found_pre_clearsign;
} else {
throw new Error("Bad line in clearsign header");
}
this.ret.lines.push(line);
break;
case 0:
if ((m = line.match(rxx_b)) != null) {
found_pre('', true);
this.ret.lines.push((this.ret.clearsign ? line : m[1]));
if (this.type == null) {
this.type = m[2];
}
this.last_type = m[2];
if (m[2] === "SIGNED MESSAGE") {
stage--;
this.ret.make_clearsign();
} else {
stage++;
}
} else {
if (this.ret.clearsign) {
this.ret.lines.push(line);
}
found_pre(line, false);
}
break;
case 1:
if ((m = line.match(rxx_e))) {
this.ret.lines.push(m[1]);
if (m[2] !== this.last_type) {
throw new Error("type mismatch -- begin " + this.last_type + " w/ end " + m[1]);
}
stage++;
post = [m[3]].concat(this.lines);
this.lines = [];
go = false;
} else {
this.ret.lines.push(line);
payload.push(line);
}
}
}
if (stage === 0) {
throw new Error("no header found");
} else if (stage === 1) {
throw new Error("no tailer found");
} else {
this.payload = payload;
return this.ret.finish_unframe({
pre: pre,
post: post
});
}
};
Parser.prototype.check_charset = function() {
if ((this.ret.clearsign == null) && !/^[\n\r\t\x20-\x7e]*$/.test(this.data)) {
throw new Error("invalid character in armor");
}
};
return Parser;
})();
exports.decode = decode = function(data) {
return katch(function() {
return (new Parser(data)).parse();
});
};
exports.mdecode = decode = function(data) {
return katch(function() {
return (new Parser(data)).mparse();
});
};
exports.compute_crc24 = compute_crc24;
}).call(this);