UNPKG

pgp-utils

Version:
447 lines (398 loc) 16.7 kB
// 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);