10 changed files with 12612 additions and 0 deletions
@ -0,0 +1,51 @@ |
|||
import { Int10 } from "./int10"; |
|||
export declare class Stream { |
|||
constructor(enc: Stream | number[], pos?: number); |
|||
private enc; |
|||
pos: number; |
|||
get(pos?: number): number; |
|||
hexDigits: string; |
|||
hexByte(b: number): string; |
|||
hexDump(start: number, end: number, raw: boolean): string; |
|||
isASCII(start: number, end: number): boolean; |
|||
parseStringISO(start: number, end: number): string; |
|||
parseStringUTF(start: number, end: number): string; |
|||
parseStringBMP(start: number, end: number): string; |
|||
parseTime(start: number, end: number, shortYear: boolean): string; |
|||
parseInteger(start: number, end: number): string | 0 | -1; |
|||
parseBitString(start: number, end: number, maxLength: number): string; |
|||
parseOctetString(start: number, end: number, maxLength: number): string; |
|||
parseOID(start: number, end: number, maxLength: number): string; |
|||
} |
|||
export declare class ASN1 { |
|||
constructor(stream: Stream, header: number, length: number, tag: ASN1Tag, sub: ASN1[]); |
|||
private stream; |
|||
private header; |
|||
private length; |
|||
private tag; |
|||
sub: ASN1[]; |
|||
typeName(): string; |
|||
content(maxLength: number): string | 0 | -1; |
|||
toString(): string; |
|||
toPrettyString(indent: string): string; |
|||
posStart(): number; |
|||
posContent(): number; |
|||
posEnd(): number; |
|||
toHexString(): string; |
|||
static decodeLength(stream: Stream): number; |
|||
/** |
|||
* Retrieve the hexadecimal value (as a string) of the current ASN.1 element |
|||
* @returns {string} |
|||
* @public |
|||
*/ |
|||
getHexStringValue(): string; |
|||
static decode(str: Stream | number[]): ASN1; |
|||
} |
|||
export declare class ASN1Tag { |
|||
constructor(stream: Stream); |
|||
tagClass: number; |
|||
tagConstructed: boolean; |
|||
tagNumber: number | Int10; |
|||
isUniversal(): boolean; |
|||
isEOC(): boolean; |
|||
} |
@ -0,0 +1,565 @@ |
|||
// ASN.1 JavaScript decoder
|
|||
// Copyright (c) 2008-2014 Lapo Luchini <lapo@lapo.it>
|
|||
// Permission to use, copy, modify, and/or distribute this software for any
|
|||
// purpose with or without fee is hereby granted, provided that the above
|
|||
// copyright notice and this permission notice appear in all copies.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ |
|||
/*global oids */ |
|||
import { Int10 } from "./int10"; |
|||
var ellipsis = "\u2026"; |
|||
var reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; |
|||
var reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; |
|||
function stringCut(str, len) { |
|||
if (str.length > len) { |
|||
str = str.substring(0, len) + ellipsis; |
|||
} |
|||
return str; |
|||
} |
|||
var Stream = /** @class */ (function () { |
|||
function Stream(enc, pos) { |
|||
this.hexDigits = "0123456789ABCDEF"; |
|||
if (enc instanceof Stream) { |
|||
this.enc = enc.enc; |
|||
this.pos = enc.pos; |
|||
} |
|||
else { |
|||
// enc should be an array or a binary string
|
|||
this.enc = enc; |
|||
this.pos = pos; |
|||
} |
|||
} |
|||
Stream.prototype.get = function (pos) { |
|||
if (pos === undefined) { |
|||
pos = this.pos++; |
|||
} |
|||
if (pos >= this.enc.length) { |
|||
throw new Error("Requesting byte offset ".concat(pos, " on a stream of length ").concat(this.enc.length)); |
|||
} |
|||
return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos]; |
|||
}; |
|||
Stream.prototype.hexByte = function (b) { |
|||
return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF); |
|||
}; |
|||
Stream.prototype.hexDump = function (start, end, raw) { |
|||
var s = ""; |
|||
for (var i = start; i < end; ++i) { |
|||
s += this.hexByte(this.get(i)); |
|||
if (raw !== true) { |
|||
switch (i & 0xF) { |
|||
case 0x7: |
|||
s += " "; |
|||
break; |
|||
case 0xF: |
|||
s += "\n"; |
|||
break; |
|||
default: |
|||
s += " "; |
|||
} |
|||
} |
|||
} |
|||
return s; |
|||
}; |
|||
Stream.prototype.isASCII = function (start, end) { |
|||
for (var i = start; i < end; ++i) { |
|||
var c = this.get(i); |
|||
if (c < 32 || c > 176) { |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
}; |
|||
Stream.prototype.parseStringISO = function (start, end) { |
|||
var s = ""; |
|||
for (var i = start; i < end; ++i) { |
|||
s += String.fromCharCode(this.get(i)); |
|||
} |
|||
return s; |
|||
}; |
|||
Stream.prototype.parseStringUTF = function (start, end) { |
|||
var s = ""; |
|||
for (var i = start; i < end;) { |
|||
var c = this.get(i++); |
|||
if (c < 128) { |
|||
s += String.fromCharCode(c); |
|||
} |
|||
else if ((c > 191) && (c < 224)) { |
|||
s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F)); |
|||
} |
|||
else { |
|||
s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F)); |
|||
} |
|||
} |
|||
return s; |
|||
}; |
|||
Stream.prototype.parseStringBMP = function (start, end) { |
|||
var str = ""; |
|||
var hi; |
|||
var lo; |
|||
for (var i = start; i < end;) { |
|||
hi = this.get(i++); |
|||
lo = this.get(i++); |
|||
str += String.fromCharCode((hi << 8) | lo); |
|||
} |
|||
return str; |
|||
}; |
|||
Stream.prototype.parseTime = function (start, end, shortYear) { |
|||
var s = this.parseStringISO(start, end); |
|||
var m = (shortYear ? reTimeS : reTimeL).exec(s); |
|||
if (!m) { |
|||
return "Unrecognized time: " + s; |
|||
} |
|||
if (shortYear) { |
|||
// to avoid querying the timer, use the fixed range [1970, 2069]
|
|||
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
|
|||
m[1] = +m[1]; |
|||
m[1] += (+m[1] < 70) ? 2000 : 1900; |
|||
} |
|||
s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4]; |
|||
if (m[5]) { |
|||
s += ":" + m[5]; |
|||
if (m[6]) { |
|||
s += ":" + m[6]; |
|||
if (m[7]) { |
|||
s += "." + m[7]; |
|||
} |
|||
} |
|||
} |
|||
if (m[8]) { |
|||
s += " UTC"; |
|||
if (m[8] != "Z") { |
|||
s += m[8]; |
|||
if (m[9]) { |
|||
s += ":" + m[9]; |
|||
} |
|||
} |
|||
} |
|||
return s; |
|||
}; |
|||
Stream.prototype.parseInteger = function (start, end) { |
|||
var v = this.get(start); |
|||
var neg = (v > 127); |
|||
var pad = neg ? 255 : 0; |
|||
var len; |
|||
var s = ""; |
|||
// skip unuseful bits (not allowed in DER)
|
|||
while (v == pad && ++start < end) { |
|||
v = this.get(start); |
|||
} |
|||
len = end - start; |
|||
if (len === 0) { |
|||
return neg ? -1 : 0; |
|||
} |
|||
// show bit length of huge integers
|
|||
if (len > 4) { |
|||
s = v; |
|||
len <<= 3; |
|||
while (((+s ^ pad) & 0x80) == 0) { |
|||
s = +s << 1; |
|||
--len; |
|||
} |
|||
s = "(" + len + " bit)\n"; |
|||
} |
|||
// decode the integer
|
|||
if (neg) { |
|||
v = v - 256; |
|||
} |
|||
var n = new Int10(v); |
|||
for (var i = start + 1; i < end; ++i) { |
|||
n.mulAdd(256, this.get(i)); |
|||
} |
|||
return s + n.toString(); |
|||
}; |
|||
Stream.prototype.parseBitString = function (start, end, maxLength) { |
|||
var unusedBit = this.get(start); |
|||
var lenBit = ((end - start - 1) << 3) - unusedBit; |
|||
var intro = "(" + lenBit + " bit)\n"; |
|||
var s = ""; |
|||
for (var i = start + 1; i < end; ++i) { |
|||
var b = this.get(i); |
|||
var skip = (i == end - 1) ? unusedBit : 0; |
|||
for (var j = 7; j >= skip; --j) { |
|||
s += (b >> j) & 1 ? "1" : "0"; |
|||
} |
|||
if (s.length > maxLength) { |
|||
return intro + stringCut(s, maxLength); |
|||
} |
|||
} |
|||
return intro + s; |
|||
}; |
|||
Stream.prototype.parseOctetString = function (start, end, maxLength) { |
|||
if (this.isASCII(start, end)) { |
|||
return stringCut(this.parseStringISO(start, end), maxLength); |
|||
} |
|||
var len = end - start; |
|||
var s = "(" + len + " byte)\n"; |
|||
maxLength /= 2; // we work in bytes
|
|||
if (len > maxLength) { |
|||
end = start + maxLength; |
|||
} |
|||
for (var i = start; i < end; ++i) { |
|||
s += this.hexByte(this.get(i)); |
|||
} |
|||
if (len > maxLength) { |
|||
s += ellipsis; |
|||
} |
|||
return s; |
|||
}; |
|||
Stream.prototype.parseOID = function (start, end, maxLength) { |
|||
var s = ""; |
|||
var n = new Int10(); |
|||
var bits = 0; |
|||
for (var i = start; i < end; ++i) { |
|||
var v = this.get(i); |
|||
n.mulAdd(128, v & 0x7F); |
|||
bits += 7; |
|||
if (!(v & 0x80)) { // finished
|
|||
if (s === "") { |
|||
n = n.simplify(); |
|||
if (n instanceof Int10) { |
|||
n.sub(80); |
|||
s = "2." + n.toString(); |
|||
} |
|||
else { |
|||
var m = n < 80 ? n < 40 ? 0 : 1 : 2; |
|||
s = m + "." + (n - m * 40); |
|||
} |
|||
} |
|||
else { |
|||
s += "." + n.toString(); |
|||
} |
|||
if (s.length > maxLength) { |
|||
return stringCut(s, maxLength); |
|||
} |
|||
n = new Int10(); |
|||
bits = 0; |
|||
} |
|||
} |
|||
if (bits > 0) { |
|||
s += ".incomplete"; |
|||
} |
|||
return s; |
|||
}; |
|||
return Stream; |
|||
}()); |
|||
export { Stream }; |
|||
var ASN1 = /** @class */ (function () { |
|||
function ASN1(stream, header, length, tag, sub) { |
|||
if (!(tag instanceof ASN1Tag)) { |
|||
throw new Error("Invalid tag value."); |
|||
} |
|||
this.stream = stream; |
|||
this.header = header; |
|||
this.length = length; |
|||
this.tag = tag; |
|||
this.sub = sub; |
|||
} |
|||
ASN1.prototype.typeName = function () { |
|||
switch (this.tag.tagClass) { |
|||
case 0: // universal
|
|||
switch (this.tag.tagNumber) { |
|||
case 0x00: |
|||
return "EOC"; |
|||
case 0x01: |
|||
return "BOOLEAN"; |
|||
case 0x02: |
|||
return "INTEGER"; |
|||
case 0x03: |
|||
return "BIT_STRING"; |
|||
case 0x04: |
|||
return "OCTET_STRING"; |
|||
case 0x05: |
|||
return "NULL"; |
|||
case 0x06: |
|||
return "OBJECT_IDENTIFIER"; |
|||
case 0x07: |
|||
return "ObjectDescriptor"; |
|||
case 0x08: |
|||
return "EXTERNAL"; |
|||
case 0x09: |
|||
return "REAL"; |
|||
case 0x0A: |
|||
return "ENUMERATED"; |
|||
case 0x0B: |
|||
return "EMBEDDED_PDV"; |
|||
case 0x0C: |
|||
return "UTF8String"; |
|||
case 0x10: |
|||
return "SEQUENCE"; |
|||
case 0x11: |
|||
return "SET"; |
|||
case 0x12: |
|||
return "NumericString"; |
|||
case 0x13: |
|||
return "PrintableString"; // ASCII subset
|
|||
case 0x14: |
|||
return "TeletexString"; // aka T61String
|
|||
case 0x15: |
|||
return "VideotexString"; |
|||
case 0x16: |
|||
return "IA5String"; // ASCII
|
|||
case 0x17: |
|||
return "UTCTime"; |
|||
case 0x18: |
|||
return "GeneralizedTime"; |
|||
case 0x19: |
|||
return "GraphicString"; |
|||
case 0x1A: |
|||
return "VisibleString"; // ASCII subset
|
|||
case 0x1B: |
|||
return "GeneralString"; |
|||
case 0x1C: |
|||
return "UniversalString"; |
|||
case 0x1E: |
|||
return "BMPString"; |
|||
} |
|||
return "Universal_" + this.tag.tagNumber.toString(); |
|||
case 1: |
|||
return "Application_" + this.tag.tagNumber.toString(); |
|||
case 2: |
|||
return "[" + this.tag.tagNumber.toString() + "]"; // Context
|
|||
case 3: |
|||
return "Private_" + this.tag.tagNumber.toString(); |
|||
} |
|||
}; |
|||
ASN1.prototype.content = function (maxLength) { |
|||
if (this.tag === undefined) { |
|||
return null; |
|||
} |
|||
if (maxLength === undefined) { |
|||
maxLength = Infinity; |
|||
} |
|||
var content = this.posContent(); |
|||
var len = Math.abs(this.length); |
|||
if (!this.tag.isUniversal()) { |
|||
if (this.sub !== null) { |
|||
return "(" + this.sub.length + " elem)"; |
|||
} |
|||
return this.stream.parseOctetString(content, content + len, maxLength); |
|||
} |
|||
switch (this.tag.tagNumber) { |
|||
case 0x01: // BOOLEAN
|
|||
return (this.stream.get(content) === 0) ? "false" : "true"; |
|||
case 0x02: // INTEGER
|
|||
return this.stream.parseInteger(content, content + len); |
|||
case 0x03: // BIT_STRING
|
|||
return this.sub ? "(" + this.sub.length + " elem)" : |
|||
this.stream.parseBitString(content, content + len, maxLength); |
|||
case 0x04: // OCTET_STRING
|
|||
return this.sub ? "(" + this.sub.length + " elem)" : |
|||
this.stream.parseOctetString(content, content + len, maxLength); |
|||
// case 0x05: // NULL
|
|||
case 0x06: // OBJECT_IDENTIFIER
|
|||
return this.stream.parseOID(content, content + len, maxLength); |
|||
// case 0x07: // ObjectDescriptor
|
|||
// case 0x08: // EXTERNAL
|
|||
// case 0x09: // REAL
|
|||
// case 0x0A: // ENUMERATED
|
|||
// case 0x0B: // EMBEDDED_PDV
|
|||
case 0x10: // SEQUENCE
|
|||
case 0x11: // SET
|
|||
if (this.sub !== null) { |
|||
return "(" + this.sub.length + " elem)"; |
|||
} |
|||
else { |
|||
return "(no elem)"; |
|||
} |
|||
case 0x0C: // UTF8String
|
|||
return stringCut(this.stream.parseStringUTF(content, content + len), maxLength); |
|||
case 0x12: // NumericString
|
|||
case 0x13: // PrintableString
|
|||
case 0x14: // TeletexString
|
|||
case 0x15: // VideotexString
|
|||
case 0x16: // IA5String
|
|||
// case 0x19: // GraphicString
|
|||
case 0x1A: // VisibleString
|
|||
// case 0x1B: // GeneralString
|
|||
// case 0x1C: // UniversalString
|
|||
return stringCut(this.stream.parseStringISO(content, content + len), maxLength); |
|||
case 0x1E: // BMPString
|
|||
return stringCut(this.stream.parseStringBMP(content, content + len), maxLength); |
|||
case 0x17: // UTCTime
|
|||
case 0x18: // GeneralizedTime
|
|||
return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17)); |
|||
} |
|||
return null; |
|||
}; |
|||
ASN1.prototype.toString = function () { |
|||
return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]"; |
|||
}; |
|||
ASN1.prototype.toPrettyString = function (indent) { |
|||
if (indent === undefined) { |
|||
indent = ""; |
|||
} |
|||
var s = indent + this.typeName() + " @" + this.stream.pos; |
|||
if (this.length >= 0) { |
|||
s += "+"; |
|||
} |
|||
s += this.length; |
|||
if (this.tag.tagConstructed) { |
|||
s += " (constructed)"; |
|||
} |
|||
else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) { |
|||
s += " (encapsulates)"; |
|||
} |
|||
s += "\n"; |
|||
if (this.sub !== null) { |
|||
indent += " "; |
|||
for (var i = 0, max = this.sub.length; i < max; ++i) { |
|||
s += this.sub[i].toPrettyString(indent); |
|||
} |
|||
} |
|||
return s; |
|||
}; |
|||
ASN1.prototype.posStart = function () { |
|||
return this.stream.pos; |
|||
}; |
|||
ASN1.prototype.posContent = function () { |
|||
return this.stream.pos + this.header; |
|||
}; |
|||
ASN1.prototype.posEnd = function () { |
|||
return this.stream.pos + this.header + Math.abs(this.length); |
|||
}; |
|||
ASN1.prototype.toHexString = function () { |
|||
return this.stream.hexDump(this.posStart(), this.posEnd(), true); |
|||
}; |
|||
ASN1.decodeLength = function (stream) { |
|||
var buf = stream.get(); |
|||
var len = buf & 0x7F; |
|||
if (len == buf) { |
|||
return len; |
|||
} |
|||
// no reason to use Int10, as it would be a huge buffer anyways
|
|||
if (len > 6) { |
|||
throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1)); |
|||
} |
|||
if (len === 0) { |
|||
return null; |
|||
} // undefined
|
|||
buf = 0; |
|||
for (var i = 0; i < len; ++i) { |
|||
buf = (buf * 256) + stream.get(); |
|||
} |
|||
return buf; |
|||
}; |
|||
/** |
|||
* Retrieve the hexadecimal value (as a string) of the current ASN.1 element |
|||
* @returns {string} |
|||
* @public |
|||
*/ |
|||
ASN1.prototype.getHexStringValue = function () { |
|||
var hexString = this.toHexString(); |
|||
var offset = this.header * 2; |
|||
var length = this.length * 2; |
|||
return hexString.substr(offset, length); |
|||
}; |
|||
ASN1.decode = function (str) { |
|||
var stream; |
|||
if (!(str instanceof Stream)) { |
|||
stream = new Stream(str, 0); |
|||
} |
|||
else { |
|||
stream = str; |
|||
} |
|||
var streamStart = new Stream(stream); |
|||
var tag = new ASN1Tag(stream); |
|||
var len = ASN1.decodeLength(stream); |
|||
var start = stream.pos; |
|||
var header = start - streamStart.pos; |
|||
var sub = null; |
|||
var getSub = function () { |
|||
var ret = []; |
|||
if (len !== null) { |
|||
// definite length
|
|||
var end = start + len; |
|||
while (stream.pos < end) { |
|||
ret[ret.length] = ASN1.decode(stream); |
|||
} |
|||
if (stream.pos != end) { |
|||
throw new Error("Content size is not correct for container starting at offset " + start); |
|||
} |
|||
} |
|||
else { |
|||
// undefined length
|
|||
try { |
|||
for (;;) { |
|||
var s = ASN1.decode(stream); |
|||
if (s.tag.isEOC()) { |
|||
break; |
|||
} |
|||
ret[ret.length] = s; |
|||
} |
|||
len = start - stream.pos; // undefined lengths are represented as negative values
|
|||
} |
|||
catch (e) { |
|||
throw new Error("Exception while decoding undefined length content: " + e); |
|||
} |
|||
} |
|||
return ret; |
|||
}; |
|||
if (tag.tagConstructed) { |
|||
// must have valid content
|
|||
sub = getSub(); |
|||
} |
|||
else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) { |
|||
// sometimes BitString and OctetString are used to encapsulate ASN.1
|
|||
try { |
|||
if (tag.tagNumber == 0x03) { |
|||
if (stream.get() != 0) { |
|||
throw new Error("BIT STRINGs with unused bits cannot encapsulate."); |
|||
} |
|||
} |
|||
sub = getSub(); |
|||
for (var i = 0; i < sub.length; ++i) { |
|||
if (sub[i].tag.isEOC()) { |
|||
throw new Error("EOC is not supposed to be actual content."); |
|||
} |
|||
} |
|||
} |
|||
catch (e) { |
|||
// but silently ignore when they don't
|
|||
sub = null; |
|||
} |
|||
} |
|||
if (sub === null) { |
|||
if (len === null) { |
|||
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start); |
|||
} |
|||
stream.pos = start + Math.abs(len); |
|||
} |
|||
return new ASN1(streamStart, header, len, tag, sub); |
|||
}; |
|||
return ASN1; |
|||
}()); |
|||
export { ASN1 }; |
|||
var ASN1Tag = /** @class */ (function () { |
|||
function ASN1Tag(stream) { |
|||
var buf = stream.get(); |
|||
this.tagClass = buf >> 6; |
|||
this.tagConstructed = ((buf & 0x20) !== 0); |
|||
this.tagNumber = buf & 0x1F; |
|||
if (this.tagNumber == 0x1F) { // long tag
|
|||
var n = new Int10(); |
|||
do { |
|||
buf = stream.get(); |
|||
n.mulAdd(128, buf & 0x7F); |
|||
} while (buf & 0x80); |
|||
this.tagNumber = n.simplify(); |
|||
} |
|||
} |
|||
ASN1Tag.prototype.isUniversal = function () { |
|||
return this.tagClass === 0x00; |
|||
}; |
|||
ASN1Tag.prototype.isEOC = function () { |
|||
return this.tagClass === 0x00 && this.tagNumber === 0x00; |
|||
}; |
|||
return ASN1Tag; |
|||
}()); |
|||
export { ASN1Tag }; |
@ -0,0 +1,5 @@ |
|||
export declare const Base64: { |
|||
decode(a: string): number[]; |
|||
re: RegExp; |
|||
unarmor(a: string): number[]; |
|||
}; |
@ -0,0 +1,88 @@ |
|||
// Base64 JavaScript decoder
|
|||
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
|||
// Permission to use, copy, modify, and/or distribute this software for any
|
|||
// purpose with or without fee is hereby granted, provided that the above
|
|||
// copyright notice and this permission notice appear in all copies.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ |
|||
var decoder; |
|||
export var Base64 = { |
|||
decode: function (a) { |
|||
var i; |
|||
if (decoder === undefined) { |
|||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|||
var ignore = "= \f\n\r\t\u00A0\u2028\u2029"; |
|||
decoder = Object.create(null); |
|||
for (i = 0; i < 64; ++i) { |
|||
decoder[b64.charAt(i)] = i; |
|||
} |
|||
decoder['-'] = 62; //+
|
|||
decoder['_'] = 63; //-
|
|||
for (i = 0; i < ignore.length; ++i) { |
|||
decoder[ignore.charAt(i)] = -1; |
|||
} |
|||
} |
|||
var out = []; |
|||
var bits = 0; |
|||
var char_count = 0; |
|||
for (i = 0; i < a.length; ++i) { |
|||
var c = a.charAt(i); |
|||
if (c == "=") { |
|||
break; |
|||
} |
|||
c = decoder[c]; |
|||
if (c == -1) { |
|||
continue; |
|||
} |
|||
if (c === undefined) { |
|||
throw new Error("Illegal character at offset " + i); |
|||
} |
|||
bits |= c; |
|||
if (++char_count >= 4) { |
|||
out[out.length] = (bits >> 16); |
|||
out[out.length] = (bits >> 8) & 0xFF; |
|||
out[out.length] = bits & 0xFF; |
|||
bits = 0; |
|||
char_count = 0; |
|||
} |
|||
else { |
|||
bits <<= 6; |
|||
} |
|||
} |
|||
switch (char_count) { |
|||
case 1: |
|||
throw new Error("Base64 encoding incomplete: at least 2 bits missing"); |
|||
case 2: |
|||
out[out.length] = (bits >> 10); |
|||
break; |
|||
case 3: |
|||
out[out.length] = (bits >> 16); |
|||
out[out.length] = (bits >> 8) & 0xFF; |
|||
break; |
|||
} |
|||
return out; |
|||
}, |
|||
re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/, |
|||
unarmor: function (a) { |
|||
var m = Base64.re.exec(a); |
|||
if (m) { |
|||
if (m[1]) { |
|||
a = m[1]; |
|||
} |
|||
else if (m[2]) { |
|||
a = m[2]; |
|||
} |
|||
else { |
|||
throw new Error("RegExp out of sync"); |
|||
} |
|||
} |
|||
return Base64.decode(a); |
|||
} |
|||
}; |
@ -0,0 +1,3 @@ |
|||
export declare const Hex: { |
|||
decode(a: string): number[]; |
|||
}; |
@ -0,0 +1,64 @@ |
|||
// Hex JavaScript decoder
|
|||
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
|||
// Permission to use, copy, modify, and/or distribute this software for any
|
|||
// purpose with or without fee is hereby granted, provided that the above
|
|||
// copyright notice and this permission notice appear in all copies.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ |
|||
var decoder; |
|||
export var Hex = { |
|||
decode: function (a) { |
|||
var i; |
|||
if (decoder === undefined) { |
|||
var hex = "0123456789ABCDEF"; |
|||
var ignore = " \f\n\r\t\u00A0\u2028\u2029"; |
|||
decoder = {}; |
|||
for (i = 0; i < 16; ++i) { |
|||
decoder[hex.charAt(i)] = i; |
|||
} |
|||
hex = hex.toLowerCase(); |
|||
for (i = 10; i < 16; ++i) { |
|||
decoder[hex.charAt(i)] = i; |
|||
} |
|||
for (i = 0; i < ignore.length; ++i) { |
|||
decoder[ignore.charAt(i)] = -1; |
|||
} |
|||
} |
|||
var out = []; |
|||
var bits = 0; |
|||
var char_count = 0; |
|||
for (i = 0; i < a.length; ++i) { |
|||
var c = a.charAt(i); |
|||
if (c == "=") { |
|||
break; |
|||
} |
|||
c = decoder[c]; |
|||
if (c == -1) { |
|||
continue; |
|||
} |
|||
if (c === undefined) { |
|||
throw new Error("Illegal character at offset " + i); |
|||
} |
|||
bits |= c; |
|||
if (++char_count >= 2) { |
|||
out[out.length] = bits; |
|||
bits = 0; |
|||
char_count = 0; |
|||
} |
|||
else { |
|||
bits <<= 4; |
|||
} |
|||
} |
|||
if (char_count) { |
|||
throw new Error("Hex encoding incomplete: 4 bits missing"); |
|||
} |
|||
return out; |
|||
} |
|||
}; |
@ -0,0 +1,9 @@ |
|||
export declare class Int10 { |
|||
constructor(value?: string | number); |
|||
mulAdd(m: number, c: number): void; |
|||
sub(c: number): void; |
|||
toString(base?: number): string; |
|||
valueOf(): number; |
|||
simplify(): number | this; |
|||
private buf; |
|||
} |
@ -0,0 +1,87 @@ |
|||
// Big integer base-10 printing library
|
|||
// Copyright (c) 2014 Lapo Luchini <lapo@lapo.it>
|
|||
// Permission to use, copy, modify, and/or distribute this software for any
|
|||
// purpose with or without fee is hereby granted, provided that the above
|
|||
// copyright notice and this permission notice appear in all copies.
|
|||
//
|
|||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */ |
|||
var max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256
|
|||
var Int10 = /** @class */ (function () { |
|||
function Int10(value) { |
|||
this.buf = [+value || 0]; |
|||
} |
|||
Int10.prototype.mulAdd = function (m, c) { |
|||
// assert(m <= 256)
|
|||
var b = this.buf; |
|||
var l = b.length; |
|||
var i; |
|||
var t; |
|||
for (i = 0; i < l; ++i) { |
|||
t = b[i] * m + c; |
|||
if (t < max) { |
|||
c = 0; |
|||
} |
|||
else { |
|||
c = 0 | (t / max); |
|||
t -= c * max; |
|||
} |
|||
b[i] = t; |
|||
} |
|||
if (c > 0) { |
|||
b[i] = c; |
|||
} |
|||
}; |
|||
Int10.prototype.sub = function (c) { |
|||
// assert(m <= 256)
|
|||
var b = this.buf; |
|||
var l = b.length; |
|||
var i; |
|||
var t; |
|||
for (i = 0; i < l; ++i) { |
|||
t = b[i] - c; |
|||
if (t < 0) { |
|||
t += max; |
|||
c = 1; |
|||
} |
|||
else { |
|||
c = 0; |
|||
} |
|||
b[i] = t; |
|||
} |
|||
while (b[b.length - 1] === 0) { |
|||
b.pop(); |
|||
} |
|||
}; |
|||
Int10.prototype.toString = function (base) { |
|||
if ((base || 10) != 10) { |
|||
throw new Error("only base 10 is supported"); |
|||
} |
|||
var b = this.buf; |
|||
var s = b[b.length - 1].toString(); |
|||
for (var i = b.length - 2; i >= 0; --i) { |
|||
s += (max + b[i]).toString().substring(1); |
|||
} |
|||
return s; |
|||
}; |
|||
Int10.prototype.valueOf = function () { |
|||
var b = this.buf; |
|||
var v = 0; |
|||
for (var i = b.length - 1; i >= 0; --i) { |
|||
v = v * max + b[i]; |
|||
} |
|||
return v; |
|||
}; |
|||
Int10.prototype.simplify = function () { |
|||
var b = this.buf; |
|||
return (b.length == 1) ? b[0] : this; |
|||
}; |
|||
return Int10; |
|||
}()); |
|||
export { Int10 }; |
File diff suppressed because it is too large
File diff suppressed because it is too large
Loading…
Reference in new issue