WTF WORKS IF U TRY A TON???????????
This commit is contained in:
parent
fbe96f6469
commit
3099109d0d
161
javascript/asn1-parser.js
Normal file
161
javascript/asn1-parser.js
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
// Copyright 2018 AJ ONeal. All rights reserved
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
;(function (exports) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (!exports.ASN1) { exports.ASN1 = {}; }
|
||||||
|
if (!exports.Enc) { exports.Enc = {}; }
|
||||||
|
if (!exports.PEM) { exports.PEM = {}; }
|
||||||
|
|
||||||
|
var ASN1 = exports.ASN1;
|
||||||
|
var Enc = exports.Enc;
|
||||||
|
var PEM = exports.PEM;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parser
|
||||||
|
//
|
||||||
|
|
||||||
|
// Although I've only seen 9 max in https certificates themselves,
|
||||||
|
// but each domain list could have up to 100
|
||||||
|
ASN1.ELOOPN = 102;
|
||||||
|
ASN1.ELOOP = "uASN1.js Error: iterated over " + ASN1.ELOOPN + "+ elements (probably a malformed file)";
|
||||||
|
// I've seen https certificates go 29 deep
|
||||||
|
ASN1.EDEEPN = 60;
|
||||||
|
ASN1.EDEEP = "uASN1.js Error: element nested " + ASN1.EDEEPN + "+ layers deep (probably a malformed file)";
|
||||||
|
// Container Types are Sequence 0x30, Container Array? (0xA0, 0xA1)
|
||||||
|
// Value Types are Boolean 0x01, Integer 0x02, Null 0x05, Object ID 0x06, String 0x0C, 0x16, 0x13, 0x1e Value Array? (0x82)
|
||||||
|
// Bit String (0x03) and Octet String (0x04) may be values or containers
|
||||||
|
// Sometimes Bit String is used as a container (RSA Pub Spki)
|
||||||
|
ASN1.CTYPES = [ 0x30, 0x31, 0xa0, 0xa1 ];
|
||||||
|
ASN1.VTYPES = [ 0x01, 0x02, 0x05, 0x06, 0x0c, 0x82 ];
|
||||||
|
ASN1.parse = function parseAsn1Helper(buf) {
|
||||||
|
//var ws = ' ';
|
||||||
|
function parseAsn1(buf, depth, eager) {
|
||||||
|
if (depth.length >= ASN1.EDEEPN) { throw new Error(ASN1.EDEEP); }
|
||||||
|
|
||||||
|
var index = 2; // we know, at minimum, data starts after type (0) and lengthSize (1)
|
||||||
|
var asn1 = { type: buf[0], lengthSize: 0, length: buf[1] };
|
||||||
|
var child;
|
||||||
|
var iters = 0;
|
||||||
|
var adjust = 0;
|
||||||
|
var adjustedLen;
|
||||||
|
|
||||||
|
// Determine how many bytes the length uses, and what it is
|
||||||
|
if (0x80 & asn1.length) {
|
||||||
|
asn1.lengthSize = 0x7f & asn1.length;
|
||||||
|
// I think that buf->hex->int solves the problem of Endianness... not sure
|
||||||
|
asn1.length = parseInt(Enc.bufToHex(buf.slice(index, index + asn1.lengthSize)), 16);
|
||||||
|
index += asn1.lengthSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// High-order bit Integers have a leading 0x00 to signify that they are positive.
|
||||||
|
// Bit Streams use the first byte to signify padding, which x.509 doesn't use.
|
||||||
|
if (0x00 === buf[index] && (0x02 === asn1.type || 0x03 === asn1.type)) {
|
||||||
|
// However, 0x00 on its own is a valid number
|
||||||
|
if (asn1.length > 1) {
|
||||||
|
index += 1;
|
||||||
|
adjust = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adjustedLen = asn1.length + adjust;
|
||||||
|
|
||||||
|
//console.warn(depth.join(ws) + '0x' + Enc.numToHex(asn1.type), index, 'len:', asn1.length, asn1);
|
||||||
|
|
||||||
|
function parseChildren(eager) {
|
||||||
|
asn1.children = [];
|
||||||
|
//console.warn('1 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', 0);
|
||||||
|
while (iters < ASN1.ELOOPN && index < (2 + asn1.length + asn1.lengthSize)) {
|
||||||
|
iters += 1;
|
||||||
|
depth.length += 1;
|
||||||
|
child = parseAsn1(buf.slice(index, index + adjustedLen), depth, eager);
|
||||||
|
depth.length -= 1;
|
||||||
|
// The numbers don't match up exactly and I don't remember why...
|
||||||
|
// probably something with adjustedLen or some such, but the tests pass
|
||||||
|
index += (2 + child.lengthSize + child.length);
|
||||||
|
//console.warn('2 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', (2 + child.lengthSize + child.length));
|
||||||
|
if (index > (2 + asn1.lengthSize + asn1.length)) {
|
||||||
|
if (!eager) { console.error(JSON.stringify(asn1, ASN1._replacer, 2)); }
|
||||||
|
throw new Error("Parse error: child value length (" + child.length
|
||||||
|
+ ") is greater than remaining parent length (" + (asn1.length - index)
|
||||||
|
+ " = " + asn1.length + " - " + index + ")");
|
||||||
|
}
|
||||||
|
asn1.children.push(child);
|
||||||
|
//console.warn(depth.join(ws) + '0x' + Enc.numToHex(asn1.type), index, 'len:', asn1.length, asn1);
|
||||||
|
}
|
||||||
|
if (index !== (2 + asn1.lengthSize + asn1.length)) {
|
||||||
|
//console.warn('index:', index, 'length:', (2 + asn1.lengthSize + asn1.length));
|
||||||
|
throw new Error("premature end-of-file");
|
||||||
|
}
|
||||||
|
if (iters >= ASN1.ELOOPN) { throw new Error(ASN1.ELOOP); }
|
||||||
|
|
||||||
|
delete asn1.value;
|
||||||
|
return asn1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse into types that are _always_ containers
|
||||||
|
if (-1 !== ASN1.CTYPES.indexOf(asn1.type)) { return parseChildren(eager); }
|
||||||
|
|
||||||
|
// Return types that are _always_ values
|
||||||
|
asn1.value = buf.slice(index, index + adjustedLen);
|
||||||
|
if (-1 !== ASN1.VTYPES.indexOf(asn1.type)) { return asn1; }
|
||||||
|
|
||||||
|
// For ambigious / unknown types, recurse and return on failure
|
||||||
|
// (and return child array size to zero)
|
||||||
|
try { return parseChildren(true); }
|
||||||
|
catch(e) { asn1.children.length = 0; return asn1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
var asn1 = parseAsn1(buf, []);
|
||||||
|
var len = buf.byteLength || buf.length;
|
||||||
|
if (len !== 2 + asn1.lengthSize + asn1.length) {
|
||||||
|
throw new Error("Length of buffer does not match length of ASN.1 sequence.");
|
||||||
|
}
|
||||||
|
return asn1;
|
||||||
|
};
|
||||||
|
ASN1._replacer = function (k, v) {
|
||||||
|
if ('type' === k) { return '0x' + Enc.numToHex(v); }
|
||||||
|
if (v && 'value' === k) { return '0x' + Enc.bufToHex(v.data || v); }
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
// don't replace the full parseBlock, if it exists
|
||||||
|
PEM.parseBlock = PEM.parseBlock || function (str) {
|
||||||
|
var der = str.split(/\n/).filter(function (line) {
|
||||||
|
return !/-----/.test(line);
|
||||||
|
}).join('');
|
||||||
|
return { der: Enc.base64ToBuf(der) };
|
||||||
|
};
|
||||||
|
|
||||||
|
Enc.base64ToBuf = function (b64) {
|
||||||
|
return Enc.binToBuf(atob(b64));
|
||||||
|
};
|
||||||
|
Enc.binToBuf = function (bin) {
|
||||||
|
var arr = bin.split('').map(function (ch) {
|
||||||
|
return ch.charCodeAt(0);
|
||||||
|
});
|
||||||
|
return 'undefined' !== typeof Uint8Array ? new Uint8Array(arr) : arr;
|
||||||
|
};
|
||||||
|
Enc.bufToHex = function (u8) {
|
||||||
|
var hex = [];
|
||||||
|
var i, h;
|
||||||
|
var len = (u8.byteLength || u8.length);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 1) {
|
||||||
|
h = u8[i].toString(16);
|
||||||
|
if (h.length % 2) { h = '0' + h; }
|
||||||
|
hex.push(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex.join('').toLowerCase();
|
||||||
|
};
|
||||||
|
Enc.numToHex = function (d) {
|
||||||
|
d = d.toString(16);
|
||||||
|
if (d.length % 2) {
|
||||||
|
return '0' + d;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
}('undefined' !== typeof window ? window : module.exports));
|
37492
javascript/classes.js
37492
javascript/classes.js
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,17 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>eagler</title>
|
<title>eagler</title>
|
||||||
<script type="text/javascript" src="jsencrypt.min.js"></script>
|
|
||||||
|
<script type="text/javascript" src="jsbn/jsbn.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/jsbn2.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/prng4.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/rng.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/rsa.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/rsa2.js"></script>
|
||||||
|
<script type="text/javascript" src="jsbn/base64.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="asn1-parser.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="classes.js"></script>
|
<script type="text/javascript" src="classes.js"></script>
|
||||||
<!--script src="https://unpkg.com/@peculiar/x509"></script-->
|
<!--script src="https://unpkg.com/@peculiar/x509"></script-->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
71
javascript/jsbn/base64.js
Normal file
71
javascript/jsbn/base64.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
var b64padchar="=";
|
||||||
|
|
||||||
|
function hex2b64(h) {
|
||||||
|
var i;
|
||||||
|
var c;
|
||||||
|
var ret = "";
|
||||||
|
for(i = 0; i+3 <= h.length; i+=3) {
|
||||||
|
c = parseInt(h.substring(i,i+3),16);
|
||||||
|
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
||||||
|
}
|
||||||
|
if(i+1 == h.length) {
|
||||||
|
c = parseInt(h.substring(i,i+1),16);
|
||||||
|
ret += b64map.charAt(c << 2);
|
||||||
|
}
|
||||||
|
else if(i+2 == h.length) {
|
||||||
|
c = parseInt(h.substring(i,i+2),16);
|
||||||
|
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
||||||
|
}
|
||||||
|
while((ret.length & 3) > 0) ret += b64padchar;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert a base64 string to hex
|
||||||
|
function b64tohex(s) {
|
||||||
|
var ret = ""
|
||||||
|
var i;
|
||||||
|
var k = 0; // b64 state, 0-3
|
||||||
|
var slop;
|
||||||
|
for(i = 0; i < s.length; ++i) {
|
||||||
|
if(s.charAt(i) == b64padchar) break;
|
||||||
|
v = b64map.indexOf(s.charAt(i));
|
||||||
|
if(v < 0) continue;
|
||||||
|
if(k == 0) {
|
||||||
|
ret += int2char(v >> 2);
|
||||||
|
slop = v & 3;
|
||||||
|
k = 1;
|
||||||
|
}
|
||||||
|
else if(k == 1) {
|
||||||
|
ret += int2char((slop << 2) | (v >> 4));
|
||||||
|
slop = v & 0xf;
|
||||||
|
k = 2;
|
||||||
|
}
|
||||||
|
else if(k == 2) {
|
||||||
|
ret += int2char(slop);
|
||||||
|
ret += int2char(v >> 2);
|
||||||
|
slop = v & 3;
|
||||||
|
k = 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret += int2char((slop << 2) | (v >> 4));
|
||||||
|
ret += int2char(v & 0xf);
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(k == 1)
|
||||||
|
ret += int2char(slop << 2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert a base64 string to a byte/number array
|
||||||
|
function b64toBA(s) {
|
||||||
|
//piggyback on b64tohex for now, optimize later
|
||||||
|
var h = b64tohex(s);
|
||||||
|
var i;
|
||||||
|
var a = new Array();
|
||||||
|
for(i = 0; 2*i < h.length; ++i) {
|
||||||
|
a[i] = parseInt(h.substring(2*i,2*i+2),16);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
559
javascript/jsbn/jsbn.js
Normal file
559
javascript/jsbn/jsbn.js
Normal file
|
@ -0,0 +1,559 @@
|
||||||
|
// Copyright (c) 2005 Tom Wu
|
||||||
|
// All Rights Reserved.
|
||||||
|
// See "LICENSE" for details.
|
||||||
|
|
||||||
|
// Basic JavaScript BN library - subset useful for RSA encryption.
|
||||||
|
|
||||||
|
// Bits per digit
|
||||||
|
var dbits;
|
||||||
|
|
||||||
|
// JavaScript engine analysis
|
||||||
|
var canary = 0xdeadbeefcafe;
|
||||||
|
var j_lm = ((canary&0xffffff)==0xefcafe);
|
||||||
|
|
||||||
|
// (public) Constructor
|
||||||
|
function BigInteger(a,b,c) {
|
||||||
|
if(a != null)
|
||||||
|
if("number" == typeof a) this.fromNumber(a,b,c);
|
||||||
|
else if(b == null && "string" != typeof a) this.fromString(a,256);
|
||||||
|
else this.fromString(a,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return new, unset BigInteger
|
||||||
|
function nbi() { return new BigInteger(null); }
|
||||||
|
|
||||||
|
// am: Compute w_j += (x*this_i), propagate carries,
|
||||||
|
// c is initial carry, returns final carry.
|
||||||
|
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
||||||
|
// We need to select the fastest one that works in this environment.
|
||||||
|
|
||||||
|
// am1: use a single mult and divide to get the high bits,
|
||||||
|
// max digit bits should be 26 because
|
||||||
|
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
||||||
|
function am1(i,x,w,j,c,n) {
|
||||||
|
while(--n >= 0) {
|
||||||
|
var v = x*this[i++]+w[j]+c;
|
||||||
|
c = Math.floor(v/0x4000000);
|
||||||
|
w[j++] = v&0x3ffffff;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
// am2 avoids a big mult-and-extract completely.
|
||||||
|
// Max digit bits should be <= 30 because we do bitwise ops
|
||||||
|
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
||||||
|
function am2(i,x,w,j,c,n) {
|
||||||
|
var xl = x&0x7fff, xh = x>>15;
|
||||||
|
while(--n >= 0) {
|
||||||
|
var l = this[i]&0x7fff;
|
||||||
|
var h = this[i++]>>15;
|
||||||
|
var m = xh*l+h*xl;
|
||||||
|
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
|
||||||
|
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
|
||||||
|
w[j++] = l&0x3fffffff;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
// Alternately, set max digit bits to 28 since some
|
||||||
|
// browsers slow down when dealing with 32-bit numbers.
|
||||||
|
function am3(i,x,w,j,c,n) {
|
||||||
|
var xl = x&0x3fff, xh = x>>14;
|
||||||
|
while(--n >= 0) {
|
||||||
|
var l = this[i]&0x3fff;
|
||||||
|
var h = this[i++]>>14;
|
||||||
|
var m = xh*l+h*xl;
|
||||||
|
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
|
||||||
|
c = (l>>28)+(m>>14)+xh*h;
|
||||||
|
w[j++] = l&0xfffffff;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
|
||||||
|
BigInteger.prototype.am = am2;
|
||||||
|
dbits = 30;
|
||||||
|
}
|
||||||
|
else if(j_lm && (navigator.appName != "Netscape")) {
|
||||||
|
BigInteger.prototype.am = am1;
|
||||||
|
dbits = 26;
|
||||||
|
}
|
||||||
|
else { // Mozilla/Netscape seems to prefer am3
|
||||||
|
BigInteger.prototype.am = am3;
|
||||||
|
dbits = 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger.prototype.DB = dbits;
|
||||||
|
BigInteger.prototype.DM = ((1<<dbits)-1);
|
||||||
|
BigInteger.prototype.DV = (1<<dbits);
|
||||||
|
|
||||||
|
var BI_FP = 52;
|
||||||
|
BigInteger.prototype.FV = Math.pow(2,BI_FP);
|
||||||
|
BigInteger.prototype.F1 = BI_FP-dbits;
|
||||||
|
BigInteger.prototype.F2 = 2*dbits-BI_FP;
|
||||||
|
|
||||||
|
// Digit conversions
|
||||||
|
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
var BI_RC = new Array();
|
||||||
|
var rr,vv;
|
||||||
|
rr = "0".charCodeAt(0);
|
||||||
|
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
|
||||||
|
rr = "a".charCodeAt(0);
|
||||||
|
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||||
|
rr = "A".charCodeAt(0);
|
||||||
|
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||||
|
|
||||||
|
function int2char(n) { return BI_RM.charAt(n); }
|
||||||
|
function intAt(s,i) {
|
||||||
|
var c = BI_RC[s.charCodeAt(i)];
|
||||||
|
return (c==null)?-1:c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) copy this to r
|
||||||
|
function bnpCopyTo(r) {
|
||||||
|
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
|
||||||
|
r.t = this.t;
|
||||||
|
r.s = this.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) set from integer value x, -DV <= x < DV
|
||||||
|
function bnpFromInt(x) {
|
||||||
|
this.t = 1;
|
||||||
|
this.s = (x<0)?-1:0;
|
||||||
|
if(x > 0) this[0] = x;
|
||||||
|
else if(x < -1) this[0] = x+this.DV;
|
||||||
|
else this.t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return bigint initialized to value
|
||||||
|
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
|
||||||
|
|
||||||
|
// (protected) set from string and radix
|
||||||
|
function bnpFromString(s,b) {
|
||||||
|
var k;
|
||||||
|
if(b == 16) k = 4;
|
||||||
|
else if(b == 8) k = 3;
|
||||||
|
else if(b == 256) k = 8; // byte array
|
||||||
|
else if(b == 2) k = 1;
|
||||||
|
else if(b == 32) k = 5;
|
||||||
|
else if(b == 4) k = 2;
|
||||||
|
else { this.fromRadix(s,b); return; }
|
||||||
|
this.t = 0;
|
||||||
|
this.s = 0;
|
||||||
|
var i = s.length, mi = false, sh = 0;
|
||||||
|
while(--i >= 0) {
|
||||||
|
var x = (k==8)?s[i]&0xff:intAt(s,i);
|
||||||
|
if(x < 0) {
|
||||||
|
if(s.charAt(i) == "-") mi = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mi = false;
|
||||||
|
if(sh == 0)
|
||||||
|
this[this.t++] = x;
|
||||||
|
else if(sh+k > this.DB) {
|
||||||
|
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
|
||||||
|
this[this.t++] = (x>>(this.DB-sh));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this[this.t-1] |= x<<sh;
|
||||||
|
sh += k;
|
||||||
|
if(sh >= this.DB) sh -= this.DB;
|
||||||
|
}
|
||||||
|
if(k == 8 && (s[0]&0x80) != 0) {
|
||||||
|
this.s = -1;
|
||||||
|
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
|
||||||
|
}
|
||||||
|
this.clamp();
|
||||||
|
if(mi) BigInteger.ZERO.subTo(this,this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) clamp off excess high words
|
||||||
|
function bnpClamp() {
|
||||||
|
var c = this.s&this.DM;
|
||||||
|
while(this.t > 0 && this[this.t-1] == c) --this.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) return string representation in given radix
|
||||||
|
function bnToString(b) {
|
||||||
|
if(this.s < 0) return "-"+this.negate().toString(b);
|
||||||
|
var k;
|
||||||
|
if(b == 16) k = 4;
|
||||||
|
else if(b == 8) k = 3;
|
||||||
|
else if(b == 2) k = 1;
|
||||||
|
else if(b == 32) k = 5;
|
||||||
|
else if(b == 4) k = 2;
|
||||||
|
else return this.toRadix(b);
|
||||||
|
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
|
||||||
|
var p = this.DB-(i*this.DB)%k;
|
||||||
|
if(i-- > 0) {
|
||||||
|
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
|
||||||
|
while(i >= 0) {
|
||||||
|
if(p < k) {
|
||||||
|
d = (this[i]&((1<<p)-1))<<(k-p);
|
||||||
|
d |= this[--i]>>(p+=this.DB-k);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = (this[i]>>(p-=k))&km;
|
||||||
|
if(p <= 0) { p += this.DB; --i; }
|
||||||
|
}
|
||||||
|
if(d > 0) m = true;
|
||||||
|
if(m) r += int2char(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m?r:"0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) -this
|
||||||
|
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
|
||||||
|
|
||||||
|
// (public) |this|
|
||||||
|
function bnAbs() { return (this.s<0)?this.negate():this; }
|
||||||
|
|
||||||
|
// (public) return + if this > a, - if this < a, 0 if equal
|
||||||
|
function bnCompareTo(a) {
|
||||||
|
var r = this.s-a.s;
|
||||||
|
if(r != 0) return r;
|
||||||
|
var i = this.t;
|
||||||
|
r = i-a.t;
|
||||||
|
if(r != 0) return (this.s<0)?-r:r;
|
||||||
|
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns bit length of the integer x
|
||||||
|
function nbits(x) {
|
||||||
|
var r = 1, t;
|
||||||
|
if((t=x>>>16) != 0) { x = t; r += 16; }
|
||||||
|
if((t=x>>8) != 0) { x = t; r += 8; }
|
||||||
|
if((t=x>>4) != 0) { x = t; r += 4; }
|
||||||
|
if((t=x>>2) != 0) { x = t; r += 2; }
|
||||||
|
if((t=x>>1) != 0) { x = t; r += 1; }
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) return the number of bits in "this"
|
||||||
|
function bnBitLength() {
|
||||||
|
if(this.t <= 0) return 0;
|
||||||
|
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this << n*DB
|
||||||
|
function bnpDLShiftTo(n,r) {
|
||||||
|
var i;
|
||||||
|
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
|
||||||
|
for(i = n-1; i >= 0; --i) r[i] = 0;
|
||||||
|
r.t = this.t+n;
|
||||||
|
r.s = this.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this >> n*DB
|
||||||
|
function bnpDRShiftTo(n,r) {
|
||||||
|
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
|
||||||
|
r.t = Math.max(this.t-n,0);
|
||||||
|
r.s = this.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this << n
|
||||||
|
function bnpLShiftTo(n,r) {
|
||||||
|
var bs = n%this.DB;
|
||||||
|
var cbs = this.DB-bs;
|
||||||
|
var bm = (1<<cbs)-1;
|
||||||
|
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
|
||||||
|
for(i = this.t-1; i >= 0; --i) {
|
||||||
|
r[i+ds+1] = (this[i]>>cbs)|c;
|
||||||
|
c = (this[i]&bm)<<bs;
|
||||||
|
}
|
||||||
|
for(i = ds-1; i >= 0; --i) r[i] = 0;
|
||||||
|
r[ds] = c;
|
||||||
|
r.t = this.t+ds+1;
|
||||||
|
r.s = this.s;
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this >> n
|
||||||
|
function bnpRShiftTo(n,r) {
|
||||||
|
r.s = this.s;
|
||||||
|
var ds = Math.floor(n/this.DB);
|
||||||
|
if(ds >= this.t) { r.t = 0; return; }
|
||||||
|
var bs = n%this.DB;
|
||||||
|
var cbs = this.DB-bs;
|
||||||
|
var bm = (1<<bs)-1;
|
||||||
|
r[0] = this[ds]>>bs;
|
||||||
|
for(var i = ds+1; i < this.t; ++i) {
|
||||||
|
r[i-ds-1] |= (this[i]&bm)<<cbs;
|
||||||
|
r[i-ds] = this[i]>>bs;
|
||||||
|
}
|
||||||
|
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
|
||||||
|
r.t = this.t-ds;
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this - a
|
||||||
|
function bnpSubTo(a,r) {
|
||||||
|
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
||||||
|
while(i < m) {
|
||||||
|
c += this[i]-a[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
if(a.t < this.t) {
|
||||||
|
c -= a.s;
|
||||||
|
while(i < this.t) {
|
||||||
|
c += this[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
c += this.s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c += this.s;
|
||||||
|
while(i < a.t) {
|
||||||
|
c -= a[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
c -= a.s;
|
||||||
|
}
|
||||||
|
r.s = (c<0)?-1:0;
|
||||||
|
if(c < -1) r[i++] = this.DV+c;
|
||||||
|
else if(c > 0) r[i++] = c;
|
||||||
|
r.t = i;
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this * a, r != this,a (HAC 14.12)
|
||||||
|
// "this" should be the larger one if appropriate.
|
||||||
|
function bnpMultiplyTo(a,r) {
|
||||||
|
var x = this.abs(), y = a.abs();
|
||||||
|
var i = x.t;
|
||||||
|
r.t = i+y.t;
|
||||||
|
while(--i >= 0) r[i] = 0;
|
||||||
|
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
|
||||||
|
r.s = 0;
|
||||||
|
r.clamp();
|
||||||
|
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = this^2, r != this (HAC 14.16)
|
||||||
|
function bnpSquareTo(r) {
|
||||||
|
var x = this.abs();
|
||||||
|
var i = r.t = 2*x.t;
|
||||||
|
while(--i >= 0) r[i] = 0;
|
||||||
|
for(i = 0; i < x.t-1; ++i) {
|
||||||
|
var c = x.am(i,x[i],r,2*i,0,1);
|
||||||
|
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
|
||||||
|
r[i+x.t] -= x.DV;
|
||||||
|
r[i+x.t+1] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
|
||||||
|
r.s = 0;
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
||||||
|
// r != q, this != m. q or r may be null.
|
||||||
|
function bnpDivRemTo(m,q,r) {
|
||||||
|
var pm = m.abs();
|
||||||
|
if(pm.t <= 0) return;
|
||||||
|
var pt = this.abs();
|
||||||
|
if(pt.t < pm.t) {
|
||||||
|
if(q != null) q.fromInt(0);
|
||||||
|
if(r != null) this.copyTo(r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(r == null) r = nbi();
|
||||||
|
var y = nbi(), ts = this.s, ms = m.s;
|
||||||
|
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
|
||||||
|
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
|
||||||
|
else { pm.copyTo(y); pt.copyTo(r); }
|
||||||
|
var ys = y.t;
|
||||||
|
var y0 = y[ys-1];
|
||||||
|
if(y0 == 0) return;
|
||||||
|
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
|
||||||
|
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
|
||||||
|
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
|
||||||
|
y.dlShiftTo(j,t);
|
||||||
|
if(r.compareTo(t) >= 0) {
|
||||||
|
r[r.t++] = 1;
|
||||||
|
r.subTo(t,r);
|
||||||
|
}
|
||||||
|
BigInteger.ONE.dlShiftTo(ys,t);
|
||||||
|
t.subTo(y,y); // "negative" y so we can replace sub with am later
|
||||||
|
while(y.t < ys) y[y.t++] = 0;
|
||||||
|
while(--j >= 0) {
|
||||||
|
// Estimate quotient digit
|
||||||
|
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
|
||||||
|
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
|
||||||
|
y.dlShiftTo(j,t);
|
||||||
|
r.subTo(t,r);
|
||||||
|
while(r[i] < --qd) r.subTo(t,r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(q != null) {
|
||||||
|
r.drShiftTo(ys,q);
|
||||||
|
if(ts != ms) BigInteger.ZERO.subTo(q,q);
|
||||||
|
}
|
||||||
|
r.t = ys;
|
||||||
|
r.clamp();
|
||||||
|
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
|
||||||
|
if(ts < 0) BigInteger.ZERO.subTo(r,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this mod a
|
||||||
|
function bnMod(a) {
|
||||||
|
var r = nbi();
|
||||||
|
this.abs().divRemTo(a,null,r);
|
||||||
|
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modular reduction using "classic" algorithm
|
||||||
|
function Classic(m) { this.m = m; }
|
||||||
|
function cConvert(x) {
|
||||||
|
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
|
||||||
|
else return x;
|
||||||
|
}
|
||||||
|
function cRevert(x) { return x; }
|
||||||
|
function cReduce(x) { x.divRemTo(this.m,null,x); }
|
||||||
|
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||||
|
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||||
|
|
||||||
|
Classic.prototype.convert = cConvert;
|
||||||
|
Classic.prototype.revert = cRevert;
|
||||||
|
Classic.prototype.reduce = cReduce;
|
||||||
|
Classic.prototype.mulTo = cMulTo;
|
||||||
|
Classic.prototype.sqrTo = cSqrTo;
|
||||||
|
|
||||||
|
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
||||||
|
// justification:
|
||||||
|
// xy == 1 (mod m)
|
||||||
|
// xy = 1+km
|
||||||
|
// xy(2-xy) = (1+km)(1-km)
|
||||||
|
// x[y(2-xy)] = 1-k^2m^2
|
||||||
|
// x[y(2-xy)] == 1 (mod m^2)
|
||||||
|
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
||||||
|
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
||||||
|
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
||||||
|
function bnpInvDigit() {
|
||||||
|
if(this.t < 1) return 0;
|
||||||
|
var x = this[0];
|
||||||
|
if((x&1) == 0) return 0;
|
||||||
|
var y = x&3; // y == 1/x mod 2^2
|
||||||
|
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
|
||||||
|
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
|
||||||
|
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
|
||||||
|
// last step - calculate inverse mod DV directly;
|
||||||
|
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
||||||
|
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
|
||||||
|
// we really want the negative inverse, and -DV < y < DV
|
||||||
|
return (y>0)?this.DV-y:-y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Montgomery reduction
|
||||||
|
function Montgomery(m) {
|
||||||
|
this.m = m;
|
||||||
|
this.mp = m.invDigit();
|
||||||
|
this.mpl = this.mp&0x7fff;
|
||||||
|
this.mph = this.mp>>15;
|
||||||
|
this.um = (1<<(m.DB-15))-1;
|
||||||
|
this.mt2 = 2*m.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// xR mod m
|
||||||
|
function montConvert(x) {
|
||||||
|
var r = nbi();
|
||||||
|
x.abs().dlShiftTo(this.m.t,r);
|
||||||
|
r.divRemTo(this.m,null,r);
|
||||||
|
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x/R mod m
|
||||||
|
function montRevert(x) {
|
||||||
|
var r = nbi();
|
||||||
|
x.copyTo(r);
|
||||||
|
this.reduce(r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x = x/R mod m (HAC 14.32)
|
||||||
|
function montReduce(x) {
|
||||||
|
while(x.t <= this.mt2) // pad x so am has enough room later
|
||||||
|
x[x.t++] = 0;
|
||||||
|
for(var i = 0; i < this.m.t; ++i) {
|
||||||
|
// faster way of calculating u0 = x[i]*mp mod DV
|
||||||
|
var j = x[i]&0x7fff;
|
||||||
|
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
|
||||||
|
// use am to combine the multiply-shift-add into one call
|
||||||
|
j = i+this.m.t;
|
||||||
|
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
|
||||||
|
// propagate carry
|
||||||
|
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
|
||||||
|
}
|
||||||
|
x.clamp();
|
||||||
|
x.drShiftTo(this.m.t,x);
|
||||||
|
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// r = "x^2/R mod m"; x != r
|
||||||
|
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||||
|
|
||||||
|
// r = "xy/R mod m"; x,y != r
|
||||||
|
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||||
|
|
||||||
|
Montgomery.prototype.convert = montConvert;
|
||||||
|
Montgomery.prototype.revert = montRevert;
|
||||||
|
Montgomery.prototype.reduce = montReduce;
|
||||||
|
Montgomery.prototype.mulTo = montMulTo;
|
||||||
|
Montgomery.prototype.sqrTo = montSqrTo;
|
||||||
|
|
||||||
|
// (protected) true iff this is even
|
||||||
|
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
|
||||||
|
|
||||||
|
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
||||||
|
function bnpExp(e,z) {
|
||||||
|
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
|
||||||
|
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
|
||||||
|
g.copyTo(r);
|
||||||
|
while(--i >= 0) {
|
||||||
|
z.sqrTo(r,r2);
|
||||||
|
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
|
||||||
|
else { var t = r; r = r2; r2 = t; }
|
||||||
|
}
|
||||||
|
return z.revert(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this^e % m, 0 <= e < 2^32
|
||||||
|
function bnModPowInt(e,m) {
|
||||||
|
var z;
|
||||||
|
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
|
||||||
|
return this.exp(e,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected
|
||||||
|
BigInteger.prototype.copyTo = bnpCopyTo;
|
||||||
|
BigInteger.prototype.fromInt = bnpFromInt;
|
||||||
|
BigInteger.prototype.fromString = bnpFromString;
|
||||||
|
BigInteger.prototype.clamp = bnpClamp;
|
||||||
|
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
|
||||||
|
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
|
||||||
|
BigInteger.prototype.lShiftTo = bnpLShiftTo;
|
||||||
|
BigInteger.prototype.rShiftTo = bnpRShiftTo;
|
||||||
|
BigInteger.prototype.subTo = bnpSubTo;
|
||||||
|
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
|
||||||
|
BigInteger.prototype.squareTo = bnpSquareTo;
|
||||||
|
BigInteger.prototype.divRemTo = bnpDivRemTo;
|
||||||
|
BigInteger.prototype.invDigit = bnpInvDigit;
|
||||||
|
BigInteger.prototype.isEven = bnpIsEven;
|
||||||
|
BigInteger.prototype.exp = bnpExp;
|
||||||
|
|
||||||
|
// public
|
||||||
|
BigInteger.prototype.toString = bnToString;
|
||||||
|
BigInteger.prototype.negate = bnNegate;
|
||||||
|
BigInteger.prototype.abs = bnAbs;
|
||||||
|
BigInteger.prototype.compareTo = bnCompareTo;
|
||||||
|
BigInteger.prototype.bitLength = bnBitLength;
|
||||||
|
BigInteger.prototype.mod = bnMod;
|
||||||
|
BigInteger.prototype.modPowInt = bnModPowInt;
|
||||||
|
|
||||||
|
// "constants"
|
||||||
|
BigInteger.ZERO = nbv(0);
|
||||||
|
BigInteger.ONE = nbv(1);
|
656
javascript/jsbn/jsbn2.js
Normal file
656
javascript/jsbn/jsbn2.js
Normal file
|
@ -0,0 +1,656 @@
|
||||||
|
// Copyright (c) 2005-2009 Tom Wu
|
||||||
|
// All Rights Reserved.
|
||||||
|
// See "LICENSE" for details.
|
||||||
|
|
||||||
|
// Extended JavaScript BN functions, required for RSA private ops.
|
||||||
|
|
||||||
|
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
|
||||||
|
// Version 1.2: square() API, isProbablePrime fix
|
||||||
|
|
||||||
|
// (public)
|
||||||
|
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
|
||||||
|
|
||||||
|
// (public) return value as integer
|
||||||
|
function bnIntValue() {
|
||||||
|
if(this.s < 0) {
|
||||||
|
if(this.t == 1) return this[0]-this.DV;
|
||||||
|
else if(this.t == 0) return -1;
|
||||||
|
}
|
||||||
|
else if(this.t == 1) return this[0];
|
||||||
|
else if(this.t == 0) return 0;
|
||||||
|
// assumes 16 < DB < 32
|
||||||
|
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) return value as byte
|
||||||
|
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
|
||||||
|
|
||||||
|
// (public) return value as short (assumes DB>=16)
|
||||||
|
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
|
||||||
|
|
||||||
|
// (protected) return x s.t. r^x < DV
|
||||||
|
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
|
||||||
|
|
||||||
|
// (public) 0 if this == 0, 1 if this > 0
|
||||||
|
function bnSigNum() {
|
||||||
|
if(this.s < 0) return -1;
|
||||||
|
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) convert to radix string
|
||||||
|
function bnpToRadix(b) {
|
||||||
|
if(b == null) b = 10;
|
||||||
|
if(this.signum() == 0 || b < 2 || b > 36) return "0";
|
||||||
|
var cs = this.chunkSize(b);
|
||||||
|
var a = Math.pow(b,cs);
|
||||||
|
var d = nbv(a), y = nbi(), z = nbi(), r = "";
|
||||||
|
this.divRemTo(d,y,z);
|
||||||
|
while(y.signum() > 0) {
|
||||||
|
r = (a+z.intValue()).toString(b).substr(1) + r;
|
||||||
|
y.divRemTo(d,y,z);
|
||||||
|
}
|
||||||
|
return z.intValue().toString(b) + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) convert from radix string
|
||||||
|
function bnpFromRadix(s,b) {
|
||||||
|
this.fromInt(0);
|
||||||
|
if(b == null) b = 10;
|
||||||
|
var cs = this.chunkSize(b);
|
||||||
|
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
|
||||||
|
for(var i = 0; i < s.length; ++i) {
|
||||||
|
var x = intAt(s,i);
|
||||||
|
if(x < 0) {
|
||||||
|
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
w = b*w+x;
|
||||||
|
if(++j >= cs) {
|
||||||
|
this.dMultiply(d);
|
||||||
|
this.dAddOffset(w,0);
|
||||||
|
j = 0;
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(j > 0) {
|
||||||
|
this.dMultiply(Math.pow(b,j));
|
||||||
|
this.dAddOffset(w,0);
|
||||||
|
}
|
||||||
|
if(mi) BigInteger.ZERO.subTo(this,this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) alternate constructor
|
||||||
|
function bnpFromNumber(a,b,c) {
|
||||||
|
if("number" == typeof b) {
|
||||||
|
// new BigInteger(int,int,RNG)
|
||||||
|
if(a < 2) this.fromInt(1);
|
||||||
|
else {
|
||||||
|
this.fromNumber(a,c);
|
||||||
|
if(!this.testBit(a-1)) // force MSB set
|
||||||
|
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
|
||||||
|
if(this.isEven()) this.dAddOffset(1,0); // force odd
|
||||||
|
while(!this.isProbablePrime(b)) {
|
||||||
|
this.dAddOffset(2,0);
|
||||||
|
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// new BigInteger(int,RNG)
|
||||||
|
var x = new Array(), t = a&7;
|
||||||
|
x.length = (a>>3)+1;
|
||||||
|
b.nextBytes(x);
|
||||||
|
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
|
||||||
|
this.fromString(x,256);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) convert to bigendian byte array
|
||||||
|
function bnToByteArray() {
|
||||||
|
var i = this.t, r = new Array();
|
||||||
|
r[0] = this.s;
|
||||||
|
var p = this.DB-(i*this.DB)%8, d, k = 0;
|
||||||
|
if(i-- > 0) {
|
||||||
|
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
|
||||||
|
r[k++] = d|(this.s<<(this.DB-p));
|
||||||
|
while(i >= 0) {
|
||||||
|
if(p < 8) {
|
||||||
|
d = (this[i]&((1<<p)-1))<<(8-p);
|
||||||
|
d |= this[--i]>>(p+=this.DB-8);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d = (this[i]>>(p-=8))&0xff;
|
||||||
|
if(p <= 0) { p += this.DB; --i; }
|
||||||
|
}
|
||||||
|
if((d&0x80) != 0) d |= -256;
|
||||||
|
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
|
||||||
|
if(k > 0 || d != this.s) r[k++] = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bnEquals(a) { return(this.compareTo(a)==0); }
|
||||||
|
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
|
||||||
|
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
|
||||||
|
|
||||||
|
// (protected) r = this op a (bitwise)
|
||||||
|
function bnpBitwiseTo(a,op,r) {
|
||||||
|
var i, f, m = Math.min(a.t,this.t);
|
||||||
|
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
|
||||||
|
if(a.t < this.t) {
|
||||||
|
f = a.s&this.DM;
|
||||||
|
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
|
||||||
|
r.t = this.t;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f = this.s&this.DM;
|
||||||
|
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
|
||||||
|
r.t = a.t;
|
||||||
|
}
|
||||||
|
r.s = op(this.s,a.s);
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this & a
|
||||||
|
function op_and(x,y) { return x&y; }
|
||||||
|
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
|
||||||
|
|
||||||
|
// (public) this | a
|
||||||
|
function op_or(x,y) { return x|y; }
|
||||||
|
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
|
||||||
|
|
||||||
|
// (public) this ^ a
|
||||||
|
function op_xor(x,y) { return x^y; }
|
||||||
|
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
|
||||||
|
|
||||||
|
// (public) this & ~a
|
||||||
|
function op_andnot(x,y) { return x&~y; }
|
||||||
|
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
|
||||||
|
|
||||||
|
// (public) ~this
|
||||||
|
function bnNot() {
|
||||||
|
var r = nbi();
|
||||||
|
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
|
||||||
|
r.t = this.t;
|
||||||
|
r.s = ~this.s;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this << n
|
||||||
|
function bnShiftLeft(n) {
|
||||||
|
var r = nbi();
|
||||||
|
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this >> n
|
||||||
|
function bnShiftRight(n) {
|
||||||
|
var r = nbi();
|
||||||
|
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return index of lowest 1-bit in x, x < 2^31
|
||||||
|
function lbit(x) {
|
||||||
|
if(x == 0) return -1;
|
||||||
|
var r = 0;
|
||||||
|
if((x&0xffff) == 0) { x >>= 16; r += 16; }
|
||||||
|
if((x&0xff) == 0) { x >>= 8; r += 8; }
|
||||||
|
if((x&0xf) == 0) { x >>= 4; r += 4; }
|
||||||
|
if((x&3) == 0) { x >>= 2; r += 2; }
|
||||||
|
if((x&1) == 0) ++r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) returns index of lowest 1-bit (or -1 if none)
|
||||||
|
function bnGetLowestSetBit() {
|
||||||
|
for(var i = 0; i < this.t; ++i)
|
||||||
|
if(this[i] != 0) return i*this.DB+lbit(this[i]);
|
||||||
|
if(this.s < 0) return this.t*this.DB;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return number of 1 bits in x
|
||||||
|
function cbit(x) {
|
||||||
|
var r = 0;
|
||||||
|
while(x != 0) { x &= x-1; ++r; }
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) return number of set bits
|
||||||
|
function bnBitCount() {
|
||||||
|
var r = 0, x = this.s&this.DM;
|
||||||
|
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) true iff nth bit is set
|
||||||
|
function bnTestBit(n) {
|
||||||
|
var j = Math.floor(n/this.DB);
|
||||||
|
if(j >= this.t) return(this.s!=0);
|
||||||
|
return((this[j]&(1<<(n%this.DB)))!=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) this op (1<<n)
|
||||||
|
function bnpChangeBit(n,op) {
|
||||||
|
var r = BigInteger.ONE.shiftLeft(n);
|
||||||
|
this.bitwiseTo(r,op,r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this | (1<<n)
|
||||||
|
function bnSetBit(n) { return this.changeBit(n,op_or); }
|
||||||
|
|
||||||
|
// (public) this & ~(1<<n)
|
||||||
|
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
|
||||||
|
|
||||||
|
// (public) this ^ (1<<n)
|
||||||
|
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
|
||||||
|
|
||||||
|
// (protected) r = this + a
|
||||||
|
function bnpAddTo(a,r) {
|
||||||
|
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
||||||
|
while(i < m) {
|
||||||
|
c += this[i]+a[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
if(a.t < this.t) {
|
||||||
|
c += a.s;
|
||||||
|
while(i < this.t) {
|
||||||
|
c += this[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
c += this.s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c += this.s;
|
||||||
|
while(i < a.t) {
|
||||||
|
c += a[i];
|
||||||
|
r[i++] = c&this.DM;
|
||||||
|
c >>= this.DB;
|
||||||
|
}
|
||||||
|
c += a.s;
|
||||||
|
}
|
||||||
|
r.s = (c<0)?-1:0;
|
||||||
|
if(c > 0) r[i++] = c;
|
||||||
|
else if(c < -1) r[i++] = this.DV+c;
|
||||||
|
r.t = i;
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) this + a
|
||||||
|
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
|
||||||
|
|
||||||
|
// (public) this - a
|
||||||
|
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
|
||||||
|
|
||||||
|
// (public) this * a
|
||||||
|
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
|
||||||
|
|
||||||
|
// (public) this^2
|
||||||
|
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
|
||||||
|
|
||||||
|
// (public) this / a
|
||||||
|
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
|
||||||
|
|
||||||
|
// (public) this % a
|
||||||
|
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
|
||||||
|
|
||||||
|
// (public) [this/a,this%a]
|
||||||
|
function bnDivideAndRemainder(a) {
|
||||||
|
var q = nbi(), r = nbi();
|
||||||
|
this.divRemTo(a,q,r);
|
||||||
|
return new Array(q,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) this *= n, this >= 0, 1 < n < DV
|
||||||
|
function bnpDMultiply(n) {
|
||||||
|
this[this.t] = this.am(0,n-1,this,0,0,this.t);
|
||||||
|
++this.t;
|
||||||
|
this.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) this += n << w words, this >= 0
|
||||||
|
function bnpDAddOffset(n,w) {
|
||||||
|
if(n == 0) return;
|
||||||
|
while(this.t <= w) this[this.t++] = 0;
|
||||||
|
this[w] += n;
|
||||||
|
while(this[w] >= this.DV) {
|
||||||
|
this[w] -= this.DV;
|
||||||
|
if(++w >= this.t) this[this.t++] = 0;
|
||||||
|
++this[w];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "null" reducer
|
||||||
|
function NullExp() {}
|
||||||
|
function nNop(x) { return x; }
|
||||||
|
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
|
||||||
|
function nSqrTo(x,r) { x.squareTo(r); }
|
||||||
|
|
||||||
|
NullExp.prototype.convert = nNop;
|
||||||
|
NullExp.prototype.revert = nNop;
|
||||||
|
NullExp.prototype.mulTo = nMulTo;
|
||||||
|
NullExp.prototype.sqrTo = nSqrTo;
|
||||||
|
|
||||||
|
// (public) this^e
|
||||||
|
function bnPow(e) { return this.exp(e,new NullExp()); }
|
||||||
|
|
||||||
|
// (protected) r = lower n words of "this * a", a.t <= n
|
||||||
|
// "this" should be the larger one if appropriate.
|
||||||
|
function bnpMultiplyLowerTo(a,n,r) {
|
||||||
|
var i = Math.min(this.t+a.t,n);
|
||||||
|
r.s = 0; // assumes a,this >= 0
|
||||||
|
r.t = i;
|
||||||
|
while(i > 0) r[--i] = 0;
|
||||||
|
var j;
|
||||||
|
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
|
||||||
|
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
|
||||||
|
r.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) r = "this * a" without lower n words, n > 0
|
||||||
|
// "this" should be the larger one if appropriate.
|
||||||
|
function bnpMultiplyUpperTo(a,n,r) {
|
||||||
|
--n;
|
||||||
|
var i = r.t = this.t+a.t-n;
|
||||||
|
r.s = 0; // assumes a,this >= 0
|
||||||
|
while(--i >= 0) r[i] = 0;
|
||||||
|
for(i = Math.max(n-this.t,0); i < a.t; ++i)
|
||||||
|
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
|
||||||
|
r.clamp();
|
||||||
|
r.drShiftTo(1,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Barrett modular reduction
|
||||||
|
function Barrett(m) {
|
||||||
|
// setup Barrett
|
||||||
|
this.r2 = nbi();
|
||||||
|
this.q3 = nbi();
|
||||||
|
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
|
||||||
|
this.mu = this.r2.divide(m);
|
||||||
|
this.m = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
function barrettConvert(x) {
|
||||||
|
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
|
||||||
|
else if(x.compareTo(this.m) < 0) return x;
|
||||||
|
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function barrettRevert(x) { return x; }
|
||||||
|
|
||||||
|
// x = x mod m (HAC 14.42)
|
||||||
|
function barrettReduce(x) {
|
||||||
|
x.drShiftTo(this.m.t-1,this.r2);
|
||||||
|
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
|
||||||
|
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
|
||||||
|
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
|
||||||
|
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
|
||||||
|
x.subTo(this.r2,x);
|
||||||
|
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// r = x^2 mod m; x != r
|
||||||
|
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||||
|
|
||||||
|
// r = x*y mod m; x,y != r
|
||||||
|
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||||
|
|
||||||
|
Barrett.prototype.convert = barrettConvert;
|
||||||
|
Barrett.prototype.revert = barrettRevert;
|
||||||
|
Barrett.prototype.reduce = barrettReduce;
|
||||||
|
Barrett.prototype.mulTo = barrettMulTo;
|
||||||
|
Barrett.prototype.sqrTo = barrettSqrTo;
|
||||||
|
|
||||||
|
// (public) this^e % m (HAC 14.85)
|
||||||
|
function bnModPow(e,m) {
|
||||||
|
var i = e.bitLength(), k, r = nbv(1), z;
|
||||||
|
if(i <= 0) return r;
|
||||||
|
else if(i < 18) k = 1;
|
||||||
|
else if(i < 48) k = 3;
|
||||||
|
else if(i < 144) k = 4;
|
||||||
|
else if(i < 768) k = 5;
|
||||||
|
else k = 6;
|
||||||
|
if(i < 8)
|
||||||
|
z = new Classic(m);
|
||||||
|
else if(m.isEven())
|
||||||
|
z = new Barrett(m);
|
||||||
|
else
|
||||||
|
z = new Montgomery(m);
|
||||||
|
|
||||||
|
// precomputation
|
||||||
|
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
|
||||||
|
g[1] = z.convert(this);
|
||||||
|
if(k > 1) {
|
||||||
|
var g2 = nbi();
|
||||||
|
z.sqrTo(g[1],g2);
|
||||||
|
while(n <= km) {
|
||||||
|
g[n] = nbi();
|
||||||
|
z.mulTo(g2,g[n-2],g[n]);
|
||||||
|
n += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
|
||||||
|
i = nbits(e[j])-1;
|
||||||
|
while(j >= 0) {
|
||||||
|
if(i >= k1) w = (e[j]>>(i-k1))&km;
|
||||||
|
else {
|
||||||
|
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
|
||||||
|
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
|
||||||
|
}
|
||||||
|
|
||||||
|
n = k;
|
||||||
|
while((w&1) == 0) { w >>= 1; --n; }
|
||||||
|
if((i -= n) < 0) { i += this.DB; --j; }
|
||||||
|
if(is1) { // ret == 1, don't bother squaring or multiplying it
|
||||||
|
g[w].copyTo(r);
|
||||||
|
is1 = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
|
||||||
|
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
|
||||||
|
z.mulTo(r2,g[w],r);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(j >= 0 && (e[j]&(1<<i)) == 0) {
|
||||||
|
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
|
||||||
|
if(--i < 0) { i = this.DB-1; --j; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return z.revert(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) gcd(this,a) (HAC 14.54)
|
||||||
|
function bnGCD(a) {
|
||||||
|
var x = (this.s<0)?this.negate():this.clone();
|
||||||
|
var y = (a.s<0)?a.negate():a.clone();
|
||||||
|
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
|
||||||
|
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
|
||||||
|
if(g < 0) return x;
|
||||||
|
if(i < g) g = i;
|
||||||
|
if(g > 0) {
|
||||||
|
x.rShiftTo(g,x);
|
||||||
|
y.rShiftTo(g,y);
|
||||||
|
}
|
||||||
|
while(x.signum() > 0) {
|
||||||
|
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
|
||||||
|
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
|
||||||
|
if(x.compareTo(y) >= 0) {
|
||||||
|
x.subTo(y,x);
|
||||||
|
x.rShiftTo(1,x);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
y.subTo(x,y);
|
||||||
|
y.rShiftTo(1,y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(g > 0) y.lShiftTo(g,y);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) this % n, n < 2^26
|
||||||
|
function bnpModInt(n) {
|
||||||
|
if(n <= 0) return 0;
|
||||||
|
var d = this.DV%n, r = (this.s<0)?n-1:0;
|
||||||
|
if(this.t > 0)
|
||||||
|
if(d == 0) r = this[0]%n;
|
||||||
|
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (public) 1/this % m (HAC 14.61)
|
||||||
|
function bnModInverse(m) {
|
||||||
|
var ac = m.isEven();
|
||||||
|
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
|
||||||
|
var u = m.clone(), v = this.clone();
|
||||||
|
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
|
||||||
|
while(u.signum() != 0) {
|
||||||
|
while(u.isEven()) {
|
||||||
|
u.rShiftTo(1,u);
|
||||||
|
if(ac) {
|
||||||
|
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
|
||||||
|
a.rShiftTo(1,a);
|
||||||
|
}
|
||||||
|
else if(!b.isEven()) b.subTo(m,b);
|
||||||
|
b.rShiftTo(1,b);
|
||||||
|
}
|
||||||
|
while(v.isEven()) {
|
||||||
|
v.rShiftTo(1,v);
|
||||||
|
if(ac) {
|
||||||
|
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
|
||||||
|
c.rShiftTo(1,c);
|
||||||
|
}
|
||||||
|
else if(!d.isEven()) d.subTo(m,d);
|
||||||
|
d.rShiftTo(1,d);
|
||||||
|
}
|
||||||
|
if(u.compareTo(v) >= 0) {
|
||||||
|
u.subTo(v,u);
|
||||||
|
if(ac) a.subTo(c,a);
|
||||||
|
b.subTo(d,b);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.subTo(u,v);
|
||||||
|
if(ac) c.subTo(a,c);
|
||||||
|
d.subTo(b,d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
|
||||||
|
if(d.compareTo(m) >= 0) return d.subtract(m);
|
||||||
|
if(d.signum() < 0) d.addTo(m,d); else return d;
|
||||||
|
if(d.signum() < 0) return d.add(m); else return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
|
||||||
|
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
|
||||||
|
|
||||||
|
// (public) test primality with certainty >= 1-.5^t
|
||||||
|
function bnIsProbablePrime(t) {
|
||||||
|
var i, x = this.abs();
|
||||||
|
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
|
||||||
|
for(i = 0; i < lowprimes.length; ++i)
|
||||||
|
if(x[0] == lowprimes[i]) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(x.isEven()) return false;
|
||||||
|
i = 1;
|
||||||
|
while(i < lowprimes.length) {
|
||||||
|
var m = lowprimes[i], j = i+1;
|
||||||
|
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
|
||||||
|
m = x.modInt(m);
|
||||||
|
while(i < j) if(m%lowprimes[i++] == 0) return false;
|
||||||
|
}
|
||||||
|
return x.millerRabin(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
||||||
|
function bnpMillerRabin(t) {
|
||||||
|
var n1 = this.subtract(BigInteger.ONE);
|
||||||
|
var k = n1.getLowestSetBit();
|
||||||
|
if(k <= 0) return false;
|
||||||
|
var r = n1.shiftRight(k);
|
||||||
|
t = (t+1)>>1;
|
||||||
|
if(t > lowprimes.length) t = lowprimes.length;
|
||||||
|
var a = nbi();
|
||||||
|
for(var i = 0; i < t; ++i) {
|
||||||
|
//Pick bases at random, instead of starting at 2
|
||||||
|
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
|
||||||
|
var y = a.modPow(r,this);
|
||||||
|
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
|
||||||
|
var j = 1;
|
||||||
|
while(j++ < k && y.compareTo(n1) != 0) {
|
||||||
|
y = y.modPowInt(2,this);
|
||||||
|
if(y.compareTo(BigInteger.ONE) == 0) return false;
|
||||||
|
}
|
||||||
|
if(y.compareTo(n1) != 0) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected
|
||||||
|
BigInteger.prototype.chunkSize = bnpChunkSize;
|
||||||
|
BigInteger.prototype.toRadix = bnpToRadix;
|
||||||
|
BigInteger.prototype.fromRadix = bnpFromRadix;
|
||||||
|
BigInteger.prototype.fromNumber = bnpFromNumber;
|
||||||
|
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
|
||||||
|
BigInteger.prototype.changeBit = bnpChangeBit;
|
||||||
|
BigInteger.prototype.addTo = bnpAddTo;
|
||||||
|
BigInteger.prototype.dMultiply = bnpDMultiply;
|
||||||
|
BigInteger.prototype.dAddOffset = bnpDAddOffset;
|
||||||
|
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
|
||||||
|
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
|
||||||
|
BigInteger.prototype.modInt = bnpModInt;
|
||||||
|
BigInteger.prototype.millerRabin = bnpMillerRabin;
|
||||||
|
|
||||||
|
// public
|
||||||
|
BigInteger.prototype.clone = bnClone;
|
||||||
|
BigInteger.prototype.intValue = bnIntValue;
|
||||||
|
BigInteger.prototype.byteValue = bnByteValue;
|
||||||
|
BigInteger.prototype.shortValue = bnShortValue;
|
||||||
|
BigInteger.prototype.signum = bnSigNum;
|
||||||
|
BigInteger.prototype.toByteArray = bnToByteArray;
|
||||||
|
BigInteger.prototype.equals = bnEquals;
|
||||||
|
BigInteger.prototype.min = bnMin;
|
||||||
|
BigInteger.prototype.max = bnMax;
|
||||||
|
BigInteger.prototype.and = bnAnd;
|
||||||
|
BigInteger.prototype.or = bnOr;
|
||||||
|
BigInteger.prototype.xor = bnXor;
|
||||||
|
BigInteger.prototype.andNot = bnAndNot;
|
||||||
|
BigInteger.prototype.not = bnNot;
|
||||||
|
BigInteger.prototype.shiftLeft = bnShiftLeft;
|
||||||
|
BigInteger.prototype.shiftRight = bnShiftRight;
|
||||||
|
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
|
||||||
|
BigInteger.prototype.bitCount = bnBitCount;
|
||||||
|
BigInteger.prototype.testBit = bnTestBit;
|
||||||
|
BigInteger.prototype.setBit = bnSetBit;
|
||||||
|
BigInteger.prototype.clearBit = bnClearBit;
|
||||||
|
BigInteger.prototype.flipBit = bnFlipBit;
|
||||||
|
BigInteger.prototype.add = bnAdd;
|
||||||
|
BigInteger.prototype.subtract = bnSubtract;
|
||||||
|
BigInteger.prototype.multiply = bnMultiply;
|
||||||
|
BigInteger.prototype.divide = bnDivide;
|
||||||
|
BigInteger.prototype.remainder = bnRemainder;
|
||||||
|
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
|
||||||
|
BigInteger.prototype.modPow = bnModPow;
|
||||||
|
BigInteger.prototype.modInverse = bnModInverse;
|
||||||
|
BigInteger.prototype.pow = bnPow;
|
||||||
|
BigInteger.prototype.gcd = bnGCD;
|
||||||
|
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
|
||||||
|
|
||||||
|
// JSBN-specific extension
|
||||||
|
BigInteger.prototype.square = bnSquare;
|
||||||
|
|
||||||
|
// BigInteger interfaces not implemented in jsbn:
|
||||||
|
|
||||||
|
// BigInteger(int signum, byte[] magnitude)
|
||||||
|
// double doubleValue()
|
||||||
|
// float floatValue()
|
||||||
|
// int hashCode()
|
||||||
|
// long longValue()
|
||||||
|
// static BigInteger valueOf(long val)
|
45
javascript/jsbn/prng4.js
Normal file
45
javascript/jsbn/prng4.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// prng4.js - uses Arcfour as a PRNG
|
||||||
|
|
||||||
|
function Arcfour() {
|
||||||
|
this.i = 0;
|
||||||
|
this.j = 0;
|
||||||
|
this.S = new Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
||||||
|
function ARC4init(key) {
|
||||||
|
var i, j, t;
|
||||||
|
for(i = 0; i < 256; ++i)
|
||||||
|
this.S[i] = i;
|
||||||
|
j = 0;
|
||||||
|
for(i = 0; i < 256; ++i) {
|
||||||
|
j = (j + this.S[i] + key[i % key.length]) & 255;
|
||||||
|
t = this.S[i];
|
||||||
|
this.S[i] = this.S[j];
|
||||||
|
this.S[j] = t;
|
||||||
|
}
|
||||||
|
this.i = 0;
|
||||||
|
this.j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ARC4next() {
|
||||||
|
var t;
|
||||||
|
this.i = (this.i + 1) & 255;
|
||||||
|
this.j = (this.j + this.S[this.i]) & 255;
|
||||||
|
t = this.S[this.i];
|
||||||
|
this.S[this.i] = this.S[this.j];
|
||||||
|
this.S[this.j] = t;
|
||||||
|
return this.S[(t + this.S[this.i]) & 255];
|
||||||
|
}
|
||||||
|
|
||||||
|
Arcfour.prototype.init = ARC4init;
|
||||||
|
Arcfour.prototype.next = ARC4next;
|
||||||
|
|
||||||
|
// Plug in your RNG constructor here
|
||||||
|
function prng_newstate() {
|
||||||
|
return new Arcfour();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool size must be a multiple of 4 and greater than 32.
|
||||||
|
// An array of bytes the size of the pool will be passed to init()
|
||||||
|
var rng_psize = 256;
|
75
javascript/jsbn/rng.js
Normal file
75
javascript/jsbn/rng.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// Random number generator - requires a PRNG backend, e.g. prng4.js
|
||||||
|
|
||||||
|
// For best results, put code like
|
||||||
|
// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
|
||||||
|
// in your main HTML document.
|
||||||
|
|
||||||
|
var rng_state;
|
||||||
|
var rng_pool;
|
||||||
|
var rng_pptr;
|
||||||
|
|
||||||
|
// Mix in a 32-bit integer into the pool
|
||||||
|
function rng_seed_int(x) {
|
||||||
|
rng_pool[rng_pptr++] ^= x & 255;
|
||||||
|
rng_pool[rng_pptr++] ^= (x >> 8) & 255;
|
||||||
|
rng_pool[rng_pptr++] ^= (x >> 16) & 255;
|
||||||
|
rng_pool[rng_pptr++] ^= (x >> 24) & 255;
|
||||||
|
if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mix in the current time (w/milliseconds) into the pool
|
||||||
|
function rng_seed_time() {
|
||||||
|
rng_seed_int(new Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the pool with junk if needed.
|
||||||
|
if(rng_pool == null) {
|
||||||
|
rng_pool = new Array();
|
||||||
|
rng_pptr = 0;
|
||||||
|
var t;
|
||||||
|
if(window.crypto && window.crypto.getRandomValues) {
|
||||||
|
// Use webcrypto if available
|
||||||
|
var ua = new Uint8Array(32);
|
||||||
|
window.crypto.getRandomValues(ua);
|
||||||
|
for(t = 0; t < 32; ++t)
|
||||||
|
rng_pool[rng_pptr++] = ua[t];
|
||||||
|
}
|
||||||
|
if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
|
||||||
|
// Extract entropy (256 bits) from NS4 RNG if available
|
||||||
|
var z = window.crypto.random(32);
|
||||||
|
for(t = 0; t < z.length; ++t)
|
||||||
|
rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
|
||||||
|
}
|
||||||
|
while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
|
||||||
|
t = Math.floor(65536 * Math.random());
|
||||||
|
rng_pool[rng_pptr++] = t >>> 8;
|
||||||
|
rng_pool[rng_pptr++] = t & 255;
|
||||||
|
}
|
||||||
|
rng_pptr = 0;
|
||||||
|
rng_seed_time();
|
||||||
|
//rng_seed_int(window.screenX);
|
||||||
|
//rng_seed_int(window.screenY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rng_get_byte() {
|
||||||
|
if(rng_state == null) {
|
||||||
|
rng_seed_time();
|
||||||
|
rng_state = prng_newstate();
|
||||||
|
rng_state.init(rng_pool);
|
||||||
|
for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
|
||||||
|
rng_pool[rng_pptr] = 0;
|
||||||
|
rng_pptr = 0;
|
||||||
|
//rng_pool = null;
|
||||||
|
}
|
||||||
|
// TODO: allow reseeding after first request
|
||||||
|
return rng_state.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function rng_get_bytes(ba) {
|
||||||
|
var i;
|
||||||
|
for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
function SecureRandom() {}
|
||||||
|
|
||||||
|
SecureRandom.prototype.nextBytes = rng_get_bytes;
|
112
javascript/jsbn/rsa.js
Normal file
112
javascript/jsbn/rsa.js
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
// Depends on jsbn.js and rng.js
|
||||||
|
|
||||||
|
// Version 1.1: support utf-8 encoding in pkcs1pad2
|
||||||
|
|
||||||
|
// convert a (hex) string to a bignum object
|
||||||
|
function parseBigInt(str,r) {
|
||||||
|
return new BigInteger(str,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
function linebrk(s,n) {
|
||||||
|
var ret = "";
|
||||||
|
var i = 0;
|
||||||
|
while(i + n < s.length) {
|
||||||
|
ret += s.substring(i,i+n) + "\n";
|
||||||
|
i += n;
|
||||||
|
}
|
||||||
|
return ret + s.substring(i,s.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function byte2Hex(b) {
|
||||||
|
if(b < 0x10)
|
||||||
|
return "0" + b.toString(16);
|
||||||
|
else
|
||||||
|
return b.toString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
|
||||||
|
function pkcs1pad2(s,n) {
|
||||||
|
if(n < s.length + 11) { // TODO: fix for utf-8
|
||||||
|
alert("Message too long for RSA");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var ba = new Array();
|
||||||
|
var i = s.length - 1;
|
||||||
|
while(i >= 0 && n > 0) {
|
||||||
|
var c = s.charCodeAt(i--);
|
||||||
|
if(c < 128) { // encode using utf-8
|
||||||
|
ba[--n] = c;
|
||||||
|
}
|
||||||
|
else if((c > 127) && (c < 2048)) {
|
||||||
|
ba[--n] = (c & 63) | 128;
|
||||||
|
ba[--n] = (c >> 6) | 192;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ba[--n] = (c & 63) | 128;
|
||||||
|
ba[--n] = ((c >> 6) & 63) | 128;
|
||||||
|
ba[--n] = (c >> 12) | 224;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ba[--n] = 0;
|
||||||
|
var rng = new SecureRandom();
|
||||||
|
var x = new Array();
|
||||||
|
while(n > 2) { // random non-zero pad
|
||||||
|
x[0] = 0;
|
||||||
|
while(x[0] == 0) rng.nextBytes(x);
|
||||||
|
ba[--n] = x[0];
|
||||||
|
}
|
||||||
|
ba[--n] = 2;
|
||||||
|
ba[--n] = 0;
|
||||||
|
return new BigInteger(ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
// "empty" RSA key constructor
|
||||||
|
function RSAKey() {
|
||||||
|
this.n = null;
|
||||||
|
this.e = 0;
|
||||||
|
this.d = null;
|
||||||
|
this.p = null;
|
||||||
|
this.q = null;
|
||||||
|
this.dmp1 = null;
|
||||||
|
this.dmq1 = null;
|
||||||
|
this.coeff = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the public key fields N and e from hex strings
|
||||||
|
function RSASetPublic(N,E) {
|
||||||
|
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N,16);
|
||||||
|
this.e = parseInt(E,16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert("Invalid RSA public key");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform raw public operation on "x": return x^e (mod n)
|
||||||
|
function RSADoPublic(x) {
|
||||||
|
return x.modPowInt(this.e, this.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
|
||||||
|
function RSAEncrypt(text) {
|
||||||
|
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
|
||||||
|
if(m == null) return null;
|
||||||
|
var c = this.doPublic(m);
|
||||||
|
if(c == null) return null;
|
||||||
|
var h = c.toString(16);
|
||||||
|
if((h.length & 1) == 0) return h; else return "0" + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
|
||||||
|
//function RSAEncryptB64(text) {
|
||||||
|
// var h = this.encrypt(text);
|
||||||
|
// if(h) return hex2b64(h); else return null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// protected
|
||||||
|
RSAKey.prototype.doPublic = RSADoPublic;
|
||||||
|
|
||||||
|
// public
|
||||||
|
RSAKey.prototype.setPublic = RSASetPublic;
|
||||||
|
RSAKey.prototype.encrypt = RSAEncrypt;
|
||||||
|
//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
|
132
javascript/jsbn/rsa2.js
Normal file
132
javascript/jsbn/rsa2.js
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Depends on rsa.js and jsbn2.js
|
||||||
|
|
||||||
|
// Version 1.1: support utf-8 decoding in pkcs1unpad2
|
||||||
|
|
||||||
|
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
|
||||||
|
function pkcs1unpad2(d,n) {
|
||||||
|
var b = d.toByteArray();
|
||||||
|
var i = 0;
|
||||||
|
while(i < b.length && b[i] == 0) ++i;
|
||||||
|
if(b.length-i != n-1 || b[i] != 2)
|
||||||
|
return null;
|
||||||
|
++i;
|
||||||
|
while(b[i] != 0)
|
||||||
|
if(++i >= b.length) return null;
|
||||||
|
var ret = "";
|
||||||
|
while(++i < b.length) {
|
||||||
|
var c = b[i] & 255;
|
||||||
|
if(c < 128) { // utf-8 decode
|
||||||
|
ret += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if((c > 191) && (c < 224)) {
|
||||||
|
ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the private key fields N, e, and d from hex strings
|
||||||
|
function RSASetPrivate(N,E,D) {
|
||||||
|
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N,16);
|
||||||
|
this.e = parseInt(E,16);
|
||||||
|
this.d = parseBigInt(D,16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert("Invalid RSA private key");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the private key fields N, e, d and CRT params from hex strings
|
||||||
|
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
|
||||||
|
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N,16);
|
||||||
|
this.e = parseInt(E,16);
|
||||||
|
this.d = parseBigInt(D,16);
|
||||||
|
this.p = parseBigInt(P,16);
|
||||||
|
this.q = parseBigInt(Q,16);
|
||||||
|
this.dmp1 = parseBigInt(DP,16);
|
||||||
|
this.dmq1 = parseBigInt(DQ,16);
|
||||||
|
this.coeff = parseBigInt(C,16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert("Invalid RSA private key");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a new random private key B bits long, using public expt E
|
||||||
|
function RSAGenerate(B,E) {
|
||||||
|
var rng = new SecureRandom();
|
||||||
|
var qs = B>>1;
|
||||||
|
this.e = parseInt(E,16);
|
||||||
|
var ee = new BigInteger(E,16);
|
||||||
|
for(;;) {
|
||||||
|
for(;;) {
|
||||||
|
this.p = new BigInteger(B-qs,1,rng);
|
||||||
|
if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
|
||||||
|
}
|
||||||
|
for(;;) {
|
||||||
|
this.q = new BigInteger(qs,1,rng);
|
||||||
|
if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
|
||||||
|
}
|
||||||
|
if(this.p.compareTo(this.q) <= 0) {
|
||||||
|
var t = this.p;
|
||||||
|
this.p = this.q;
|
||||||
|
this.q = t;
|
||||||
|
}
|
||||||
|
var p1 = this.p.subtract(BigInteger.ONE);
|
||||||
|
var q1 = this.q.subtract(BigInteger.ONE);
|
||||||
|
var phi = p1.multiply(q1);
|
||||||
|
if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
||||||
|
this.n = this.p.multiply(this.q);
|
||||||
|
this.d = ee.modInverse(phi);
|
||||||
|
this.dmp1 = this.d.mod(p1);
|
||||||
|
this.dmq1 = this.d.mod(q1);
|
||||||
|
this.coeff = this.q.modInverse(this.p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform raw private operation on "x": return x^d (mod n)
|
||||||
|
function RSADoPrivate(x) {
|
||||||
|
if(this.p == null || this.q == null)
|
||||||
|
return x.modPow(this.d, this.n);
|
||||||
|
|
||||||
|
// TODO: re-calculate any missing CRT params
|
||||||
|
var xp = x.mod(this.p).modPow(this.dmp1, this.p);
|
||||||
|
var xq = x.mod(this.q).modPow(this.dmq1, this.q);
|
||||||
|
|
||||||
|
while(xp.compareTo(xq) < 0)
|
||||||
|
xp = xp.add(this.p);
|
||||||
|
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the PKCS#1 RSA decryption of "ctext".
|
||||||
|
// "ctext" is an even-length hex string and the output is a plain string.
|
||||||
|
function RSADecrypt(ctext) {
|
||||||
|
var c = parseBigInt(ctext, 16);
|
||||||
|
var m = this.doPrivate(c);
|
||||||
|
if(m == null) return null;
|
||||||
|
return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the PKCS#1 RSA decryption of "ctext".
|
||||||
|
// "ctext" is a Base64-encoded string and the output is a plain string.
|
||||||
|
//function RSAB64Decrypt(ctext) {
|
||||||
|
// var h = b64tohex(ctext);
|
||||||
|
// if(h) return this.decrypt(h); else return null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// protected
|
||||||
|
RSAKey.prototype.doPrivate = RSADoPrivate;
|
||||||
|
|
||||||
|
// public
|
||||||
|
RSAKey.prototype.setPrivate = RSASetPrivate;
|
||||||
|
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
|
||||||
|
RSAKey.prototype.generate = RSAGenerate;
|
||||||
|
RSAKey.prototype.decrypt = RSADecrypt;
|
||||||
|
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
|
2
javascript/jsencrypt.min.js
vendored
2
javascript/jsencrypt.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -87,11 +87,8 @@ public class NetClientHandler extends NetHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleServerAuthData(Packet253ServerAuthData par1Packet253ServerAuthData) {
|
public void handleServerAuthData(Packet253ServerAuthData par1Packet253ServerAuthData) {
|
||||||
String var2 = par1Packet253ServerAuthData.getServerId().trim();
|
//String var2 = par1Packet253ServerAuthData.getServerId().trim();
|
||||||
PublicKey var3 = par1Packet253ServerAuthData.getPublicKey();
|
this.addToSendQueue(new Packet252SharedKey(CryptManager.createNewSharedKey(), par1Packet253ServerAuthData.getPublicKey(), par1Packet253ServerAuthData.getVerifyToken()));
|
||||||
SecretKey var4 = CryptManager.createNewSharedKey();
|
|
||||||
|
|
||||||
this.addToSendQueue(new Packet252SharedKey(var4, var3, par1Packet253ServerAuthData.getVerifyToken()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleSharedKey(Packet252SharedKey par1Packet252SharedKey) {
|
public void handleSharedKey(Packet252SharedKey par1Packet252SharedKey) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import me.ayunami2000.ayuncraft.PubKey;
|
||||||
import me.ayunami2000.ayuncraft.java.security.Key;
|
import me.ayunami2000.ayuncraft.java.security.Key;
|
||||||
import me.ayunami2000.ayuncraft.java.security.PrivateKey;
|
import me.ayunami2000.ayuncraft.java.security.PrivateKey;
|
||||||
import me.ayunami2000.ayuncraft.java.security.PublicKey;
|
import me.ayunami2000.ayuncraft.java.security.PublicKey;
|
||||||
|
@ -23,11 +24,11 @@ public class Packet252SharedKey extends Packet
|
||||||
|
|
||||||
public Packet252SharedKey() {}
|
public Packet252SharedKey() {}
|
||||||
|
|
||||||
public Packet252SharedKey(SecretKey par1SecretKey, PublicKey par2PublicKey, byte[] par3ArrayOfByte)
|
public Packet252SharedKey(SecretKey par1SecretKey, PubKey par2PublicKey, byte[] par3ArrayOfByte)
|
||||||
{
|
{
|
||||||
this.sharedKey = par1SecretKey;
|
this.sharedKey = par1SecretKey;
|
||||||
this.sharedSecret = CryptManager.encryptData((Key) par2PublicKey, par1SecretKey.getEncoded());
|
this.sharedSecret = CryptManager.encryptData(par2PublicKey, par1SecretKey.getEncoded());
|
||||||
this.verifyToken = CryptManager.encryptData((Key) par2PublicKey, par3ArrayOfByte);
|
this.verifyToken = CryptManager.encryptData(par2PublicKey, par3ArrayOfByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +68,7 @@ public class Packet252SharedKey extends Packet
|
||||||
/**
|
/**
|
||||||
* Return secretKey, decrypting it from the sharedSecret byte array if needed
|
* Return secretKey, decrypting it from the sharedSecret byte array if needed
|
||||||
*/
|
*/
|
||||||
public SecretKey getSharedKey(PrivateKey par1PrivateKey)
|
public SecretKey getSharedKey(PubKey par1PrivateKey)
|
||||||
{
|
{
|
||||||
return par1PrivateKey == null ? this.sharedKey : (this.sharedKey = CryptManager.decryptSharedKey(par1PrivateKey, this.sharedSecret));
|
return par1PrivateKey == null ? this.sharedKey : (this.sharedKey = CryptManager.decryptSharedKey(par1PrivateKey, this.sharedSecret));
|
||||||
}
|
}
|
||||||
|
@ -83,8 +84,8 @@ public class Packet252SharedKey extends Packet
|
||||||
/**
|
/**
|
||||||
* Return verifyToken
|
* Return verifyToken
|
||||||
*/
|
*/
|
||||||
public byte[] getVerifyToken(PrivateKey par1PrivateKey)
|
public byte[] getVerifyToken(PubKey par1PrivateKey)
|
||||||
{
|
{
|
||||||
return par1PrivateKey == null ? this.verifyToken : CryptManager.decryptData((Key) par1PrivateKey, this.verifyToken);
|
return par1PrivateKey == null ? this.verifyToken : CryptManager.decryptData(par1PrivateKey, this.verifyToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,17 +5,20 @@ import me.ayunami2000.ayuncraft.CryptManager;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import me.ayunami2000.ayuncraft.PubKey;
|
||||||
import me.ayunami2000.ayuncraft.java.security.PublicKey;
|
import me.ayunami2000.ayuncraft.java.security.PublicKey;
|
||||||
|
|
||||||
public class Packet253ServerAuthData extends Packet
|
public class Packet253ServerAuthData extends Packet
|
||||||
{
|
{
|
||||||
private String serverId;
|
private String serverId;
|
||||||
private PublicKey publicKey;
|
private PubKey publicKey;
|
||||||
private byte[] verifyToken = new byte[0];
|
private byte[] verifyToken = new byte[0];
|
||||||
|
|
||||||
public Packet253ServerAuthData() {}
|
public Packet253ServerAuthData() {}
|
||||||
|
|
||||||
public Packet253ServerAuthData(String par1Str, PublicKey par2PublicKey, byte[] par3ArrayOfByte)
|
public Packet253ServerAuthData(String par1Str, PubKey par2PublicKey, byte[] par3ArrayOfByte)
|
||||||
{
|
{
|
||||||
this.serverId = par1Str;
|
this.serverId = par1Str;
|
||||||
this.publicKey = par2PublicKey;
|
this.publicKey = par2PublicKey;
|
||||||
|
@ -63,7 +66,7 @@ public class Packet253ServerAuthData extends Packet
|
||||||
return this.serverId;
|
return this.serverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PublicKey getPublicKey()
|
public PubKey getPublicKey()
|
||||||
{
|
{
|
||||||
return this.publicKey;
|
return this.publicKey;
|
||||||
}
|
}
|
||||||
|
|
186
src/teavm/java/com/beanit/asn1bean/ber/BerLength.java
Normal file
186
src/teavm/java/com/beanit/asn1bean/ber/BerLength.java
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.util.HexString;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerLength implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public int val;
|
||||||
|
|
||||||
|
public BerLength() {}
|
||||||
|
|
||||||
|
public static int encodeLength(OutputStream reverseOS, int length) throws IOException {
|
||||||
|
|
||||||
|
if (length <= 127) {
|
||||||
|
// this is the short form
|
||||||
|
reverseOS.write(length);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length <= 255) {
|
||||||
|
reverseOS.write(length);
|
||||||
|
reverseOS.write(0x81);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length <= 65535) {
|
||||||
|
reverseOS.write(length);
|
||||||
|
reverseOS.write(length >> 8);
|
||||||
|
reverseOS.write(0x82);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length <= 16777215) {
|
||||||
|
reverseOS.write(length);
|
||||||
|
reverseOS.write(length >> 8);
|
||||||
|
reverseOS.write(length >> 16);
|
||||||
|
reverseOS.write(0x83);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numLengthBytes = 1;
|
||||||
|
while (((int) (Math.pow(2, 8 * numLengthBytes) - 1)) < length) {
|
||||||
|
numLengthBytes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < numLengthBytes; i++) {
|
||||||
|
reverseOS.write(length >> (8 * i));
|
||||||
|
}
|
||||||
|
reverseOS.write(0x80 | numLengthBytes);
|
||||||
|
|
||||||
|
return 1 + numLengthBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int readEocByte(InputStream is) throws IOException {
|
||||||
|
int b = is.read();
|
||||||
|
if (b != 0) {
|
||||||
|
if (b == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
throw new IOException(
|
||||||
|
"Byte " + HexString.fromByte(b) + " does not match end of contents octet of zero.");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int readEocByte(InputStream is, OutputStream os) throws IOException {
|
||||||
|
int b = is.read();
|
||||||
|
if (b != 0) {
|
||||||
|
if (b == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
os.write(b);
|
||||||
|
throw new IOException(
|
||||||
|
"Byte " + HexString.fromByte(b) + " does not match end of contents octet of zero.");
|
||||||
|
}
|
||||||
|
os.write(b);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
|
||||||
|
val = is.read();
|
||||||
|
// check for short form
|
||||||
|
if (val < 128) {
|
||||||
|
if (val == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lengthLength = val & 0x7f;
|
||||||
|
// check for indefinite length
|
||||||
|
if (lengthLength == 0) {
|
||||||
|
val = -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lengthLength > 4) {
|
||||||
|
throw new IOException("Length is out of bounds: " + lengthLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
for (int i = 0; i < lengthLength; i++) {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
val |= nextByte << (8 * (lengthLength - i - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lengthLength + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, OutputStream os) throws IOException {
|
||||||
|
|
||||||
|
val = is.read();
|
||||||
|
if (val == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
os.write(val);
|
||||||
|
|
||||||
|
// check for short form
|
||||||
|
if (val < 128) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lengthLength = val & 0x7f;
|
||||||
|
// check for indefinite length
|
||||||
|
if (lengthLength == 0) {
|
||||||
|
val = -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lengthLength > 4) {
|
||||||
|
throw new IOException("Length is out of bounds: " + lengthLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = 0;
|
||||||
|
for (int i = 0; i < lengthLength; i++) {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
os.write(nextByte);
|
||||||
|
val |= nextByte << (8 * (lengthLength - i - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lengthLength + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the end of contents octets from the given input stream if this length object has the
|
||||||
|
* indefinite form.
|
||||||
|
*
|
||||||
|
* @param is the input stream
|
||||||
|
* @return the number of bytes read from the input stream
|
||||||
|
* @throws IOException if an error occurs while reading from the input stream
|
||||||
|
*/
|
||||||
|
public int readEocIfIndefinite(InputStream is) throws IOException {
|
||||||
|
if (val >= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
readEocByte(is);
|
||||||
|
readEocByte(is);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
259
src/teavm/java/com/beanit/asn1bean/ber/BerTag.java
Normal file
259
src/teavm/java/com/beanit/asn1bean/ber/BerTag.java
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.util.HexString;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerTag implements Serializable {
|
||||||
|
|
||||||
|
public static final int UNIVERSAL_CLASS = 0x00;
|
||||||
|
public static final int APPLICATION_CLASS = 0x40;
|
||||||
|
public static final int CONTEXT_CLASS = 0x80;
|
||||||
|
public static final int PRIVATE_CLASS = 0xc0;
|
||||||
|
public static final int PRIMITIVE = 0x00;
|
||||||
|
public static final int CONSTRUCTED = 0x20;
|
||||||
|
public static final int BOOLEAN_TAG = 1;
|
||||||
|
public static final int INTEGER_TAG = 2;
|
||||||
|
public static final int BIT_STRING_TAG = 3;
|
||||||
|
public static final int OCTET_STRING_TAG = 4;
|
||||||
|
public static final int NULL_TAG = 5;
|
||||||
|
public static final int OBJECT_IDENTIFIER_TAG = 6;
|
||||||
|
public static final int OBJECT_DESCRIPTOR_TAG = 7;
|
||||||
|
public static final int REAL_TAG = 9;
|
||||||
|
public static final int ENUMERATED_TAG = 10;
|
||||||
|
public static final int UTF8_STRING_TAG = 12;
|
||||||
|
public static final int TIME_TAG = 14;
|
||||||
|
public static final int SEQUENCE_TAG = 16;
|
||||||
|
public static final int SET_TAG = 17;
|
||||||
|
public static final int NUMERIC_STRING_TAG = 18;
|
||||||
|
public static final int PRINTABLE_STRING_TAG = 19;
|
||||||
|
public static final int TELETEX_STRING_TAG = 20;
|
||||||
|
public static final int VIDEOTEX_STRING_TAG = 21;
|
||||||
|
public static final int IA5_STRING_TAG = 22;
|
||||||
|
public static final int UTC_TIME_TAG = 23;
|
||||||
|
public static final int GENERALIZED_TIME_TAG = 24;
|
||||||
|
public static final int GRAPHIC_STRING_TAG = 25;
|
||||||
|
public static final int VISIBLE_STRING_TAG = 26;
|
||||||
|
public static final int GENERAL_STRING_TAG = 27;
|
||||||
|
public static final int UNIVERSAL_STRING_TAG = 28;
|
||||||
|
public static final int BMP_STRING_TAG = 30;
|
||||||
|
public static final int DATE_TAG = 31;
|
||||||
|
public static final int TIME_OF_DAY_TAG = 32;
|
||||||
|
public static final int DATE_TIME_TAG = 33;
|
||||||
|
public static final int DURATION_TAG = 34;
|
||||||
|
public static final BerTag SEQUENCE = new BerTag(UNIVERSAL_CLASS, CONSTRUCTED, SEQUENCE_TAG);
|
||||||
|
public static final BerTag SET = new BerTag(UNIVERSAL_CLASS, CONSTRUCTED, SET_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public byte[] tagBytes = null;
|
||||||
|
public int tagClass;
|
||||||
|
public int primitive;
|
||||||
|
public int tagNumber;
|
||||||
|
|
||||||
|
public BerTag(int identifierClass, int primitive, int tagNumber) {
|
||||||
|
this.tagClass = identifierClass;
|
||||||
|
this.primitive = primitive;
|
||||||
|
this.tagNumber = tagNumber;
|
||||||
|
code();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerTag() {}
|
||||||
|
|
||||||
|
private void code() {
|
||||||
|
if (tagNumber < 31) {
|
||||||
|
tagBytes = new byte[1];
|
||||||
|
tagBytes[0] = (byte) (tagClass | primitive | tagNumber);
|
||||||
|
} else {
|
||||||
|
int tagLength = 1;
|
||||||
|
while (tagNumber > (Math.pow(2, (7 * tagLength)) - 1)) {
|
||||||
|
tagLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tagBytes = new byte[1 + tagLength];
|
||||||
|
tagBytes[0] = (byte) (tagClass | primitive | 31);
|
||||||
|
|
||||||
|
for (int j = 1; j <= (tagLength - 1); j++) {
|
||||||
|
tagBytes[j] = (byte) (((tagNumber >> (7 * (tagLength - j))) & 0xff) | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
tagBytes[tagLength] = (byte) (tagNumber & 0x7f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
if (tagBytes == null) {
|
||||||
|
code();
|
||||||
|
}
|
||||||
|
for (int i = (tagBytes.length - 1); i >= 0; i--) {
|
||||||
|
reverseOS.write(tagBytes[i]);
|
||||||
|
}
|
||||||
|
return tagBytes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encodeForwards(OutputStream os) throws IOException {
|
||||||
|
if (tagBytes == null) {
|
||||||
|
code();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < tagBytes.length; i++) {
|
||||||
|
os.write(tagBytes[i]);
|
||||||
|
}
|
||||||
|
return tagBytes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
tagClass = nextByte & 0xC0;
|
||||||
|
primitive = nextByte & 0x20;
|
||||||
|
tagNumber = nextByte & 0x1f;
|
||||||
|
|
||||||
|
int codeLength = 1;
|
||||||
|
|
||||||
|
if (tagNumber == 0x1f) {
|
||||||
|
tagNumber = 0;
|
||||||
|
int numTagBytes = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength++;
|
||||||
|
if (numTagBytes >= 6) {
|
||||||
|
throw new IOException("Tag is too large.");
|
||||||
|
}
|
||||||
|
tagNumber = tagNumber << 7;
|
||||||
|
tagNumber |= (nextByte & 0x7f);
|
||||||
|
numTagBytes++;
|
||||||
|
} while ((nextByte & 0x80) != 0);
|
||||||
|
}
|
||||||
|
tagBytes = null;
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, OutputStream os) throws IOException {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
os.write(nextByte);
|
||||||
|
|
||||||
|
tagClass = nextByte & 0xC0;
|
||||||
|
primitive = nextByte & 0x20;
|
||||||
|
tagNumber = nextByte & 0x1f;
|
||||||
|
|
||||||
|
int codeLength = 1;
|
||||||
|
|
||||||
|
if (tagNumber == 0x1f) {
|
||||||
|
tagNumber = 0;
|
||||||
|
int numTagBytes = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
os.write(nextByte);
|
||||||
|
|
||||||
|
codeLength++;
|
||||||
|
if (numTagBytes >= 6) {
|
||||||
|
throw new IOException("Tag is too large.");
|
||||||
|
}
|
||||||
|
tagNumber = tagNumber << 7;
|
||||||
|
tagNumber |= (nextByte & 0x7f);
|
||||||
|
numTagBytes++;
|
||||||
|
} while ((nextByte & 0x80) != 0);
|
||||||
|
}
|
||||||
|
tagBytes = null;
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the Identifier from the ByteArrayInputStream and throws an Exception if it is not equal
|
||||||
|
* to itself. Returns the number of bytes read from the InputStream.
|
||||||
|
*
|
||||||
|
* @param is the input stream to read the identifier from.
|
||||||
|
* @return the length of the identifier read.
|
||||||
|
* @throws IOException if an exception occurs reading the identifier from the stream.
|
||||||
|
*/
|
||||||
|
public int decodeAndCheck(InputStream is) throws IOException {
|
||||||
|
if (tagBytes == null) {
|
||||||
|
code();
|
||||||
|
}
|
||||||
|
for (byte identifierByte : tagBytes) {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextByte != (identifierByte & 0xff)) {
|
||||||
|
throw new IOException(
|
||||||
|
"Identifier does not match, expected: 0x"
|
||||||
|
+ HexString.fromByte(identifierByte)
|
||||||
|
+ ", received: 0x"
|
||||||
|
+ HexString.fromByte((byte) nextByte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tagBytes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(int identifierClass, int primitive, int tagNumber) {
|
||||||
|
return (this.tagNumber == tagNumber
|
||||||
|
&& this.tagClass == identifierClass
|
||||||
|
&& this.primitive == primitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof BerTag)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BerTag berIdentifier = (BerTag) obj;
|
||||||
|
return (tagNumber == berIdentifier.tagNumber
|
||||||
|
&& tagClass == berIdentifier.tagClass
|
||||||
|
&& primitive == berIdentifier.primitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 31 + tagNumber;
|
||||||
|
hash = hash * 31 + tagClass;
|
||||||
|
hash = hash * 31 + primitive;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "identifier class: "
|
||||||
|
+ tagClass
|
||||||
|
+ ", primitive: "
|
||||||
|
+ primitive
|
||||||
|
+ ", tag number: "
|
||||||
|
+ tagNumber;
|
||||||
|
}
|
||||||
|
}
|
72
src/teavm/java/com/beanit/asn1bean/ber/DecodeUtil.java
Normal file
72
src/teavm/java/com/beanit/asn1bean/ber/DecodeUtil.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class DecodeUtil {
|
||||||
|
|
||||||
|
private DecodeUtil() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int decodeUnknownComponent(InputStream is) throws IOException {
|
||||||
|
int byteCount = 0;
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
byteCount += length.decode(is);
|
||||||
|
int lengthVal = length.val;
|
||||||
|
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
if (lengthVal < 0) {
|
||||||
|
byteCount += berTag.decode(is);
|
||||||
|
while (!berTag.equals(0, 0, 0)) {
|
||||||
|
byteCount += decodeUnknownComponent(is);
|
||||||
|
byteCount += berTag.decode(is);
|
||||||
|
}
|
||||||
|
byteCount += BerLength.readEocByte(is);
|
||||||
|
return byteCount;
|
||||||
|
} else {
|
||||||
|
Util.readFullyAndDiscard(is, lengthVal);
|
||||||
|
return byteCount + lengthVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int decodeUnknownComponent(InputStream is, OutputStream os) throws IOException {
|
||||||
|
int byteCount = 0;
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
byteCount += length.decode(is, os);
|
||||||
|
int lengthVal = length.val;
|
||||||
|
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
if (lengthVal < 0) {
|
||||||
|
byteCount += berTag.decode(is, os);
|
||||||
|
while (!berTag.equals(0, 0, 0)) {
|
||||||
|
byteCount += decodeUnknownComponent(is, os);
|
||||||
|
byteCount += berTag.decode(is, os);
|
||||||
|
}
|
||||||
|
byteCount += BerLength.readEocByte(is, os);
|
||||||
|
return byteCount;
|
||||||
|
} else {
|
||||||
|
byte[] contentBytes = new byte[lengthVal];
|
||||||
|
Util.readFully(is, contentBytes);
|
||||||
|
os.write(contentBytes);
|
||||||
|
return byteCount + lengthVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class ReverseByteArrayOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
private final boolean automaticResize;
|
||||||
|
public byte[] buffer;
|
||||||
|
public int index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a <code>ReverseByteArrayOutputStream</code> with a byte array of size <code>bufferSize
|
||||||
|
* </code>. The buffer will not be resized automatically. Use {@link
|
||||||
|
* #ReverseByteArrayOutputStream(int, boolean)} instead if you want the buffer to be dynamically
|
||||||
|
* resized.
|
||||||
|
*
|
||||||
|
* @param bufferSize the size of the underlying buffer
|
||||||
|
*/
|
||||||
|
public ReverseByteArrayOutputStream(int bufferSize) {
|
||||||
|
this(new byte[bufferSize], bufferSize - 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseByteArrayOutputStream(int bufferSize, boolean automaticResize) {
|
||||||
|
this(new byte[bufferSize], bufferSize - 1, automaticResize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseByteArrayOutputStream(byte[] buffer) {
|
||||||
|
this(buffer, buffer.length - 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseByteArrayOutputStream(byte[] buffer, int startingIndex) {
|
||||||
|
this(buffer, startingIndex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseByteArrayOutputStream(byte[] buffer, int startingIndex, boolean automaticResize) {
|
||||||
|
if (buffer.length <= 0) {
|
||||||
|
throw new IllegalArgumentException("buffer size may not be <= 0");
|
||||||
|
}
|
||||||
|
this.buffer = buffer;
|
||||||
|
index = startingIndex;
|
||||||
|
this.automaticResize = automaticResize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int arg0) {
|
||||||
|
write((byte) arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte arg0) {
|
||||||
|
try {
|
||||||
|
buffer[index] = arg0;
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
if (automaticResize) {
|
||||||
|
resize();
|
||||||
|
buffer[index] = arg0;
|
||||||
|
} else {
|
||||||
|
throw new ArrayIndexOutOfBoundsException("buffer.length = " + buffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resize() {
|
||||||
|
byte[] newBuffer = new byte[buffer.length * 2];
|
||||||
|
System.arraycopy(
|
||||||
|
buffer, index + 1, newBuffer, buffer.length + index + 1, buffer.length - index - 1);
|
||||||
|
index += buffer.length;
|
||||||
|
buffer = newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte[] byteArray) {
|
||||||
|
// check if there is enough space - resize otherwise
|
||||||
|
while (index + 1 - byteArray.length < 0) {
|
||||||
|
if (automaticResize) {
|
||||||
|
resize();
|
||||||
|
} else {
|
||||||
|
throw new ArrayIndexOutOfBoundsException("buffer.length = " + buffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(byteArray, 0, buffer, index - byteArray.length + 1, byteArray.length);
|
||||||
|
index -= byteArray.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new array containing the subarray of the stream array that contains the coded
|
||||||
|
* content.
|
||||||
|
*
|
||||||
|
* @return a new array containing the subarray of the stream array
|
||||||
|
*/
|
||||||
|
public byte[] getArray() {
|
||||||
|
if (index == -1) {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
int subBufferLength = buffer.length - index - 1;
|
||||||
|
byte[] subBuffer = new byte[subBufferLength];
|
||||||
|
System.arraycopy(buffer, index + 1, subBuffer, 0, subBufferLength);
|
||||||
|
return subBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getByteBuffer() {
|
||||||
|
return ByteBuffer.wrap(buffer, index + 1, buffer.length - (index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
index = buffer.length - 1;
|
||||||
|
}
|
||||||
|
}
|
40
src/teavm/java/com/beanit/asn1bean/ber/internal/Util.java
Normal file
40
src/teavm/java/com/beanit/asn1bean/ber/internal/Util.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.internal;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
public static void readFully(InputStream is, byte[] buffer) throws IOException {
|
||||||
|
readFully(is, buffer, 0, buffer.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void readFully(InputStream is, byte[] buffer, int off, int len) throws IOException {
|
||||||
|
while (len > 0) {
|
||||||
|
int bytesRead = is.read(buffer, off, len);
|
||||||
|
if (bytesRead == -1) {
|
||||||
|
throw new EOFException("End of input stream reached.");
|
||||||
|
}
|
||||||
|
len -= bytesRead;
|
||||||
|
off += bytesRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void readFullyAndDiscard(InputStream is, int lengthVal) throws IOException {
|
||||||
|
readFully(is, new byte[lengthVal]);
|
||||||
|
}
|
||||||
|
}
|
70
src/teavm/java/com/beanit/asn1bean/ber/types/BerAny.java
Normal file
70
src/teavm/java/com/beanit/asn1bean/ber/types/BerAny.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.DecodeUtil;
|
||||||
|
import com.beanit.asn1bean.util.HexString;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerAny implements Serializable, BerType {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public byte[] value;
|
||||||
|
|
||||||
|
public BerAny() {}
|
||||||
|
|
||||||
|
public BerAny(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
reverseOS.write(value);
|
||||||
|
return value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
|
||||||
|
return decode(is, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, BerTag tag) throws IOException {
|
||||||
|
|
||||||
|
int byteCount = 0;
|
||||||
|
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
if (tag == null) {
|
||||||
|
tag = new BerTag();
|
||||||
|
byteCount = tag.decode(is, os);
|
||||||
|
} else {
|
||||||
|
tag.encode(os);
|
||||||
|
}
|
||||||
|
byteCount += DecodeUtil.decodeUnknownComponent(is, os);
|
||||||
|
value = os.toByteArray();
|
||||||
|
return byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return HexString.fromBytes(value);
|
||||||
|
}
|
||||||
|
}
|
166
src/teavm/java/com/beanit/asn1bean/ber/types/BerBitString.java
Normal file
166
src/teavm/java/com/beanit/asn1bean/ber/types/BerBitString.java
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerBitString implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.BIT_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public byte[] value = null;
|
||||||
|
public int numBits;
|
||||||
|
private byte[] code = null;
|
||||||
|
|
||||||
|
public BerBitString() {}
|
||||||
|
|
||||||
|
public BerBitString(byte[] value, int numBits) {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException("value cannot be null");
|
||||||
|
}
|
||||||
|
if (numBits < 0) {
|
||||||
|
throw new IllegalArgumentException("numBits cannot be negative.");
|
||||||
|
}
|
||||||
|
if (numBits > (value.length * 8)) {
|
||||||
|
throw new IllegalArgumentException("'value' is too short to hold all bits.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
this.numBits = numBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerBitString(boolean[] value) {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException("value cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
numBits = value.length;
|
||||||
|
this.value = new byte[(numBits + 7) / 8];
|
||||||
|
for (int i = 0; i < numBits; i++) {
|
||||||
|
if (value[i]) {
|
||||||
|
this.value[i / 8] = (byte) (this.value[i / 8] | (1 << (7 - (i % 8))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerBitString(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean[] getValueAsBooleans() {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean[] booleans = new boolean[numBits];
|
||||||
|
for (int i = 0; i < numBits; i++) {
|
||||||
|
booleans[i] = ((value[i / 8] & (1 << (7 - (i % 8)))) > 0);
|
||||||
|
}
|
||||||
|
return booleans;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = (value.length - 1); i >= 0; i--) {
|
||||||
|
reverseOS.write(value[i]);
|
||||||
|
}
|
||||||
|
reverseOS.write(value.length * 8 - numBits);
|
||||||
|
|
||||||
|
int codeLength = value.length + 1;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
// could be encoded in primitiv and constructed mode
|
||||||
|
// only primitiv mode is implemented
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
value = new byte[length.val - 1];
|
||||||
|
|
||||||
|
int unusedBits = is.read();
|
||||||
|
if (unusedBits == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
if (unusedBits > 7) {
|
||||||
|
throw new IOException(
|
||||||
|
"Number of unused bits in bit string expected to be less than 8 but is: " + unusedBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
numBits = (value.length * 8) - unusedBits;
|
||||||
|
|
||||||
|
if (value.length > 0) {
|
||||||
|
Util.readFully(is, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += value.length + 1;
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (boolean bit : getValueAsBooleans()) {
|
||||||
|
if (bit) {
|
||||||
|
sb.append('1');
|
||||||
|
} else {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
116
src/teavm/java/com/beanit/asn1bean/ber/types/BerBoolean.java
Normal file
116
src/teavm/java/com/beanit/asn1bean/ber/types/BerBoolean.java
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerBoolean implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.BOOLEAN_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public boolean value;
|
||||||
|
private byte[] code = null;
|
||||||
|
|
||||||
|
public BerBoolean() {}
|
||||||
|
|
||||||
|
public BerBoolean(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerBoolean(boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = 1;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
reverseOS.write(0xff);
|
||||||
|
} else {
|
||||||
|
reverseOS.write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
if (length.val != 1) {
|
||||||
|
throw new IOException("Decoded length of BerBoolean is not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength++;
|
||||||
|
value = nextByte != 0;
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(os, false);
|
||||||
|
code = os.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
}
|
62
src/teavm/java/com/beanit/asn1bean/ber/types/BerDate.java
Normal file
62
src/teavm/java/com/beanit/asn1bean/ber/types/BerDate.java
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerDate extends BerTime {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.DATE_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerDate() {}
|
||||||
|
|
||||||
|
public BerDate(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerDate(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerDateTime extends BerTime {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.DATE_TIME_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerDateTime() {}
|
||||||
|
|
||||||
|
public BerDateTime(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerDateTime(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerDuration extends BerTime {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.DURATION_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerDuration() {}
|
||||||
|
|
||||||
|
public BerDuration(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerDuration(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
780
src/teavm/java/com/beanit/asn1bean/ber/types/BerEmbeddedPdv.java
Normal file
780
src/teavm/java/com/beanit/asn1bean/ber/types/BerEmbeddedPdv.java
Normal file
|
@ -0,0 +1,780 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
|
||||||
|
import com.beanit.asn1bean.ber.types.string.BerObjectDescriptor;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerEmbeddedPdv implements BerType, Serializable {
|
||||||
|
|
||||||
|
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 11);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private byte[] code = null;
|
||||||
|
private Identification identification = null;
|
||||||
|
private BerObjectDescriptor dataValueDescriptor = null;
|
||||||
|
private BerOctetString dataValue = null;
|
||||||
|
|
||||||
|
public BerEmbeddedPdv() {}
|
||||||
|
|
||||||
|
public BerEmbeddedPdv(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identification getIdentification() {
|
||||||
|
return identification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentification(Identification identification) {
|
||||||
|
this.identification = identification;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectDescriptor getDataValueDescriptor() {
|
||||||
|
return dataValueDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataValueDescriptor(BerObjectDescriptor dataValueDescriptor) {
|
||||||
|
this.dataValueDescriptor = dataValueDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerOctetString getDataValue() {
|
||||||
|
return dataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataValue(BerOctetString dataValue) {
|
||||||
|
this.dataValue = dataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
int sublength;
|
||||||
|
|
||||||
|
codeLength += dataValue.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 2
|
||||||
|
reverseOS.write(0x82);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
if (dataValueDescriptor != null) {
|
||||||
|
codeLength += dataValueDescriptor.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
|
||||||
|
reverseOS.write(0x81);
|
||||||
|
codeLength += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sublength = identification.encode(reverseOS);
|
||||||
|
codeLength += sublength;
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, sublength);
|
||||||
|
// write tag: CONTEXT_CLASS, CONSTRUCTED, 0
|
||||||
|
reverseOS.write(0xA0);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
int tlByteCount = 0;
|
||||||
|
int vByteCount = 0;
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
tlByteCount += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
tlByteCount += length.decode(is);
|
||||||
|
int lengthVal = length.val;
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 0)) {
|
||||||
|
vByteCount += length.decode(is);
|
||||||
|
identification = new Identification();
|
||||||
|
vByteCount += identification.decode(is, null);
|
||||||
|
vByteCount += length.readEocIfIndefinite(is);
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
|
||||||
|
dataValueDescriptor = new BerObjectDescriptor();
|
||||||
|
vByteCount += dataValueDescriptor.decode(is, false);
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 2)) {
|
||||||
|
dataValue = new BerOctetString();
|
||||||
|
vByteCount += dataValue.decode(is, false);
|
||||||
|
if (lengthVal >= 0 && vByteCount == lengthVal) {
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lengthVal < 0) {
|
||||||
|
if (!berTag.equals(0, 0, 0)) {
|
||||||
|
throw new IOException("Decoded sequence has wrong end of contents octets");
|
||||||
|
}
|
||||||
|
vByteCount += BerLength.readEocByte(is);
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException(
|
||||||
|
"Unexpected end of sequence, length tag: " + lengthVal + ", bytes decoded: " + vByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream reverseOS = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(reverseOS, false);
|
||||||
|
code = reverseOS.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
appendAsString(sb, 0);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendAsString(StringBuilder sb, int indentLevel) {
|
||||||
|
|
||||||
|
sb.append("{");
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (identification != null) {
|
||||||
|
sb.append("identification: ");
|
||||||
|
identification.appendAsString(sb, indentLevel + 1);
|
||||||
|
} else {
|
||||||
|
sb.append("identification: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataValueDescriptor != null) {
|
||||||
|
sb.append(",\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
sb.append("dataValueDescriptor: ").append(dataValueDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(",\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (dataValue != null) {
|
||||||
|
sb.append("dataValue: ").append(dataValue);
|
||||||
|
} else {
|
||||||
|
sb.append("dataValue: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Identification implements BerType, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private byte[] code = null;
|
||||||
|
private Syntaxes syntaxes = null;
|
||||||
|
private BerObjectIdentifier syntax = null;
|
||||||
|
private BerInteger presentationContextId = null;
|
||||||
|
private ContextNegotiation contextNegotiation = null;
|
||||||
|
private BerObjectIdentifier transferSyntax = null;
|
||||||
|
private BerNull fixed = null;
|
||||||
|
|
||||||
|
public Identification() {}
|
||||||
|
|
||||||
|
public Identification(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Syntaxes getSyntaxes() {
|
||||||
|
return syntaxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyntaxes(Syntaxes syntaxes) {
|
||||||
|
this.syntaxes = syntaxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier getSyntax() {
|
||||||
|
return syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSyntax(BerObjectIdentifier syntax) {
|
||||||
|
this.syntax = syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerInteger getPresentationContextId() {
|
||||||
|
return presentationContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPresentationContextId(BerInteger presentationContextId) {
|
||||||
|
this.presentationContextId = presentationContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContextNegotiation getContextNegotiation() {
|
||||||
|
return contextNegotiation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextNegotiation(ContextNegotiation contextNegotiation) {
|
||||||
|
this.contextNegotiation = contextNegotiation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier getTransferSyntax() {
|
||||||
|
return transferSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransferSyntax(BerObjectIdentifier transferSyntax) {
|
||||||
|
this.transferSyntax = transferSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerNull getFixed() {
|
||||||
|
return fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFixed(BerNull fixed) {
|
||||||
|
this.fixed = fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
if (fixed != null) {
|
||||||
|
codeLength += fixed.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 5
|
||||||
|
reverseOS.write(0x85);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferSyntax != null) {
|
||||||
|
codeLength += transferSyntax.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 4
|
||||||
|
reverseOS.write(0x84);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextNegotiation != null) {
|
||||||
|
codeLength += contextNegotiation.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, CONSTRUCTED, 3
|
||||||
|
reverseOS.write(0xA3);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentationContextId != null) {
|
||||||
|
codeLength += presentationContextId.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 2
|
||||||
|
reverseOS.write(0x82);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntax != null) {
|
||||||
|
codeLength += syntax.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
|
||||||
|
reverseOS.write(0x81);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntaxes != null) {
|
||||||
|
codeLength += syntaxes.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, CONSTRUCTED, 0
|
||||||
|
reverseOS.write(0xA0);
|
||||||
|
codeLength += 1;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Error encoding CHOICE: No element of CHOICE was selected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, BerTag berTag) throws IOException {
|
||||||
|
|
||||||
|
int tlvByteCount = 0;
|
||||||
|
boolean tagWasPassed = (berTag != null);
|
||||||
|
|
||||||
|
if (berTag == null) {
|
||||||
|
berTag = new BerTag();
|
||||||
|
tlvByteCount += berTag.decode(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 0)) {
|
||||||
|
syntaxes = new Syntaxes();
|
||||||
|
tlvByteCount += syntaxes.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
|
||||||
|
syntax = new BerObjectIdentifier();
|
||||||
|
tlvByteCount += syntax.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 2)) {
|
||||||
|
presentationContextId = new BerInteger();
|
||||||
|
tlvByteCount += presentationContextId.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.CONSTRUCTED, 3)) {
|
||||||
|
contextNegotiation = new ContextNegotiation();
|
||||||
|
tlvByteCount += contextNegotiation.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 4)) {
|
||||||
|
transferSyntax = new BerObjectIdentifier();
|
||||||
|
tlvByteCount += transferSyntax.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 5)) {
|
||||||
|
fixed = new BerNull();
|
||||||
|
tlvByteCount += fixed.decode(is, false);
|
||||||
|
return tlvByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagWasPassed) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Error decoding CHOICE: Tag " + berTag + " matched to no item.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream reverseOS = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(reverseOS);
|
||||||
|
code = reverseOS.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
appendAsString(sb, 0);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendAsString(StringBuilder sb, int indentLevel) {
|
||||||
|
|
||||||
|
if (syntaxes != null) {
|
||||||
|
sb.append("syntaxes: ");
|
||||||
|
syntaxes.appendAsString(sb, indentLevel + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntax != null) {
|
||||||
|
sb.append("syntax: ").append(syntax);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentationContextId != null) {
|
||||||
|
sb.append("presentationContextId: ").append(presentationContextId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contextNegotiation != null) {
|
||||||
|
sb.append("contextNegotiation: ");
|
||||||
|
contextNegotiation.appendAsString(sb, indentLevel + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferSyntax != null) {
|
||||||
|
sb.append("transferSyntax: ").append(transferSyntax);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixed != null) {
|
||||||
|
sb.append("fixed: ").append(fixed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("<none>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Syntaxes implements BerType, Serializable {
|
||||||
|
|
||||||
|
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private byte[] code = null;
|
||||||
|
private BerObjectIdentifier abstract_ = null;
|
||||||
|
private BerObjectIdentifier transfer = null;
|
||||||
|
|
||||||
|
public Syntaxes() {}
|
||||||
|
|
||||||
|
public Syntaxes(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier getAbstract() {
|
||||||
|
return abstract_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAbstract(BerObjectIdentifier abstract_) {
|
||||||
|
this.abstract_ = abstract_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier getTransfer() {
|
||||||
|
return transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransfer(BerObjectIdentifier transfer) {
|
||||||
|
this.transfer = transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
codeLength += transfer.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
|
||||||
|
reverseOS.write(0x81);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
codeLength += abstract_.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 0
|
||||||
|
reverseOS.write(0x80);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
int tlByteCount = 0;
|
||||||
|
int vByteCount = 0;
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
tlByteCount += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
tlByteCount += length.decode(is);
|
||||||
|
int lengthVal = length.val;
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 0)) {
|
||||||
|
abstract_ = new BerObjectIdentifier();
|
||||||
|
vByteCount += abstract_.decode(is, false);
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
|
||||||
|
transfer = new BerObjectIdentifier();
|
||||||
|
vByteCount += transfer.decode(is, false);
|
||||||
|
if (lengthVal >= 0 && vByteCount == lengthVal) {
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lengthVal < 0) {
|
||||||
|
if (!berTag.equals(0, 0, 0)) {
|
||||||
|
throw new IOException("Decoded sequence has wrong end of contents octets");
|
||||||
|
}
|
||||||
|
vByteCount += BerLength.readEocByte(is);
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException(
|
||||||
|
"Unexpected end of sequence, length tag: "
|
||||||
|
+ lengthVal
|
||||||
|
+ ", bytes decoded: "
|
||||||
|
+ vByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream reverseOS =
|
||||||
|
new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(reverseOS, false);
|
||||||
|
code = reverseOS.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
appendAsString(sb, 0);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendAsString(StringBuilder sb, int indentLevel) {
|
||||||
|
|
||||||
|
sb.append("{");
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (abstract_ != null) {
|
||||||
|
sb.append("abstract_: ").append(abstract_);
|
||||||
|
} else {
|
||||||
|
sb.append("abstract_: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(",\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (transfer != null) {
|
||||||
|
sb.append("transfer: ").append(transfer);
|
||||||
|
} else {
|
||||||
|
sb.append("transfer: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ContextNegotiation implements BerType, Serializable {
|
||||||
|
|
||||||
|
public static final BerTag tag = new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.CONSTRUCTED, 16);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private byte[] code = null;
|
||||||
|
private BerInteger presentationContextId = null;
|
||||||
|
private BerObjectIdentifier transferSyntax = null;
|
||||||
|
|
||||||
|
public ContextNegotiation() {}
|
||||||
|
|
||||||
|
public ContextNegotiation(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerInteger getPresentationContextId() {
|
||||||
|
return presentationContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPresentationContextId(BerInteger presentationContextId) {
|
||||||
|
this.presentationContextId = presentationContextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier getTransferSyntax() {
|
||||||
|
return transferSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransferSyntax(BerObjectIdentifier transferSyntax) {
|
||||||
|
this.transferSyntax = transferSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
codeLength += transferSyntax.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 1
|
||||||
|
reverseOS.write(0x81);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
codeLength += presentationContextId.encode(reverseOS, false);
|
||||||
|
// write tag: CONTEXT_CLASS, PRIMITIVE, 0
|
||||||
|
reverseOS.write(0x80);
|
||||||
|
codeLength += 1;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
int tlByteCount = 0;
|
||||||
|
int vByteCount = 0;
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
tlByteCount += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
tlByteCount += length.decode(is);
|
||||||
|
int lengthVal = length.val;
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 0)) {
|
||||||
|
presentationContextId = new BerInteger();
|
||||||
|
vByteCount += presentationContextId.decode(is, false);
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (berTag.equals(BerTag.CONTEXT_CLASS, BerTag.PRIMITIVE, 1)) {
|
||||||
|
transferSyntax = new BerObjectIdentifier();
|
||||||
|
vByteCount += transferSyntax.decode(is, false);
|
||||||
|
if (lengthVal >= 0 && vByteCount == lengthVal) {
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
vByteCount += berTag.decode(is);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Tag does not match mandatory sequence component.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lengthVal < 0) {
|
||||||
|
if (!berTag.equals(0, 0, 0)) {
|
||||||
|
throw new IOException("Decoded sequence has wrong end of contents octets");
|
||||||
|
}
|
||||||
|
vByteCount += BerLength.readEocByte(is);
|
||||||
|
return tlByteCount + vByteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException(
|
||||||
|
"Unexpected end of sequence, length tag: "
|
||||||
|
+ lengthVal
|
||||||
|
+ ", bytes decoded: "
|
||||||
|
+ vByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream reverseOS =
|
||||||
|
new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(reverseOS, false);
|
||||||
|
code = reverseOS.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
appendAsString(sb, 0);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendAsString(StringBuilder sb, int indentLevel) {
|
||||||
|
|
||||||
|
sb.append("{");
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (presentationContextId != null) {
|
||||||
|
sb.append("presentationContextId: ").append(presentationContextId);
|
||||||
|
} else {
|
||||||
|
sb.append("presentationContextId: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(",\n");
|
||||||
|
for (int i = 0; i < indentLevel + 1; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
if (transferSyntax != null) {
|
||||||
|
sb.append("transferSyntax: ").append(transferSyntax);
|
||||||
|
} else {
|
||||||
|
sb.append("transferSyntax: <empty-required-field>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("\n");
|
||||||
|
for (int i = 0; i < indentLevel; i++) {
|
||||||
|
sb.append("\t");
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
src/teavm/java/com/beanit/asn1bean/ber/types/BerEnum.java
Normal file
67
src/teavm/java/com/beanit/asn1bean/ber/types/BerEnum.java
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class BerEnum extends BerInteger {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.ENUMERATED_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerEnum() {}
|
||||||
|
|
||||||
|
public BerEnum(byte[] code) {
|
||||||
|
super(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerEnum(BigInteger val) {
|
||||||
|
this.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerEnum(long val) {
|
||||||
|
this.value = BigInteger.valueOf(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.string.BerVisibleString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class BerGeneralizedTime extends BerVisibleString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.GENERALIZED_TIME_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generalized time is one of the following (ITU-T X.680 08/2015): YYYYMMDDHH[MM[SS]][.fff]
|
||||||
|
* LocalTime YYYYMMDDHH[MM[SS]][.fff]Z UTC YYYYMMDDHH[MM[SS]][.fff]+-HH[MM] local time with time
|
||||||
|
* zone
|
||||||
|
*
|
||||||
|
* <p>Regexp: ^ (?<year>\\d{4}) YYYY (?<month>\\d{2}) MM (?<day>\\d{2}) DD (?<hour>\\d{2}) HH (
|
||||||
|
* [MM[SS]] (?<minute>\\d{2}) MM (?<second>\\d{2})? [SS] )? ([.,](?<frac>\\d+))? [.fff] (or
|
||||||
|
* [,fff]) (?<timezone> "" or "Z" or "+-HH[MM]" Z | ( "+-HH[MM]" [+-] "+-" \\d{2}(?<tzmin>\\d{2})?
|
||||||
|
* HH[MM] ) )? $
|
||||||
|
*/
|
||||||
|
private static final String GENERALIZED_TIME_PATTERN =
|
||||||
|
"^(?<year>\\d{4})(?<month>\\d{2})(?<day>\\d{2})(?<hour>\\d{2})((?<minute>\\d{2})(?<second>\\d{2})?)?([.,](?<frac>\\d+))?(?<timezone>Z|([+-]\\d{2}(?<tzmin>\\d{2})?))?$";
|
||||||
|
|
||||||
|
private static final Pattern generalizedTimePattern = Pattern.compile(GENERALIZED_TIME_PATTERN);
|
||||||
|
|
||||||
|
public BerGeneralizedTime() {}
|
||||||
|
|
||||||
|
public BerGeneralizedTime(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerGeneralizedTime(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Calendar asCalendar() throws ParseException {
|
||||||
|
|
||||||
|
Matcher matcher = generalizedTimePattern.matcher(toString());
|
||||||
|
|
||||||
|
if (!matcher.find()) {
|
||||||
|
throw new ParseException("", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
String mg, mgf;
|
||||||
|
int year = Integer.parseInt(matcher.group("year"));
|
||||||
|
int month = Integer.parseInt(matcher.group("month"));
|
||||||
|
month -= 1; // java.util.Calendar's month goes from 0 to 11
|
||||||
|
int day = Integer.parseInt(matcher.group("day"));
|
||||||
|
int hour = Integer.parseInt(matcher.group("hour"));
|
||||||
|
|
||||||
|
mg = matcher.group("minute");
|
||||||
|
mgf = matcher.group("frac");
|
||||||
|
int minute = 0, second = 0, millisec = 0;
|
||||||
|
double frac = mgf == null ? 0 : Double.parseDouble("0." + mgf);
|
||||||
|
if (mg == null) {
|
||||||
|
// Missing minutes and seconds
|
||||||
|
if (mgf != null) {
|
||||||
|
// frac is a fraction of a hour
|
||||||
|
millisec = (int) Math.round(1000 * 60 * 60 * frac);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minute = Integer.parseInt(mg);
|
||||||
|
mg = matcher.group("second");
|
||||||
|
if (mg == null) {
|
||||||
|
// Missing seconds
|
||||||
|
if (mgf != null) {
|
||||||
|
// frac is a fraction of a minute
|
||||||
|
millisec = (int) Math.round(1000 * 60 * frac);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
second = Integer.parseInt(mg);
|
||||||
|
if (mgf != null) {
|
||||||
|
// frac is a fraction of a second
|
||||||
|
millisec = (int) Math.round(1000 * frac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mg = matcher.group("timezone");
|
||||||
|
String mgt = matcher.group("tzmin");
|
||||||
|
String timeZoneStr =
|
||||||
|
mg == null
|
||||||
|
? TimeZone.getDefault().getID()
|
||||||
|
: (mg.equals("Z") ? "UTC" : (mgt == null ? "GMT" + mg + "00" : "GMT" + mg));
|
||||||
|
TimeZone timeZone = TimeZone.getTimeZone(timeZoneStr);
|
||||||
|
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setLenient(true); // accept millisec greater than 999
|
||||||
|
calendar.set(year, month, day, hour, minute, second);
|
||||||
|
calendar.set(Calendar.MILLISECOND, millisec);
|
||||||
|
calendar.setTimeZone(timeZone);
|
||||||
|
|
||||||
|
return calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date asDate() throws ParseException {
|
||||||
|
return asCalendar().getTime();
|
||||||
|
}
|
||||||
|
}
|
132
src/teavm/java/com/beanit/asn1bean/ber/types/BerInteger.java
Normal file
132
src/teavm/java/com/beanit/asn1bean/ber/types/BerInteger.java
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class BerInteger implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.INTEGER_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public BigInteger value;
|
||||||
|
private byte[] code = null;
|
||||||
|
|
||||||
|
public BerInteger() {}
|
||||||
|
|
||||||
|
public BerInteger(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerInteger(BigInteger val) {
|
||||||
|
this.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerInteger(long val) {
|
||||||
|
this.value = BigInteger.valueOf(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encoded = value.toByteArray();
|
||||||
|
int codeLength = encoded.length;
|
||||||
|
reverseOS.write(encoded);
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
if (length.val < 1) {
|
||||||
|
throw new IOException("Decoded length of BerInteger is not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] byteCode = new byte[length.val];
|
||||||
|
Util.readFully(is, byteCode);
|
||||||
|
|
||||||
|
codeLength += length.val;
|
||||||
|
|
||||||
|
value = new BigInteger(byteCode);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(os, false);
|
||||||
|
code = os.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte byteValue() {
|
||||||
|
return value.byteValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short shortValue() {
|
||||||
|
return value.shortValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int intValue() {
|
||||||
|
return value.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long longValue() {
|
||||||
|
return value.longValue();
|
||||||
|
}
|
||||||
|
}
|
76
src/teavm/java/com/beanit/asn1bean/ber/types/BerNull.java
Normal file
76
src/teavm/java/com/beanit/asn1bean/ber/types/BerNull.java
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerNull implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.NULL_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerNull() {}
|
||||||
|
|
||||||
|
public BerNull(byte[] code) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = BerLength.encodeLength(reverseOS, 0);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
if (length.val != 0) {
|
||||||
|
throw new IOException("Decoded length of BerNull is not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ASN1_NULL";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BerObjectIdentifier implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.OBJECT_IDENTIFIER_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public int[] value;
|
||||||
|
private byte[] code = null;
|
||||||
|
|
||||||
|
public BerObjectIdentifier() {}
|
||||||
|
|
||||||
|
public BerObjectIdentifier(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerObjectIdentifier(int[] value) {
|
||||||
|
if ((value.length < 2)
|
||||||
|
|| ((value[0] == 0 || value[0] == 1) && (value[1] > 39))
|
||||||
|
|| value[0] > 2) {
|
||||||
|
throw new IllegalArgumentException("invalid object identifier components");
|
||||||
|
}
|
||||||
|
for (int objectIdentifierComponent : value) {
|
||||||
|
if (objectIdentifierComponent < 0) {
|
||||||
|
throw new IllegalArgumentException("invalid object identifier components");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstSubidentifier = 40 * value[0] + value[1];
|
||||||
|
|
||||||
|
int subidentifier;
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
for (int i = (value.length - 1); i > 0; i--) {
|
||||||
|
|
||||||
|
if (i == 1) {
|
||||||
|
subidentifier = firstSubidentifier;
|
||||||
|
} else {
|
||||||
|
subidentifier = value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// get length of subidentifier
|
||||||
|
int subIDLength = 1;
|
||||||
|
while (subidentifier > (Math.pow(2, (7 * subIDLength)) - 1)) {
|
||||||
|
subIDLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
reverseOS.write(subidentifier & 0x7f);
|
||||||
|
|
||||||
|
for (int j = 1; j <= (subIDLength - 1); j++) {
|
||||||
|
reverseOS.write(((subidentifier >> (7 * j)) & 0xff) | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += subIDLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
if (length.val == 0) {
|
||||||
|
value = new int[0];
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] byteCode = new byte[length.val];
|
||||||
|
Util.readFully(is, byteCode);
|
||||||
|
|
||||||
|
codeLength += length.val;
|
||||||
|
|
||||||
|
List<Integer> objectIdentifierComponentsList = new ArrayList<>();
|
||||||
|
|
||||||
|
int subIDEndIndex = 0;
|
||||||
|
while ((byteCode[subIDEndIndex] & 0x80) == 0x80) {
|
||||||
|
if (subIDEndIndex >= (length.val - 1)) {
|
||||||
|
throw new IOException("Invalid Object Identifier");
|
||||||
|
}
|
||||||
|
subIDEndIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int subidentifier = 0;
|
||||||
|
for (int i = 0; i <= subIDEndIndex; i++) {
|
||||||
|
subidentifier |= ((byteCode[i] & 0x7f) << ((subIDEndIndex - i) * 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subidentifier < 40) {
|
||||||
|
objectIdentifierComponentsList.add(0);
|
||||||
|
objectIdentifierComponentsList.add(subidentifier);
|
||||||
|
} else if (subidentifier < 80) {
|
||||||
|
objectIdentifierComponentsList.add(1);
|
||||||
|
objectIdentifierComponentsList.add(subidentifier - 40);
|
||||||
|
} else {
|
||||||
|
objectIdentifierComponentsList.add(2);
|
||||||
|
objectIdentifierComponentsList.add(subidentifier - 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
subIDEndIndex++;
|
||||||
|
|
||||||
|
while (subIDEndIndex < length.val) {
|
||||||
|
int subIDStartIndex = subIDEndIndex;
|
||||||
|
|
||||||
|
while ((byteCode[subIDEndIndex] & 0x80) == 0x80) {
|
||||||
|
if (subIDEndIndex == (length.val - 1)) {
|
||||||
|
throw new IOException("Invalid Object Identifier");
|
||||||
|
}
|
||||||
|
subIDEndIndex++;
|
||||||
|
}
|
||||||
|
subidentifier = 0;
|
||||||
|
for (int j = subIDStartIndex; j <= subIDEndIndex; j++) {
|
||||||
|
subidentifier |= ((byteCode[j] & 0x7f) << ((subIDEndIndex - j) * 7));
|
||||||
|
}
|
||||||
|
objectIdentifierComponentsList.add(subidentifier);
|
||||||
|
subIDEndIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = new int[objectIdentifierComponentsList.size()];
|
||||||
|
for (int i = 0; i < objectIdentifierComponentsList.size(); i++) {
|
||||||
|
value[i] = objectIdentifierComponentsList.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (value == null || value.length == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(Integer.toString(value[0]));
|
||||||
|
for (int i = 1; i < value.length; i++) {
|
||||||
|
sb.append(".").append(value[i]);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
142
src/teavm/java/com/beanit/asn1bean/ber/types/BerOctetString.java
Normal file
142
src/teavm/java/com/beanit/asn1bean/ber/types/BerOctetString.java
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import com.beanit.asn1bean.util.HexString;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerOctetString implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.OCTET_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public byte[] value;
|
||||||
|
|
||||||
|
public BerOctetString() {}
|
||||||
|
|
||||||
|
public BerOctetString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
reverseOS.write(value);
|
||||||
|
int codeLength = value.length;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
int nextByte = is.read();
|
||||||
|
switch (nextByte) {
|
||||||
|
case -1:
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
case 0x04:
|
||||||
|
return 1 + decodePrimitiveOctetString(is);
|
||||||
|
case 0x24:
|
||||||
|
return 1 + decodeConstructedOctetString(is);
|
||||||
|
default:
|
||||||
|
throw new IOException(
|
||||||
|
"Octet String identifier does not match, expected: 0x04 or 0x24, received: 0x"
|
||||||
|
+ HexString.fromByte((byte) nextByte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decodePrimitiveOctetString(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int decodeConstructedOctetString(InputStream is) throws IOException {
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
int lengthLength = length.decode(is);
|
||||||
|
|
||||||
|
value = new byte[0];
|
||||||
|
int vLength = 0;
|
||||||
|
|
||||||
|
if (length.val < 0) {
|
||||||
|
BerTag berTag = new BerTag();
|
||||||
|
vLength += berTag.decode(is);
|
||||||
|
while (!berTag.equals(0, 0, 0)) {
|
||||||
|
BerOctetString subOctetString = new BerOctetString();
|
||||||
|
vLength += subOctetString.decode(is, false);
|
||||||
|
value = concatenate(value, subOctetString.value);
|
||||||
|
vLength += berTag.decode(is);
|
||||||
|
}
|
||||||
|
vLength += BerLength.readEocByte(is);
|
||||||
|
} else {
|
||||||
|
while (vLength < length.val) {
|
||||||
|
BerOctetString subOctetString = new BerOctetString();
|
||||||
|
vLength += subOctetString.decode(is);
|
||||||
|
value = concatenate(value, subOctetString.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lengthLength + vLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] concatenate(byte[] a, byte[] b) {
|
||||||
|
int aLen = a.length;
|
||||||
|
int bLen = b.length;
|
||||||
|
|
||||||
|
byte[] c = new byte[aLen + bLen];
|
||||||
|
System.arraycopy(a, 0, c, 0, aLen);
|
||||||
|
System.arraycopy(b, 0, c, aLen, bLen);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int decodePrimitiveOctetString(InputStream is) throws IOException {
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
value = new byte[length.val];
|
||||||
|
|
||||||
|
if (length.val != 0) {
|
||||||
|
Util.readFully(is, value);
|
||||||
|
codeLength += length.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return HexString.fromBytes(value);
|
||||||
|
}
|
||||||
|
}
|
240
src/teavm/java/com/beanit/asn1bean/ber/types/BerReal.java
Normal file
240
src/teavm/java/com/beanit/asn1bean/ber/types/BerReal.java
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class BerReal implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.REAL_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public double value;
|
||||||
|
private byte[] code = null;
|
||||||
|
|
||||||
|
public BerReal() {}
|
||||||
|
|
||||||
|
public BerReal(byte[] code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerReal(double value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
if (code != null) {
|
||||||
|
reverseOS.write(code);
|
||||||
|
if (withTag) {
|
||||||
|
return tag.encode(reverseOS) + code.length;
|
||||||
|
}
|
||||||
|
return code.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int codeLength = encodeValue(reverseOS);
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int encodeValue(OutputStream reverseOS) throws IOException {
|
||||||
|
|
||||||
|
// explained in Annex C and Ch. 8.5 of X.690
|
||||||
|
|
||||||
|
// we use binary encoding, with base 2 and F==0
|
||||||
|
// F is only needed when encoding with base 8 or 16
|
||||||
|
|
||||||
|
long longBits = Double.doubleToLongBits(value);
|
||||||
|
|
||||||
|
boolean isNegative = (longBits & 0x8000000000000000L) == 0x8000000000000000L;
|
||||||
|
|
||||||
|
int exponent = ((int) (longBits >> 52)) & 0x7ff;
|
||||||
|
|
||||||
|
long mantissa = (longBits & 0x000fffffffffffffL) | 0x0010000000000000L;
|
||||||
|
|
||||||
|
if (exponent == 0x7ff) {
|
||||||
|
if (mantissa == 0x0010000000000000L) {
|
||||||
|
if (isNegative) {
|
||||||
|
// - infinity
|
||||||
|
reverseOS.write(0x41);
|
||||||
|
} else {
|
||||||
|
// + infinity
|
||||||
|
reverseOS.write(0x40);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
throw new IOException("NAN not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((exponent == 0 && mantissa == 0x0010000000000000L)) {
|
||||||
|
// zero
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// because IEEE double-precision format is (-1)^sign * 1.b51b50..b0 * 2^(e-1023) we need to
|
||||||
|
// subtract 1023 and 52
|
||||||
|
// from the exponent to get an exponent corresponding to an integer matissa as need here.
|
||||||
|
exponent -= 1075; // 1023 + 52 = 1075
|
||||||
|
|
||||||
|
// trailing zeros of the mantissa should be removed. Therefor find out how much the mantissa can
|
||||||
|
// be shifted and
|
||||||
|
// the exponent can be increased
|
||||||
|
int exponentIncr = 0;
|
||||||
|
while (((mantissa >> exponentIncr) & 0xff) == 0x00) {
|
||||||
|
exponentIncr += 8;
|
||||||
|
}
|
||||||
|
while (((mantissa >> exponentIncr) & 0x01) == 0x00) {
|
||||||
|
exponentIncr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
exponent += exponentIncr;
|
||||||
|
mantissa >>= exponentIncr;
|
||||||
|
|
||||||
|
int mantissaLength = (Long.SIZE - Long.numberOfLeadingZeros(mantissa) + 7) / 8;
|
||||||
|
|
||||||
|
for (int i = 0; i < mantissaLength; i++) {
|
||||||
|
reverseOS.write((int) (mantissa >> (8 * i)));
|
||||||
|
}
|
||||||
|
int codeLength = mantissaLength;
|
||||||
|
|
||||||
|
byte[] exponentBytes = BigInteger.valueOf(exponent).toByteArray();
|
||||||
|
reverseOS.write(exponentBytes);
|
||||||
|
codeLength += exponentBytes.length;
|
||||||
|
|
||||||
|
byte exponentFormat;
|
||||||
|
if (exponentBytes.length < 4) {
|
||||||
|
exponentFormat = (byte) (exponentBytes.length - 1);
|
||||||
|
} else {
|
||||||
|
reverseOS.write(exponentBytes.length);
|
||||||
|
codeLength++;
|
||||||
|
exponentFormat = 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNegative) {
|
||||||
|
reverseOS.write(0x80 | 0x40 | exponentFormat);
|
||||||
|
} else {
|
||||||
|
reverseOS.write(0x80 | exponentFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength++;
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
if (length.val == 0) {
|
||||||
|
value = 0;
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length.val == 1) {
|
||||||
|
int nextByte = is.read();
|
||||||
|
if (nextByte == -1) {
|
||||||
|
throw new EOFException("Unexpected end of input stream.");
|
||||||
|
}
|
||||||
|
if (nextByte == 0x40) {
|
||||||
|
value = Double.POSITIVE_INFINITY;
|
||||||
|
} else if (nextByte == 0x41) {
|
||||||
|
value = Double.NEGATIVE_INFINITY;
|
||||||
|
} else {
|
||||||
|
throw new IOException("invalid real encoding");
|
||||||
|
}
|
||||||
|
return codeLength + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] byteCode = new byte[length.val];
|
||||||
|
Util.readFully(is, byteCode);
|
||||||
|
|
||||||
|
if ((byteCode[0] & 0x80) != 0x80) {
|
||||||
|
throw new IOException("Only binary REAL encoding is supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += length.val;
|
||||||
|
int tempLength = 1;
|
||||||
|
|
||||||
|
int sign = 1;
|
||||||
|
if ((byteCode[0] & 0x40) == 0x40) {
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exponentLength = (byteCode[0] & 0x03) + 1;
|
||||||
|
if (exponentLength == 4) {
|
||||||
|
exponentLength = byteCode[1];
|
||||||
|
tempLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempLength += exponentLength;
|
||||||
|
|
||||||
|
int exponent = 0;
|
||||||
|
for (int i = 0; i < exponentLength; i++) {
|
||||||
|
exponent |= byteCode[1 + i] << (8 * (exponentLength - i - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
long mantissa = 0;
|
||||||
|
for (int i = 0; i < length.val - tempLength; i++) {
|
||||||
|
mantissa |= (byteCode[i + tempLength] & 0xffL) << (8 * (length.val - tempLength - i - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
value = sign * mantissa * Math.pow(2, exponent);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||||
|
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||||
|
encode(os, false);
|
||||||
|
code = os.getArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
}
|
63
src/teavm/java/com/beanit/asn1bean/ber/types/BerTime.java
Normal file
63
src/teavm/java/com/beanit/asn1bean/ber/types/BerTime.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.string.BerVisibleString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerTime extends BerVisibleString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.TIME_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerTime() {}
|
||||||
|
|
||||||
|
public BerTime(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerTime(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerTimeOfDay extends BerTime {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.TIME_OF_DAY_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerTimeOfDay() {}
|
||||||
|
|
||||||
|
public BerTimeOfDay(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerTimeOfDay(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
25
src/teavm/java/com/beanit/asn1bean/ber/types/BerType.java
Normal file
25
src/teavm/java/com/beanit/asn1bean/ber/types/BerType.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public interface BerType {
|
||||||
|
|
||||||
|
int encode(OutputStream reverseOS) throws IOException;
|
||||||
|
|
||||||
|
int decode(InputStream is) throws IOException;
|
||||||
|
}
|
118
src/teavm/java/com/beanit/asn1bean/ber/types/BerUtcTime.java
Normal file
118
src/teavm/java/com/beanit/asn1bean/ber/types/BerUtcTime.java
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.string.BerVisibleString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class BerUtcTime extends BerVisibleString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.UTC_TIME_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTC time is one of the following (ITU-T X.680 08/2015): YYMMDDhhmm[ss]Z YYMMDDhhmm[ss](+|-)hhmm
|
||||||
|
* Regexp: ^ (?<year>\\d{2}) YY (?<month>\\d{2}) MM (?<day>\\d{2}) DD (?<hour>\\d{2}) hh
|
||||||
|
* (?<minute>\\d{2}) mm (?<second>\\d{2})? ss (?<timezone> Z | Z or (+|-)hhmm ( [+-]\\d{4}
|
||||||
|
* (+|-)hhmm ) ) $
|
||||||
|
*/
|
||||||
|
private static final String UTC_TIME_PATTERN =
|
||||||
|
"^(?<year>\\d{2})(?<month>\\d{2})(?<day>\\d{2})(?<hour>\\d{2})(?<minute>\\d{2})(?<second>\\d{2})?(?<timezone>Z|([+-]\\d{4}))$";
|
||||||
|
|
||||||
|
private static final Pattern utcTimePattern = Pattern.compile(UTC_TIME_PATTERN);
|
||||||
|
|
||||||
|
public BerUtcTime() {}
|
||||||
|
|
||||||
|
public BerUtcTime(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerUtcTime(String valueAsString) {
|
||||||
|
super(valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
Calendar asCalendar() throws ParseException {
|
||||||
|
|
||||||
|
Matcher matcher = utcTimePattern.matcher(toString());
|
||||||
|
|
||||||
|
if (!matcher.find()) throw new ParseException("", 0);
|
||||||
|
|
||||||
|
String mg;
|
||||||
|
int year = Integer.parseInt(matcher.group("year"));
|
||||||
|
int month = Integer.parseInt(matcher.group("month"));
|
||||||
|
month -= 1; // java.util.Calendar's month goes from 0 to 11
|
||||||
|
int day = Integer.parseInt(matcher.group("day"));
|
||||||
|
int hour = Integer.parseInt(matcher.group("hour"));
|
||||||
|
int minute = Integer.parseInt(matcher.group("minute"));
|
||||||
|
mg = matcher.group("second");
|
||||||
|
int second = mg == null ? 0 : Integer.parseInt(mg);
|
||||||
|
|
||||||
|
mg = matcher.group("timezone");
|
||||||
|
String timeZoneStr = mg.equals("Z") ? "UTC" : "GMT" + mg;
|
||||||
|
TimeZone timeZone = TimeZone.getTimeZone(timeZoneStr);
|
||||||
|
|
||||||
|
Calendar calendar = Calendar.getInstance(timeZone);
|
||||||
|
|
||||||
|
// Add 2000 to the year
|
||||||
|
int century = (calendar.get(Calendar.YEAR) / 100) * 100;
|
||||||
|
year += century;
|
||||||
|
|
||||||
|
// noinspection MagicConstant
|
||||||
|
calendar.set(year, month, day, hour, minute, second);
|
||||||
|
calendar.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
|
return calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date asDate() throws ParseException {
|
||||||
|
return asCalendar().getTime();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerBMPString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.BMP_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerBMPString() {}
|
||||||
|
|
||||||
|
public BerBMPString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerGeneralString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.GENERAL_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerGeneralString() {}
|
||||||
|
|
||||||
|
public BerGeneralString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerGraphicString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.GRAPHIC_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerGraphicString() {}
|
||||||
|
|
||||||
|
public BerGraphicString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerIA5String extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.IA5_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerIA5String() {}
|
||||||
|
|
||||||
|
public BerIA5String(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerNumericString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.NUMERIC_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerNumericString() {}
|
||||||
|
|
||||||
|
public BerNumericString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerObjectDescriptor extends BerGraphicString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.OBJECT_DESCRIPTOR_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerObjectDescriptor() {}
|
||||||
|
|
||||||
|
public BerObjectDescriptor(byte[] value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength;
|
||||||
|
|
||||||
|
codeLength = super.encode(reverseOS, false);
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerPrintableString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.PRINTABLE_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerPrintableString() {}
|
||||||
|
|
||||||
|
public BerPrintableString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerTeletexString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.TELETEX_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerTeletexString() {}
|
||||||
|
|
||||||
|
public BerTeletexString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class BerUTF8String extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.UTF8_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerUTF8String() {}
|
||||||
|
|
||||||
|
public BerUTF8String(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerUTF8String(String valueAsString) {
|
||||||
|
value = valueAsString.getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerUniversalString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.UNIVERSAL_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerUniversalString() {}
|
||||||
|
|
||||||
|
public BerUniversalString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BerVideotexString extends BerOctetString {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.VIDEOTEX_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public BerVideotexString() {}
|
||||||
|
|
||||||
|
public BerVideotexString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = super.encode(reverseOS, false);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
codeLength += super.decode(is, false);
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 The ASN1bean Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.ber.types.string;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.beanit.asn1bean.ber.BerLength;
|
||||||
|
import com.beanit.asn1bean.ber.BerTag;
|
||||||
|
import com.beanit.asn1bean.ber.internal.Util;
|
||||||
|
import com.beanit.asn1bean.ber.types.BerType;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BerVisibleString implements Serializable, BerType {
|
||||||
|
|
||||||
|
public static final BerTag tag =
|
||||||
|
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.VISIBLE_STRING_TAG);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
public byte[] value;
|
||||||
|
|
||||||
|
public BerVisibleString() {}
|
||||||
|
|
||||||
|
public BerVisibleString(byte[] value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BerVisibleString(String valueAsString) {
|
||||||
|
value = valueAsString.getBytes(UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encode(OutputStream reverseOS) throws IOException {
|
||||||
|
return encode(reverseOS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
reverseOS.write(value);
|
||||||
|
int codeLength = value.length;
|
||||||
|
|
||||||
|
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.encode(reverseOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream is) throws IOException {
|
||||||
|
return decode(is, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||||
|
|
||||||
|
int codeLength = 0;
|
||||||
|
|
||||||
|
if (withTag) {
|
||||||
|
codeLength += tag.decodeAndCheck(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
BerLength length = new BerLength();
|
||||||
|
codeLength += length.decode(is);
|
||||||
|
|
||||||
|
value = new byte[length.val];
|
||||||
|
|
||||||
|
if (length.val != 0) {
|
||||||
|
Util.readFully(is, value);
|
||||||
|
codeLength += length.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new String(value, UTF_8);
|
||||||
|
}
|
||||||
|
}
|
152
src/teavm/java/com/beanit/asn1bean/util/HexString.java
Normal file
152
src/teavm/java/com/beanit/asn1bean/util/HexString.java
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 beanit
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||||
|
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||||
|
* or implied. See the License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package com.beanit.asn1bean.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class HexString {
|
||||||
|
|
||||||
|
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
/** Don't let anyone instantiate this class. */
|
||||||
|
private HexString() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the byte as a hex string. If b is less than 16 the hex string returned contains a
|
||||||
|
* leading zero.
|
||||||
|
*
|
||||||
|
* @param b the byte to be converted
|
||||||
|
* @return the hex string.
|
||||||
|
*/
|
||||||
|
public static String fromByte(byte b) {
|
||||||
|
return fromBytes(new byte[] {b});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromByte(int b) {
|
||||||
|
return fromBytes(new byte[] {(byte) b});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the integer value as hex string filled with leading zeros.
|
||||||
|
*
|
||||||
|
* @param i the integer value to be converted
|
||||||
|
* @return the hex string
|
||||||
|
*/
|
||||||
|
public static String fromInt(int i) {
|
||||||
|
byte[] bytes = new byte[] {(byte) (i >> 24), (byte) (i >> 16), (byte) (i >> 8), (byte) i};
|
||||||
|
return fromBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the long value as hex string filled with leading zeros.
|
||||||
|
*
|
||||||
|
* @param l the long value to be converted
|
||||||
|
* @return the hex string
|
||||||
|
*/
|
||||||
|
public static String fromLong(long l) {
|
||||||
|
byte[] bytes =
|
||||||
|
new byte[] {
|
||||||
|
(byte) (l >> 56),
|
||||||
|
(byte) (l >> 48),
|
||||||
|
(byte) (l >> 40),
|
||||||
|
(byte) (l >> 32),
|
||||||
|
(byte) (l >> 24),
|
||||||
|
(byte) (l >> 16),
|
||||||
|
(byte) (l >> 8),
|
||||||
|
(byte) l
|
||||||
|
};
|
||||||
|
return fromBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytes(byte[] bytes) {
|
||||||
|
return fromBytes(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytesFormatted(byte[] bytes) {
|
||||||
|
return fromBytesFormatted(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytes(byte[] bytes, int offset, int length) {
|
||||||
|
char[] hexChars = new char[length * 2];
|
||||||
|
for (int j = 0; j < length; j++) {
|
||||||
|
int v = bytes[j + offset] & 0xff;
|
||||||
|
hexChars[j * 2] = hexArray[v >>> 4];
|
||||||
|
hexChars[j * 2 + 1] = hexArray[v & 0x0f];
|
||||||
|
}
|
||||||
|
return new String(hexChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytes(ByteBuffer buffer) {
|
||||||
|
return fromBytes(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.limit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytesFormatted(byte[] bytes, int offset, int length) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
int l = 1;
|
||||||
|
for (int i = offset; i < (offset + length); i++) {
|
||||||
|
if ((l != 1) && ((l - 1) % 8 == 0)) {
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
if ((l != 1) && ((l - 1) % 16 == 0)) {
|
||||||
|
builder.append('\n');
|
||||||
|
}
|
||||||
|
l++;
|
||||||
|
appendFromByte(bytes[i], builder);
|
||||||
|
if (i != offset + length - 1) {
|
||||||
|
builder.append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given hex string to a byte array.
|
||||||
|
*
|
||||||
|
* @param hexString the hex string
|
||||||
|
* @return the bytes
|
||||||
|
* @throws NumberFormatException if the string is not a valid hex string
|
||||||
|
*/
|
||||||
|
public static byte[] toBytes(String hexString) {
|
||||||
|
|
||||||
|
Objects.requireNonNull(hexString);
|
||||||
|
if ((hexString.length() == 0) || ((hexString.length() % 2) != 0)) {
|
||||||
|
throw new NumberFormatException("argument is not a valid hex string");
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = hexString.length();
|
||||||
|
|
||||||
|
byte[] data = new byte[length / 2];
|
||||||
|
for (int i = 0; i < length; i += 2) {
|
||||||
|
int firstCharacter = Character.digit(hexString.charAt(i), 16);
|
||||||
|
int secondCharacter = Character.digit(hexString.charAt(i + 1), 16);
|
||||||
|
|
||||||
|
if (firstCharacter == -1 || secondCharacter == -1) {
|
||||||
|
throw new NumberFormatException("argument is not a valid hex string");
|
||||||
|
}
|
||||||
|
|
||||||
|
data[i / 2] = (byte) ((firstCharacter << 4) + secondCharacter);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void appendFromByte(byte b, StringBuilder builder) {
|
||||||
|
builder.append(fromByte(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void appendFromBytes(StringBuilder builder, byte[] bytes, int offset, int length) {
|
||||||
|
builder.append(fromBytes(bytes, offset, length));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
package com.rhg.rsa;
|
package com.rhg.rsa;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.SecureRandom;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing private and public keys with the ability to generate new keys.
|
* Class representing private and public keys with the ability to generate new keys.
|
||||||
*
|
*
|
||||||
|
@ -14,7 +15,7 @@ public class RSAKeyGenerator extends RSACompleteKey
|
||||||
private static final int MIN_BIT_LENGTH = 1024;
|
private static final int MIN_BIT_LENGTH = 1024;
|
||||||
|
|
||||||
/** Source of securely (pseudo-) random bits. */
|
/** Source of securely (pseudo-) random bits. */
|
||||||
SecureRandom rand = new SecureRandom();
|
Random rand = new Random();
|
||||||
|
|
||||||
/** The number of bits required in the modulus. */
|
/** The number of bits required in the modulus. */
|
||||||
private int bitLength;
|
private int bitLength;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.rhg.rsa;
|
package com.rhg.rsa;
|
||||||
|
|
||||||
import org.teavm.jso.JSBody;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package me.ayunami2000.ayuncraft;
|
package me.ayunami2000.ayuncraft;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.*;
|
||||||
import java.io.OutputStream;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import me.ayunami2000.ayuncraft.java.security.Key;
|
import me.ayunami2000.ayuncraft.java.security.Key;
|
||||||
import me.ayunami2000.ayuncraft.java.security.PrivateKey;
|
|
||||||
import me.ayunami2000.ayuncraft.java.security.PublicKey;
|
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.Base64;
|
import net.lax1dude.eaglercraft.Base64;
|
||||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||||
|
@ -19,6 +17,7 @@ import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||||
import me.ayunami2000.ayuncraft.javax.crypto.SecretKey;
|
import me.ayunami2000.ayuncraft.javax.crypto.SecretKey;
|
||||||
import me.ayunami2000.ayuncraft.javax.crypto.spec.SecretKeySpec;
|
import me.ayunami2000.ayuncraft.javax.crypto.spec.SecretKeySpec;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
|
import org.teavm.jso.typedarrays.Uint8Array;
|
||||||
|
|
||||||
public class CryptManager
|
public class CryptManager
|
||||||
{
|
{
|
||||||
|
@ -31,128 +30,61 @@ public class CryptManager
|
||||||
return new SecretKeySpec(baseSharedKey,"AES");
|
return new SecretKeySpec(baseSharedKey,"AES");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@JSBody(params = {"base64enc"}, script =
|
||||||
@JSBody(params = {"base64enc"}, script = "window.servercertraw=base64enc;window.servercert=new x509.X509Certificate(base64enc);")
|
"var xd=window.ASN1.parse(window.PEM.parseBlock(base64enc).der);" +
|
||||||
private static native void setupDecode(String base64enc);
|
"xd=xd.children.find(e=>{return e.type==3;});" +
|
||||||
|
"xd=xd.children.find(e=>{return e.type==48;});" +
|
||||||
@JSBody(params = {}, script = "return window.servercert.publickey.algorithm.name;")
|
"return [xd.children[0].value,xd.children[1].value];")
|
||||||
private static native String decodeAlgorithm();
|
private static native Uint8Array[] x509decode(String base64enc);
|
||||||
|
|
||||||
@JSBody(params = {}, script = "return window.servercert.publickey.algorithm.publicExponent;")
|
|
||||||
private static native Uint8Array decodePublicExponent();
|
|
||||||
|
|
||||||
@JSBody(params = {}, script = "return window.servercert.publickey.algorithm.modulusLength;")
|
|
||||||
private static native int decodeModulusLength();
|
|
||||||
|
|
||||||
@JSBody(params = {}, script = "return new Uint8Array(window.servercert.publickey.rawData);")
|
|
||||||
private static native Uint8Array decodeData();
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new PublicKey from encoded X.509 data
|
* Create a new PublicKey from encoded X.509 data
|
||||||
*/
|
*/
|
||||||
public static PublicKey decodePublicKey(byte[] par0ArrayOfByte)
|
public static PubKey decodePublicKey(byte[] par0ArrayOfByte)
|
||||||
{
|
{
|
||||||
/*
|
Uint8Array[] resarr=x509decode(Base64.encodeBase64String(par0ArrayOfByte));
|
||||||
setupDecode(Base64.encodeBase64String(par0ArrayOfByte));
|
PubKey results = new PubKey(par0ArrayOfByte,new BigInteger(uInt8toByteArr(resarr[0])),new BigInteger(uInt8toByteArr(resarr[1])));
|
||||||
Uint8Array a = decodeData();
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] uInt8toByteArr(Uint8Array a){
|
||||||
byte[] b = new byte[a.getByteLength()];
|
byte[] b = new byte[a.getByteLength()];
|
||||||
for(int i = 0; i < b.length; ++i) {
|
for(int i = 0; i < b.length; ++i) {
|
||||||
b[i] = (byte) (a.get(i) & 0xFF);
|
b[i] = (byte) (a.get(i) & 0xFF);
|
||||||
}
|
}
|
||||||
*/
|
return b;
|
||||||
|
|
||||||
//ParseRSAPublicKey parser = new ParseRSAPublicKey(par0ArrayOfByte);
|
|
||||||
//BigInteger[] results = parser.parse();
|
|
||||||
|
|
||||||
//return new RSAPublicKeySpec(results[0],results[1]);
|
|
||||||
return new ModifiablePublicKey("RSA","X.509",par0ArrayOfByte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt shared secret AES key using RSA private key
|
* Decrypt shared secret AES key using RSA private key
|
||||||
*/
|
*/
|
||||||
public static SecretKey decryptSharedKey(PrivateKey par0PrivateKey, byte[] par1ArrayOfByte)
|
public static SecretKey decryptSharedKey(PubKey par0PrivateKey, byte[] par1ArrayOfByte)
|
||||||
{
|
{
|
||||||
return new SecretKeySpec(decryptData(par0PrivateKey, par1ArrayOfByte), "AES");
|
return new SecretKeySpec(decryptData(par0PrivateKey, par1ArrayOfByte), "AES");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
///*
|
||||||
private static RSA rsa=new RSA(1024);
|
@JSBody(params = {"pubkey", "mod", "indata"}, script = "var rsa=new RSAKey();rsa.setPublic(b64tohex(mod),b64tohex(pubkey));var res=hex2b64(rsa.encrypt(atob(indata)));return res;")
|
||||||
|
private static native String encryptDataNative(String pubkey, String mod, String indata);
|
||||||
|
|
||||||
static {
|
@JSBody(params = {"privkey", "mod", "indata"}, script = "var rsa=new RSAKey();rsa.setPrivate(b64tohex(mod),b64tohex(privkey));var res=rsa.decrypt(b64tohex(indata));return res;")
|
||||||
rsa.setModulus(BigInteger.valueOf(16));
|
private static native String decryptDataNative(String pubkey, String mod, String indata);
|
||||||
}
|
//*/
|
||||||
*/
|
|
||||||
//private static final BigInteger modu = new BigInteger("1000000000000000000000000000000");
|
|
||||||
|
|
||||||
@JSBody(params = {"pubkey", "indata"}, script = "var enc=new JSEncrypt();enc.setPublicKey(pubkey);var res=enc.encrypt(indata);return res;")
|
|
||||||
private static native String encryptDataNative(String pubkey, String indata);
|
|
||||||
|
|
||||||
@JSBody(params = {"privkey", "indata"}, script = "var dec=new JSEncrypt();dec.setPrivateKey(privkey);var res=dec.decrypt(indata);return res;")
|
|
||||||
private static native String decryptDataNative(String privkey, String indata);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypt byte[] data with RSA public key
|
* Encrypt byte[] data with RSA public key
|
||||||
*/
|
*/
|
||||||
public static byte[] encryptData(Key par0Key, byte[] par1ArrayOfByte)
|
public static byte[] encryptData(PubKey par0Key, byte[] par1ArrayOfByte)
|
||||||
{
|
{
|
||||||
return Base64.decodeBase64(encryptDataNative("-----BEGIN PUBLIC KEY-----\n"+Base64.encodeBase64String(par0Key.getEncoded()).replaceAll("(.{64})", "$1\n")+"\n-----END PUBLIC KEY-----",Base64.encodeBase64String(par1ArrayOfByte)));
|
return Base64.decodeBase64(encryptDataNative(Base64.encodeBase64String(par0Key.getPriExp().toByteArray()),Base64.encodeBase64String(par0Key.getModulus().toByteArray()),Base64.encodeBase64String(par1ArrayOfByte)));
|
||||||
/*
|
|
||||||
try {
|
|
||||||
//System.out.println(Arrays.toString(par0Key.getEncoded()));
|
|
||||||
//System.out.println(Arrays.toString(par1ArrayOfByte));
|
|
||||||
RSAPublicKey rsaPublicKey = new RSAPublicKey(modu, new BigInteger(par0Key.getEncoded()));
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
rsaPublicKey.use(par1ArrayOfByte, baos);
|
|
||||||
return baos.toByteArray();
|
|
||||||
}catch(Exception e){
|
|
||||||
System.err.println(e.getClass().getName() + "\n" + e.getMessage());
|
|
||||||
//e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
try {
|
|
||||||
rsa.setPublicKey(new BigInteger(par0Key.getEncoded()));
|
|
||||||
BigInteger res = rsa.encrypt(new BigInteger(par1ArrayOfByte));
|
|
||||||
return res.toByteArray();
|
|
||||||
}catch(Exception e){
|
|
||||||
System.err.println(e.getClass().getName() + "\n" + e.getMessage());
|
|
||||||
//e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypt byte[] data with RSA private key
|
* Decrypt byte[] data with RSA private key
|
||||||
*/
|
*/
|
||||||
public static byte[] decryptData(Key par0Key, byte[] par1ArrayOfByte)
|
public static byte[] decryptData(PubKey par0Key, byte[] par1ArrayOfByte)
|
||||||
{
|
{
|
||||||
return Base64.decodeBase64(decryptDataNative("-----BEGIN RSA PRIVATE KEY-----\n"+Base64.encodeBase64String(par0Key.getEncoded()).replaceAll("(.{64})", "$1\n")+"\n-----END RSA PRIVATE KEY-----",Base64.encodeBase64String(par1ArrayOfByte)));
|
return Base64.decodeBase64(decryptDataNative(Base64.encodeBase64String(par0Key.getPriExp().toByteArray()),Base64.encodeBase64String(par0Key.getModulus().toByteArray()),Base64.encodeBase64String(par1ArrayOfByte)));
|
||||||
/*
|
|
||||||
try{
|
|
||||||
RSAPrivateKey rsaPrivateKey = new RSAPrivateKey(modu,new BigInteger(par0Key.getEncoded()));
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
rsaPrivateKey.use(par1ArrayOfByte,baos);
|
|
||||||
return baos.toByteArray();
|
|
||||||
}catch(Exception e){
|
|
||||||
System.err.println(e.getClass().getName() + "\n" + e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
try {
|
|
||||||
rsa.setPrivateKey(new BigInteger(par0Key.getEncoded()));
|
|
||||||
BigInteger res = rsa.decrypt(new BigInteger(par1ArrayOfByte));
|
|
||||||
return res.toByteArray();
|
|
||||||
}catch(Exception e){
|
|
||||||
System.err.println(e.getClass().getName() + "\n" + e.getMessage());
|
|
||||||
//e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -8,7 +8,10 @@ public class ParseRSAPublicKey {
|
||||||
private static final int INTEGER = 0x02;
|
private static final int INTEGER = 0x02;
|
||||||
private final ByteBuffer derBuf;
|
private final ByteBuffer derBuf;
|
||||||
|
|
||||||
|
private static byte[] derDat;
|
||||||
|
|
||||||
public ParseRSAPublicKey(byte[] der) {
|
public ParseRSAPublicKey(byte[] der) {
|
||||||
|
derDat=der;
|
||||||
derBuf = ByteBuffer.wrap(der);
|
derBuf = ByteBuffer.wrap(der);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +69,7 @@ public class ParseRSAPublicKey {
|
||||||
}
|
}
|
||||||
return new BigInteger(1, getArray((int) length));
|
return new BigInteger(1, getArray((int) length));
|
||||||
}
|
}
|
||||||
public BigInteger[] parse() {
|
public PubKey parse() {
|
||||||
// Parse SEQUENCE header
|
// Parse SEQUENCE header
|
||||||
if (parseId() != SEQUENCE) {
|
if (parseId() != SEQUENCE) {
|
||||||
throw new RuntimeException("expected SEQUENCE tag");
|
throw new RuntimeException("expected SEQUENCE tag");
|
||||||
|
@ -78,7 +81,6 @@ public class ParseRSAPublicKey {
|
||||||
// Parse INTEGER modulus
|
// Parse INTEGER modulus
|
||||||
BigInteger n = parseInteger();
|
BigInteger n = parseInteger();
|
||||||
BigInteger e = parseInteger();
|
BigInteger e = parseInteger();
|
||||||
return new BigInteger[] {n, e};
|
return new PubKey(derDat, n, e);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
27
src/teavm/java/me/ayunami2000/ayuncraft/PubKey.java
Normal file
27
src/teavm/java/me/ayunami2000/ayuncraft/PubKey.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package me.ayunami2000.ayuncraft;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class PubKey {
|
||||||
|
private static byte[] encoded=null;
|
||||||
|
private static BigInteger modulus=null;
|
||||||
|
private static BigInteger priexp=null;
|
||||||
|
|
||||||
|
public PubKey(byte[] e, BigInteger m, BigInteger p){
|
||||||
|
encoded=e;
|
||||||
|
modulus=m;
|
||||||
|
priexp=p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEncoded(){
|
||||||
|
return encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getModulus(){
|
||||||
|
return modulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getPriExp(){
|
||||||
|
return priexp;
|
||||||
|
}
|
||||||
|
}
|
20
src/teavm/java/org/bouncycastle/crypto/BlockCipher.java
Normal file
20
src/teavm/java/org/bouncycastle/crypto/BlockCipher.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public interface BlockCipher
|
||||||
|
{
|
||||||
|
void init(boolean var1, CipherParameters var2) throws IllegalArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of the algorithm the cipher implements.
|
||||||
|
*/
|
||||||
|
String getAlgorithmName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the block size for this cipher (in bytes).
|
||||||
|
*/
|
||||||
|
int getBlockSize();
|
||||||
|
|
||||||
|
int processBlock(byte[] var1, int var2, byte[] var3, int var4) throws DataLengthException, IllegalStateException;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
}
|
161
src/teavm/java/org/bouncycastle/crypto/BufferedBlockCipher.java
Normal file
161
src/teavm/java/org/bouncycastle/crypto/BufferedBlockCipher.java
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public class BufferedBlockCipher
|
||||||
|
{
|
||||||
|
protected byte[] buf;
|
||||||
|
protected int bufOff;
|
||||||
|
protected boolean forEncryption;
|
||||||
|
protected BlockCipher cipher;
|
||||||
|
protected boolean partialBlockOkay;
|
||||||
|
protected boolean pgpCFB;
|
||||||
|
|
||||||
|
protected BufferedBlockCipher() {}
|
||||||
|
|
||||||
|
public BufferedBlockCipher(BlockCipher par1BlockCipher)
|
||||||
|
{
|
||||||
|
this.cipher = par1BlockCipher;
|
||||||
|
this.buf = new byte[par1BlockCipher.getBlockSize()];
|
||||||
|
this.bufOff = 0;
|
||||||
|
String var2 = par1BlockCipher.getAlgorithmName();
|
||||||
|
int var3 = var2.indexOf(47) + 1;
|
||||||
|
this.pgpCFB = var3 > 0 && var2.startsWith("PGP", var3);
|
||||||
|
|
||||||
|
if (this.pgpCFB)
|
||||||
|
{
|
||||||
|
this.partialBlockOkay = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.partialBlockOkay = var3 > 0 && (var2.startsWith("CFB", var3) || var2.startsWith("OFB", var3) || var2.startsWith("OpenPGP", var3) || var2.startsWith("SIC", var3) || var2.startsWith("GCTR", var3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(boolean par1, CipherParameters par2CipherParameters) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
this.forEncryption = par1;
|
||||||
|
this.reset();
|
||||||
|
this.cipher.init(par1, par2CipherParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockSize()
|
||||||
|
{
|
||||||
|
return this.cipher.getBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUpdateOutputSize(int par1)
|
||||||
|
{
|
||||||
|
int var2 = par1 + this.bufOff;
|
||||||
|
int var3;
|
||||||
|
|
||||||
|
if (this.pgpCFB)
|
||||||
|
{
|
||||||
|
var3 = var2 % this.buf.length - (this.cipher.getBlockSize() + 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var3 = var2 % this.buf.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var2 - var3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOutputSize(int par1)
|
||||||
|
{
|
||||||
|
return par1 + this.bufOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int processByte(byte[] par1ArrayOfByte, int par2, int par3, byte[] par4ArrayOfByte, int par5) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
if (par3 < 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Can\'t have a negative input length!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int var6 = this.getBlockSize();
|
||||||
|
int var7 = this.getUpdateOutputSize(par3);
|
||||||
|
|
||||||
|
if (var7 > 0 && par5 + var7 > par4ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("output buffer too short");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int var8 = 0;
|
||||||
|
int var9 = this.buf.length - this.bufOff;
|
||||||
|
|
||||||
|
if (par3 > var9)
|
||||||
|
{
|
||||||
|
System.arraycopy(par1ArrayOfByte, par2, this.buf, this.bufOff, var9);
|
||||||
|
var8 += this.cipher.processBlock(this.buf, 0, par4ArrayOfByte, par5);
|
||||||
|
this.bufOff = 0;
|
||||||
|
par3 -= var9;
|
||||||
|
|
||||||
|
for (par2 += var9; par3 > this.buf.length; par2 += var6)
|
||||||
|
{
|
||||||
|
var8 += this.cipher.processBlock(par1ArrayOfByte, par2, par4ArrayOfByte, par5 + var8);
|
||||||
|
par3 -= var6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(par1ArrayOfByte, par2, this.buf, this.bufOff, par3);
|
||||||
|
this.bufOff += par3;
|
||||||
|
|
||||||
|
if (this.bufOff == this.buf.length)
|
||||||
|
{
|
||||||
|
var8 += this.cipher.processBlock(this.buf, 0, par4ArrayOfByte, par5 + var8);
|
||||||
|
this.bufOff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int doFinal(byte[] par1ArrayOfByte, int par2) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
int var4;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int var3 = 0;
|
||||||
|
|
||||||
|
if (par2 + this.bufOff > par1ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("output buffer too short for doFinal()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.bufOff != 0)
|
||||||
|
{
|
||||||
|
if (!this.partialBlockOkay)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("data not block size aligned");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cipher.processBlock(this.buf, 0, this.buf, 0);
|
||||||
|
var3 = this.bufOff;
|
||||||
|
this.bufOff = 0;
|
||||||
|
System.arraycopy(this.buf, 0, par1ArrayOfByte, par2, var3);
|
||||||
|
}
|
||||||
|
|
||||||
|
var4 = var3;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return var4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
for (int var1 = 0; var1 < this.buf.length; ++var1)
|
||||||
|
{
|
||||||
|
this.buf[var1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bufOff = 0;
|
||||||
|
this.cipher.reset();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class CipherKeyGenerator
|
||||||
|
{
|
||||||
|
protected Random random;
|
||||||
|
protected int strength;
|
||||||
|
|
||||||
|
public void init(KeyGenerationParameters par1)
|
||||||
|
{
|
||||||
|
this.random = par1.getRandom();
|
||||||
|
this.strength = (par1.getStrength() + 7) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateKey()
|
||||||
|
{
|
||||||
|
byte[] var1 = new byte[this.strength];
|
||||||
|
this.random.nextBytes(var1);
|
||||||
|
return var1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public interface CipherParameters
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public class DataLengthException extends RuntimeCryptoException
|
||||||
|
{
|
||||||
|
public DataLengthException() {}
|
||||||
|
|
||||||
|
public DataLengthException(String par1Str)
|
||||||
|
{
|
||||||
|
super(par1Str);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class KeyGenerationParameters
|
||||||
|
{
|
||||||
|
private Random random;
|
||||||
|
private int strength;
|
||||||
|
|
||||||
|
public KeyGenerationParameters(Random par1SecureRandom, int par2)
|
||||||
|
{
|
||||||
|
this.random = par1SecureRandom;
|
||||||
|
this.strength = par2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the random source associated with this generator.
|
||||||
|
*/
|
||||||
|
public Random getRandom()
|
||||||
|
{
|
||||||
|
return this.random;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bit strength for keys produced by this generator.
|
||||||
|
*/
|
||||||
|
public int getStrength()
|
||||||
|
{
|
||||||
|
return this.strength;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public class RuntimeCryptoException extends RuntimeException
|
||||||
|
{
|
||||||
|
public RuntimeCryptoException() {}
|
||||||
|
|
||||||
|
public RuntimeCryptoException(String par1Str)
|
||||||
|
{
|
||||||
|
super(par1Str);
|
||||||
|
}
|
||||||
|
}
|
11
src/teavm/java/org/bouncycastle/crypto/StreamCipher.java
Normal file
11
src/teavm/java/org/bouncycastle/crypto/StreamCipher.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package org.bouncycastle.crypto;
|
||||||
|
|
||||||
|
public interface StreamCipher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Encrypt/decrypt a single byte, returning the result.
|
||||||
|
*/
|
||||||
|
byte returnByte(byte var1);
|
||||||
|
|
||||||
|
void processBytes(byte[] var1, int var2, int var3, byte[] var4, int var5) throws DataLengthException;
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
package org.bouncycastle.crypto.engines;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.BlockCipher;
|
||||||
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
|
import org.bouncycastle.crypto.DataLengthException;
|
||||||
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||||||
|
|
||||||
|
public class AESFastEngine implements BlockCipher
|
||||||
|
{
|
||||||
|
private static final byte[] S = new byte[] {(byte)99, (byte)124, (byte)119, (byte)123, (byte) - 14, (byte)107, (byte)111, (byte) - 59, (byte)48, (byte)1, (byte)103, (byte)43, (byte) - 2, (byte) - 41, (byte) - 85, (byte)118, (byte) - 54, (byte) - 126, (byte) - 55, (byte)125, (byte) - 6, (byte)89, (byte)71, (byte) - 16, (byte) - 83, (byte) - 44, (byte) - 94, (byte) - 81, (byte) - 100, (byte) - 92, (byte)114, (byte) - 64, (byte) - 73, (byte) - 3, (byte) - 109, (byte)38, (byte)54, (byte)63, (byte) - 9, (byte) - 52, (byte)52, (byte) - 91, (byte) - 27, (byte) - 15, (byte)113, (byte) - 40, (byte)49, (byte)21, (byte)4, (byte) - 57, (byte)35, (byte) - 61, (byte)24, (byte) - 106, (byte)5, (byte) - 102, (byte)7, (byte)18, (byte) - 128, (byte) - 30, (byte) - 21, (byte)39, (byte) - 78, (byte)117, (byte)9, (byte) - 125, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte) - 96, (byte)82, (byte)59, (byte) - 42, (byte) - 77, (byte)41, (byte) - 29, (byte)47, (byte) - 124, (byte)83, (byte) - 47, (byte)0, (byte) - 19, (byte)32, (byte) - 4, (byte) - 79, (byte)91, (byte)106, (byte) - 53, (byte) - 66, (byte)57, (byte)74, (byte)76, (byte)88, (byte) - 49, (byte) - 48, (byte) - 17, (byte) - 86, (byte) - 5, (byte)67, (byte)77, (byte)51, (byte) - 123, (byte)69, (byte) - 7, (byte)2, (byte)127, (byte)80, (byte)60, (byte) - 97, (byte) - 88, (byte)81, (byte) - 93, (byte)64, (byte) - 113, (byte) - 110, (byte) - 99, (byte)56, (byte) - 11, (byte) - 68, (byte) - 74, (byte) - 38, (byte)33, (byte)16, (byte) - 1, (byte) - 13, (byte) - 46, (byte) - 51, (byte)12, (byte)19, (byte) - 20, (byte)95, (byte) - 105, (byte)68, (byte)23, (byte) - 60, (byte) - 89, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115, (byte)96, (byte) - 127, (byte)79, (byte) - 36, (byte)34, (byte)42, (byte) - 112, (byte) - 120, (byte)70, (byte) - 18, (byte) - 72, (byte)20, (byte) - 34, (byte)94, (byte)11, (byte) - 37, (byte) - 32, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92, (byte) - 62, (byte) - 45, (byte) - 84, (byte)98, (byte) - 111, (byte) - 107, (byte) - 28, (byte)121, (byte) - 25, (byte) - 56, (byte)55, (byte)109, (byte) - 115, (byte) - 43, (byte)78, (byte) - 87, (byte)108, (byte)86, (byte) - 12, (byte) - 22, (byte)101, (byte)122, (byte) - 82, (byte)8, (byte) - 70, (byte)120, (byte)37, (byte)46, (byte)28, (byte) - 90, (byte) - 76, (byte) - 58, (byte) - 24, (byte) - 35, (byte)116, (byte)31, (byte)75, (byte) - 67, (byte) - 117, (byte) - 118, (byte)112, (byte)62, (byte) - 75, (byte)102, (byte)72, (byte)3, (byte) - 10, (byte)14, (byte)97, (byte)53, (byte)87, (byte) - 71, (byte) - 122, (byte) - 63, (byte)29, (byte) - 98, (byte) - 31, (byte) - 8, (byte) - 104, (byte)17, (byte)105, (byte) - 39, (byte) - 114, (byte) - 108, (byte) - 101, (byte)30, (byte) - 121, (byte) - 23, (byte) - 50, (byte)85, (byte)40, (byte) - 33, (byte) - 116, (byte) - 95, (byte) - 119, (byte)13, (byte) - 65, (byte) - 26, (byte)66, (byte)104, (byte)65, (byte) - 103, (byte)45, (byte)15, (byte) - 80, (byte)84, (byte) - 69, (byte)22};
|
||||||
|
private static final byte[] Si = new byte[] {(byte)82, (byte)9, (byte)106, (byte) - 43, (byte)48, (byte)54, (byte) - 91, (byte)56, (byte) - 65, (byte)64, (byte) - 93, (byte) - 98, (byte) - 127, (byte) - 13, (byte) - 41, (byte) - 5, (byte)124, (byte) - 29, (byte)57, (byte) - 126, (byte) - 101, (byte)47, (byte) - 1, (byte) - 121, (byte)52, (byte) - 114, (byte)67, (byte)68, (byte) - 60, (byte) - 34, (byte) - 23, (byte) - 53, (byte)84, (byte)123, (byte) - 108, (byte)50, (byte) - 90, (byte) - 62, (byte)35, (byte)61, (byte) - 18, (byte)76, (byte) - 107, (byte)11, (byte)66, (byte) - 6, (byte) - 61, (byte)78, (byte)8, (byte)46, (byte) - 95, (byte)102, (byte)40, (byte) - 39, (byte)36, (byte) - 78, (byte)118, (byte)91, (byte) - 94, (byte)73, (byte)109, (byte) - 117, (byte) - 47, (byte)37, (byte)114, (byte) - 8, (byte) - 10, (byte)100, (byte) - 122, (byte)104, (byte) - 104, (byte)22, (byte) - 44, (byte) - 92, (byte)92, (byte) - 52, (byte)93, (byte)101, (byte) - 74, (byte) - 110, (byte)108, (byte)112, (byte)72, (byte)80, (byte) - 3, (byte) - 19, (byte) - 71, (byte) - 38, (byte)94, (byte)21, (byte)70, (byte)87, (byte) - 89, (byte) - 115, (byte) - 99, (byte) - 124, (byte) - 112, (byte) - 40, (byte) - 85, (byte)0, (byte) - 116, (byte) - 68, (byte) - 45, (byte)10, (byte) - 9, (byte) - 28, (byte)88, (byte)5, (byte) - 72, (byte) - 77, (byte)69, (byte)6, (byte) - 48, (byte)44, (byte)30, (byte) - 113, (byte) - 54, (byte)63, (byte)15, (byte)2, (byte) - 63, (byte) - 81, (byte) - 67, (byte)3, (byte)1, (byte)19, (byte) - 118, (byte)107, (byte)58, (byte) - 111, (byte)17, (byte)65, (byte)79, (byte)103, (byte) - 36, (byte) - 22, (byte) - 105, (byte) - 14, (byte) - 49, (byte) - 50, (byte) - 16, (byte) - 76, (byte) - 26, (byte)115, (byte) - 106, (byte) - 84, (byte)116, (byte)34, (byte) - 25, (byte) - 83, (byte)53, (byte) - 123, (byte) - 30, (byte) - 7, (byte)55, (byte) - 24, (byte)28, (byte)117, (byte) - 33, (byte)110, (byte)71, (byte) - 15, (byte)26, (byte)113, (byte)29, (byte)41, (byte) - 59, (byte) - 119, (byte)111, (byte) - 73, (byte)98, (byte)14, (byte) - 86, (byte)24, (byte) - 66, (byte)27, (byte) - 4, (byte)86, (byte)62, (byte)75, (byte) - 58, (byte) - 46, (byte)121, (byte)32, (byte) - 102, (byte) - 37, (byte) - 64, (byte) - 2, (byte)120, (byte) - 51, (byte)90, (byte) - 12, (byte)31, (byte) - 35, (byte) - 88, (byte)51, (byte) - 120, (byte)7, (byte) - 57, (byte)49, (byte) - 79, (byte)18, (byte)16, (byte)89, (byte)39, (byte) - 128, (byte) - 20, (byte)95, (byte)96, (byte)81, (byte)127, (byte) - 87, (byte)25, (byte) - 75, (byte)74, (byte)13, (byte)45, (byte) - 27, (byte)122, (byte) - 97, (byte) - 109, (byte) - 55, (byte) - 100, (byte) - 17, (byte) - 96, (byte) - 32, (byte)59, (byte)77, (byte) - 82, (byte)42, (byte) - 11, (byte) - 80, (byte) - 56, (byte) - 21, (byte) - 69, (byte)60, (byte) - 125, (byte)83, (byte) - 103, (byte)97, (byte)23, (byte)43, (byte)4, (byte)126, (byte) - 70, (byte)119, (byte) - 42, (byte)38, (byte) - 31, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125};
|
||||||
|
private static final int[] rcon = new int[] {1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145};
|
||||||
|
private static final int[] T0 = new int[] { -1520213050, -2072216328, -1720223762, -1921287178, 234025727, -1117033514, -1318096930, 1422247313, 1345335392, 50397442, -1452841010, 2099981142, 436141799, 1658312629, -424957107, -1703512340, 1170918031, -1652391393, 1086966153, -2021818886, 368769775, -346465870, -918075506, 200339707, -324162239, 1742001331, -39673249, -357585083, -1080255453, -140204973, -1770884380, 1539358875, -1028147339, 486407649, -1366060227, 1780885068, 1513502316, 1094664062, 49805301, 1338821763, 1546925160, -190470831, 887481809, 150073849, -1821281822, 1943591083, 1395732834, 1058346282, 201589768, 1388824469, 1696801606, 1589887901, 672667696, -1583966665, 251987210, -1248159185, 151455502, 907153956, -1686077413, 1038279391, 652995533, 1764173646, -843926913, -1619692054, 453576978, -1635548387, 1949051992, 773462580, 756751158, -1301385508, -296068428, -73359269, -162377052, 1295727478, 1641469623, -827083907, 2066295122, 1055122397, 1898917726, -1752923117, -179088474, 1758581177, 0, 753790401, 1612718144, 536673507, -927878791, -312779850, -1100322092, 1187761037, -641810841, 1262041458, -565556588, -733197160, -396863312, 1255133061, 1808847035, 720367557, -441800113, 385612781, -985447546, -682799718, 1429418854, -1803188975, -817543798, 284817897, 100794884, -2122350594, -263171936, 1144798328, -1163944155, -475486133, -212774494, -22830243, -1069531008, -1970303227, -1382903233, -1130521311, 1211644016, 83228145, -541279133, -1044990345, 1977277103, 1663115586, 806359072, 452984805, 250868733, 1842533055, 1288555905, 336333848, 890442534, 804056259, -513843266, -1567123659, -867941240, 957814574, 1472513171, -223893675, -2105639172, 1195195770, -1402706744, -413311558, 723065138, -1787595802, -1604296512, -1736343271, -783331426, 2145180835, 1713513028, 2116692564, -1416589253, -2088204277, -901364084, 703524551, -742868885, 1007948840, 2044649127, -497131844, 487262998, 1994120109, 1004593371, 1446130276, 1312438900, 503974420, -615954030, 168166924, 1814307912, -463709000, 1573044895, 1859376061, -273896381, -1503501628, -1466855111, -1533700815, 937747667, -1954973198, 854058965, 1137232011, 1496790894, -1217565222, -1936880383, 1691735473, -766620004, -525751991, -1267962664, -95005012, 133494003, 636152527, -1352309302, -1904575756, -374428089, 403179536, -709182865, -2005370640, 1864705354, 1915629148, 605822008, -240736681, -944458637, 1371981463, 602466507, 2094914977, -1670089496, 555687742, -582268010, -591544991, -2037675251, -2054518257, -1871679264, 1111375484, -994724495, -1436129588, -666351472, 84083462, 32962295, 302911004, -1553899070, 1597322602, -111716434, -793134743, -1853454825, 1489093017, 656219450, -1180787161, 954327513, 335083755, -1281845205, 856756514, -1150719534, 1893325225, -1987146233, -1483434957, -1231316179, 572399164, -1836611819, 552200649, 1238290055, -11184726, 2015897680, 2061492133, -1886614525, -123625127, -2138470135, 386731290, -624967835, 837215959, -968736124, -1201116976, -1019133566, -1332111063, 1999449434, 286199582, -877612933, -61582168, -692339859, 974525996};
|
||||||
|
private static final int[] T1 = new int[] {1667483301, 2088564868, 2004348569, 2071721613, -218956019, 1802229437, 1869602481, -976907948, 808476752, 16843267, 1734856361, 724260477, -16849127, -673729182, -1414836762, 1987505306, -892694715, -2105401443, -909539008, 2105408135, -84218091, 1499050731, 1195871945, -252642549, -1381154324, -724257945, -1566416899, -1347467798, -1667488833, -1532734473, 1920132246, -1061119141, -1212713534, -33693412, -1819066962, 640044138, 909536346, 1061125697, -134744830, -859012273, 875849820, -1515892236, -437923532, -235800312, 1903288979, -656888973, 825320019, 353708607, 67373068, -943221422, 589514341, -1010590370, 404238376, -1768540255, 84216335, -1701171275, 117902857, 303178806, -2139087973, -488448195, -336868058, 656887401, -1296924723, 1970662047, 151589403, -2088559202, 741103732, 437924910, 454768173, 1852759218, 1515893998, -1600103429, 1381147894, 993752653, -690571423, -1280082482, 690573947, -471605954, 791633521, -2071719017, 1397991157, -774784664, 0, -303185620, 538984544, -50535649, -1313769016, 1532737261, 1785386174, -875852474, -1094817831, 960066123, 1246401758, 1280088276, 1482207464, -808483510, -791626901, -269499094, -1431679003, -67375850, 1128498885, 1296931543, 859006549, -2054876780, 1162185423, -101062384, 33686534, 2139094657, 1347461360, 1010595908, -1616960070, -1465365533, 1364304627, -1549574658, 1077969088, -1886452342, -1835909203, -1650646596, 943222856, -168431356, -1128504353, -1229555775, -623202443, 555827811, 269492272, -6886, -202113778, -757940371, -842170036, 202119188, 320022069, -320027857, 1600110305, -1751698014, 1145342156, 387395129, -993750185, -1482205710, 2122251394, 1027439175, 1684326572, 1566423783, 421081643, 1936975509, 1616953504, -2122245736, 1330618065, -589520001, 572671078, 707417214, -1869595733, -2004350077, 1179028682, -286341335, -1195873325, 336865340, -555833479, 1583267042, 185275933, -606360202, -522134725, 842163286, 976909390, 168432670, 1229558491, 101059594, 606357612, 1549580516, -1027432611, -741098130, -1397996561, 1650640038, -1852753496, -1785384540, -454765769, 2038035083, -404237006, -926381245, 926379609, 1835915959, -1920138868, -707415708, 1313774802, -1448523296, 1819072692, 1448520954, -185273593, -353710299, 1701169839, 2054878350, -1364310039, 134746136, -1162186795, 2021191816, 623200879, 774790258, 471611428, -1499047951, -1263242297, -960063663, -387396829, -572677764, 1953818780, 522141217, 1263245021, -1111662116, -1953821306, -1970663547, 1886445712, 1044282434, -1246400060, 1718013098, 1212715224, 50529797, -151587071, 235805714, 1633796771, 892693087, 1465364217, -1179031088, -2038032495, -1044276904, 488454695, -1633802311, -505292488, -117904621, -1734857805, 286335539, 1768542907, -640046736, -1903294583, -1802226777, -1684329034, 505297954, -2021190254, -370554592, -825325751, 1431677695, 673730680, -538991238, -1936981105, -1583261192, -1987507840, 218962455, -1077975590, -421079247, 1111655622, 1751699640, 1094812355, -1718015568, 757946999, 252648977, -1330611253, 1414834428, -1145344554, 370551866};
|
||||||
|
private static final int[] T2 = new int[] {1673962851, 2096661628, 2012125559, 2079755643, -218165774, 1809235307, 1876865391, -980331323, 811618352, 16909057, 1741597031, 727088427, -18408962, -675978537, -1420958037, 1995217526, -896580150, -2111857278, -913751863, 2113570685, -84994566, 1504897881, 1200539975, -251982864, -1388188499, -726439980, -1570767454, -1354372433, -1675378788, -1538000988, 1927583346, -1063560256, -1217019209, -35578627, -1824674157, 642542118, 913070646, 1065238847, -134937865, -863809588, 879254580, -1521355611, -439274267, -235337487, 1910674289, -659852328, 828527409, 355090197, 67636228, -946515257, 591815971, -1013096765, 405809176, -1774739050, 84545285, -1708149350, 118360327, 304363026, -2145674368, -488686110, -338876693, 659450151, -1300247118, 1978310517, 152181513, -2095210877, 743994412, 439627290, 456535323, 1859957358, 1521806938, -1604584544, 1386542674, 997608763, -692624938, -1283600717, 693271337, -472039709, 794718511, -2079090812, 1403450707, -776378159, 0, -306107155, 541089824, -52224004, -1317418831, 1538714971, 1792327274, -879933749, -1100490306, 963791673, 1251270218, 1285084236, 1487988824, -813348145, -793023536, -272291089, -1437604438, -68348165, 1132905795, 1301993293, 862344499, -2062445435, 1166724933, -102166279, 33818114, 2147385727, 1352724560, 1014514748, -1624917345, -1471421528, 1369633617, -1554121053, 1082179648, -1895462257, -1841320558, -1658733411, 946882616, -168753931, -1134305348, -1233665610, -626035238, 557998881, 270544912, -1762561, -201519373, -759206446, -847164211, 202904588, 321271059, -322752532, 1606345055, -1758092649, 1149815876, 388905239, -996976700, -1487539545, 2130477694, 1031423805, 1690872932, 1572530013, 422718233, 1944491379, 1623236704, -2129028991, 1335808335, -593264676, 574907938, 710180394, -1875137648, -2012511352, 1183631942, -288937490, -1200893000, 338181140, -559449634, 1589437022, 185998603, -609388837, -522503200, 845436466, 980700730, 169090570, 1234361161, 101452294, 608726052, 1555620956, -1029743166, -742560045, -1404833876, 1657054818, -1858492271, -1791908715, -455919644, 2045938553, -405458201, -930397240, 929978679, 1843050349, -1929278323, -709794603, 1318900302, -1454776151, 1826141292, 1454176854, -185399308, -355523094, 1707781989, 2062847610, -1371018834, 135272456, -1167075910, 2029029496, 625635109, 777810478, 473441308, -1504185946, -1267480652, -963161658, -389340184, -576619299, 1961401460, 524165407, 1268178251, -1117659971, -1962047861, -1978694262, 1893765232, 1048330814, -1250835275, 1724688998, 1217452104, 50726147, -151584266, 236720654, 1640145761, 896163637, 1471084887, -1184247623, -2045275770, -1046914879, 490350365, -1641563746, -505857823, -118811656, -1741966440, 287453969, 1775418217, -643206951, -1912108658, -1808554092, -1691502949, 507257374, -2028629369, -372694807, -829994546, 1437269845, 676362280, -542803233, -1945923700, -1587939167, -1995865975, 219813645, -1083843905, -422104602, 1115997762, 1758509160, 1099088705, -1725321063, 760903469, 253628687, -1334064208, 1420360788, -1150429509, 371997206};
|
||||||
|
private static final int[] T3 = new int[] { -962239645, -125535108, -291932297, -158499973, -15863054, -692229269, -558796945, -1856715323, 1615867952, 33751297, -827758745, 1451043627, -417726722, -1251813417, 1306962859, -325421450, -1891251510, 530416258, -1992242743, -91783811, -283772166, -1293199015, -1899411641, -83103504, 1106029997, -1285040940, 1610457762, 1173008303, 599760028, 1408738468, -459902350, -1688485696, 1975695287, -518193667, 1034851219, 1282024998, 1817851446, 2118205247, -184354825, -2091922228, 1750873140, 1374987685, -785062427, -116854287, -493653647, -1418471208, 1649619249, 708777237, 135005188, -1789737017, 1181033251, -1654733885, 807933976, 933336726, 168756485, 800430746, 235472647, 607523346, 463175808, -549592350, -853087253, 1315514151, 2144187058, -358648459, 303761673, 496927619, 1484008492, 875436570, 908925723, -592286098, -1259447718, 1543217312, -1527360942, 1984772923, -1218324778, 2110698419, 1383803177, -583080989, 1584475951, 328696964, -1493871789, -1184312879, 0, -1054020115, 1080041504, -484442884, 2043195825, -1225958565, -725718422, -1924740149, 1742323390, 1917532473, -1797371318, -1730917300, -1326950312, -2058694705, -1150562096, -987041809, 1340451498, -317260805, -2033892541, -1697166003, 1716859699, 294946181, -1966127803, -384763399, 67502594, -25067649, -1594863536, 2017737788, 632987551, 1273211048, -1561112239, 1576969123, -2134884288, 92966799, 1068339858, 566009245, 1883781176, -251333131, 1675607228, 2009183926, -1351230758, 1113792801, 540020752, -451215361, -49351693, -1083321646, -2125673011, 403966988, 641012499, -1020269332, -1092526241, 899848087, -1999879100, 775493399, -1822964540, 1441965991, -58556802, 2051489085, -928226204, -1159242403, 841685273, -426413197, -1063231392, 429425025, -1630449841, -1551901476, 1147544098, 1417554474, 1001099408, 193169544, -1932900794, -953553170, 1809037496, 675025940, -1485185314, -1126015394, 371002123, -1384719397, -616832800, 1683370546, 1951283770, 337512970, -1831122615, 201983494, 1215046692, -1192993700, -1621245246, -1116810285, 1139780780, -995728798, 967348625, 832869781, -751311644, -225740423, -718084121, -1958491960, 1851340599, -625513107, 25988493, -1318791723, -1663938994, 1239460265, -659264404, -1392880042, -217582348, -819598614, -894474907, -191989126, 1206496942, 270010376, 1876277946, -259491720, 1248797989, 1550986798, 941890588, 1475454630, 1942467764, -1756248378, -886839064, -1585652259, -392399756, 1042358047, -1763882165, 1641856445, 226921355, 260409994, -527404944, 2084716094, 1908716981, -861247898, -1864873912, 100991747, -150866186, 470945294, -1029480095, 1784624437, -1359390889, 1775286713, 395413126, -1722236479, 975641885, 666476190, -650583583, -351012616, 733190296, 573772049, -759469719, -1452221991, 126455438, 866620564, 766942107, 1008868894, 361924487, -920589847, -2025206066, -1426107051, 1350051880, -1518673953, 59739276, 1509466529, 159418761, 437718285, 1708834751, -684595482, -2067381694, -793221016, -2101132991, 699439513, 1517759789, 504434447, 2076946608, -1459858348, 1842789307, 742004246};
|
||||||
|
private static final int[] Tinv0 = new int[] {1353184337, 1399144830, -1012656358, -1772214470, -882136261, -247096033, -1420232020, -1828461749, 1442459680, -160598355, -1854485368, 625738485, -52959921, -674551099, -2143013594, -1885117771, 1230680542, 1729870373, -1743852987, -507445667, 41234371, 317738113, -1550367091, -956705941, -413167869, -1784901099, -344298049, -631680363, 763608788, -752782248, 694804553, 1154009486, 1787413109, 2021232372, 1799248025, -579749593, -1236278850, 397248752, 1722556617, -1271214467, 407560035, -2110711067, 1613975959, 1165972322, -529046351, -2068943941, 480281086, -1809118983, 1483229296, 436028815, -2022908268, -1208452270, 601060267, -503166094, 1468997603, 715871590, 120122290, 63092015, -1703164538, -1526188077, -226023376, -1297760477, -1167457534, 1552029421, 723308426, -1833666137, -252573709, -1578997426, -839591323, -708967162, 526529745, -1963022652, -1655493068, -1604979806, 853641733, 1978398372, 971801355, -1427152832, 111112542, 1360031421, -108388034, 1023860118, -1375387939, 1186850381, -1249028975, 90031217, 1876166148, -15380384, 620468249, -1746289194, -868007799, 2006899047, -1119688528, -2004121337, 945494503, -605108103, 1191869601, -384875908, -920746760, 0, -2088337399, 1223502642, -1401941730, 1316117100, -67170563, 1446544655, 517320253, 658058550, 1691946762, 564550760, -783000677, 976107044, -1318647284, 266819475, -761860428, -1634624741, 1338359936, -1574904735, 1766553434, 370807324, 179999714, -450191168, 1138762300, 488053522, 185403662, -1379431438, -1180125651, -928440812, -2061897385, 1275557295, -1143105042, -44007517, -1624899081, -1124765092, -985962940, 880737115, 1982415755, -590994485, 1761406390, 1676797112, -891538985, 277177154, 1076008723, 538035844, 2099530373, -130171950, 288553390, 1839278535, 1261411869, -214912292, -330136051, -790380169, 1813426987, -1715900247, -95906799, 577038663, -997393240, 440397984, -668172970, -275762398, -951170681, -1043253031, -22885748, 906744984, -813566554, 685669029, 646887386, -1530942145, -459458004, 227702864, -1681105046, 1648787028, -1038905866, -390539120, 1593260334, -173030526, -1098883681, 2090061929, -1456614033, -1290656305, 999926984, -1484974064, 1852021992, 2075868123, 158869197, -199730834, 28809964, -1466282109, 1701746150, 2129067946, 147831841, -420997649, -644094022, -835293366, -737566742, -696471511, -1347247055, 824393514, 815048134, -1067015627, 935087732, -1496677636, -1328508704, 366520115, 1251476721, -136647615, 240176511, 804688151, -1915335306, 1303441219, 1414376140, -553347356, -474623586, 461924940, -1205916479, 2136040774, 82468509, 1563790337, 1937016826, 776014843, 1511876531, 1389550482, 861278441, 323475053, -1939744870, 2047648055, -1911228327, -1992551445, -299390514, 902390199, -303751967, 1018251130, 1507840668, 1064563285, 2043548696, -1086863501, -355600557, 1537932639, 342834655, -2032450440, -2114736182, 1053059257, 741614648, 1598071746, 1925389590, 203809468, -1958134744, 1100287487, 1895934009, -558691320, -1662733096, -1866377628, 1636092795, 1890988757, 1952214088, 1113045200};
|
||||||
|
private static final int[] Tinv1 = new int[] { -1477160624, 1698790995, -1541989693, 1579629206, 1806384075, 1167925233, 1492823211, 65227667, -97509291, 1836494326, 1993115793, 1275262245, -672837636, -886389289, 1144333952, -1553812081, 1521606217, 465184103, 250234264, -1057071647, 1966064386, -263421678, -1756983901, -103584826, 1603208167, -1668147819, 2054012907, 1498584538, -2084645843, 561273043, 1776306473, -926314940, -1983744662, 2039411832, 1045993835, 1907959773, 1340194486, -1383534569, -1407137434, 986611124, 1256153880, 823846274, 860985184, 2136171077, 2003087840, -1368671356, -1602093540, 722008468, 1749577816, -45773031, 1826526343, -126135625, -747394269, 38499042, -1893735593, -1420466646, 686535175, -1028313341, 2076542618, 137876389, -2027409166, -1514200142, 1778582202, -2112426660, 483363371, -1267095662, -234359824, -496415071, -187013683, -1106966827, 1647628575, -22625142, 1395537053, 1442030240, -511048398, -336157579, -326956231, -278904662, -1619960314, 275692881, -1977532679, 115185213, 88006062, -1108980410, -1923837515, 1573155077, -737803153, 357589247, -73918172, -373434729, 1128303052, -1629919369, 1122545853, -1953953912, 1528424248, -288851493, 175939911, 256015593, 512030921, 0, -2038429309, -315936184, 1880170156, 1918528590, -15794693, 948244310, -710001378, 959264295, -653325724, -1503893471, 1415289809, 775300154, 1728711857, -413691121, -1762741038, -1852105826, -977239985, 551313826, 1266113129, 437394454, -1164713462, 715178213, -534627261, 387650077, 218697227, -947129683, -1464455751, -1457646392, 435246981, 125153100, -577114437, 1618977789, 637663135, -177054532, 996558021, 2130402100, 692292470, -970732580, -51530136, -236668829, -600713270, -2057092592, 580326208, 298222624, 608863613, 1035719416, 855223825, -1591097491, 798891339, 817028339, 1384517100, -473860144, 380840812, -1183798887, 1217663482, 1693009698, -1929598780, 1072734234, 746411736, -1875696913, 1313441735, -784803391, -1563783938, 198481974, -2114607409, -562387672, -1900553690, -1079165020, -1657131804, -1837608947, -866162021, 1182684258, 328070850, -1193766680, -147247522, -1346141451, -2141347906, -1815058052, 768962473, 304467891, -1716729797, 2098729127, 1671227502, -1153705093, 2015808777, 408514292, -1214583807, -1706064984, 1855317605, -419452290, -809754360, -401215514, -1679312167, 913263310, 161475284, 2091919830, -1297862225, 591342129, -1801075152, 1721906624, -1135709129, -897385306, -795811664, -660131051, -1744506550, -622050825, 1355644686, -158263505, -699566451, -1326496947, 1303039060, 76997855, -1244553501, -2006299621, 523026872, 1365591679, -362898172, 898367837, 1955068531, 1091304238, 493335386, -757362094, 1443948851, 1205234963, 1641519756, 211892090, 351820174, 1007938441, 665439982, -916342987, -451091987, -1320715716, -539845543, 1945261375, -837543815, 935818175, -839429142, -1426235557, 1866325780, -616269690, -206583167, -999769794, 874788908, 1084473951, -1021503886, 635616268, 1228679307, -1794244799, 27801969, -1291056930, -457910116, -1051302768, -2067039391, -1238182544, 1550600308, 1471729730};
|
||||||
|
private static final int[] Tinv2 = new int[] { -195997529, 1098797925, 387629988, 658151006, -1422144661, -1658851003, -89347240, -481586429, 807425530, 1991112301, -863465098, 49620300, -447742761, 717608907, 891715652, 1656065955, -1310832294, -1171953893, -364537842, -27401792, 801309301, 1283527408, 1183687575, -747911431, -1895569569, -1844079204, 1841294202, 1385552473, -1093390973, 1951978273, -532076183, -913423160, -1032492407, -1896580999, 1486449470, -1188569743, -507595185, -1997531219, 550069932, -830622662, -547153846, 451248689, 1368875059, 1398949247, 1689378935, 1807451310, -2114052960, 150574123, 1215322216, 1167006205, -560691348, 2069018616, 1940595667, 1265820162, 534992783, 1432758955, -340654296, -1255210046, -981034373, 936617224, 674296455, -1088179547, 50510442, 384654466, -813028580, 2041025204, 133427442, 1766760930, -630862348, 84334014, 886120290, -1497068802, 775200083, -207445931, -1979370783, -156994069, -2096416276, 1614850799, 1901987487, 1857900816, 557775242, -577356538, 1054715397, -431143235, 1418835341, -999226019, 100954068, 1348534037, -1743182597, -1110009879, 1082772547, -647530594, -391070398, -1995994997, 434583643, -931537938, 2090944266, 1115482383, -2064070370, 0, -2146860154, 724715757, 287222896, 1517047410, 251526143, -2062592456, -1371726123, 758523705, 252339417, 1550328230, 1536938324, 908343854, 168604007, 1469255655, -290139498, -1692688751, -1065332795, -597581280, 2002413899, 303830554, -1813902662, -1597971158, 574374880, 454171927, 151915277, -1947030073, -1238517336, 504678569, -245922535, 1974422535, -1712407587, 2141453664, 33005350, 1918680309, 1715782971, -77908866, 1133213225, 600562886, -306812676, -457677839, 836225756, 1665273989, -1760346078, -964419567, 1250262308, -1143801795, -106032846, 700935585, -1642247377, -1294142672, -2045907886, -1049112349, -1288999914, 1890163129, -1810761144, -381214108, -56048500, -257942977, 2102843436, 857927568, 1233635150, 953795025, -896729438, -728222197, -173617279, 2057644254, -1210440050, -1388337985, 976020637, 2018512274, 1600822220, 2119459398, -1913208301, -661591880, 959340279, -1014827601, 1570750080, -798393197, -714102483, 634368786, -1396163687, 403744637, -1662488989, 1004239803, 650971512, 1500443672, -1695809097, 1334028442, -1780062866, -5603610, -1138685745, 368043752, -407184997, 1867173430, -1612000247, -1339435396, -1540247630, 1059729699, -1513738092, -1573535642, 1316239292, -2097371446, -1864322864, -1489824296, 82922136, -331221030, -847311280, -1860751370, 1299615190, -280801872, -1429449651, -1763385596, -778116171, 1783372680, 750893087, 1699118929, 1587348714, -1946067659, -2013629580, 201010753, 1739807261, -611167534, 283718486, -697494713, -677737375, -1590199796, -128348652, 334203196, -1446056409, 1639396809, 484568549, 1199193265, -761505313, -229294221, 337148366, -948715721, -145495347, -44082262, 1038029935, 1148749531, -1345682957, 1756970692, 607661108, -1547542720, 488010435, -490992603, 1009290057, 234832277, -1472630527, 201907891, -1260872476, 1449431233, -881106556, 852848822, 1816687708, -1194311081};
|
||||||
|
private static final int[] Tinv3 = new int[] {1364240372, 2119394625, 449029143, 982933031, 1003187115, 535905693, -1398056710, 1267925987, 542505520, -1376359050, -2003732788, -182105086, 1341970405, -975713494, 645940277, -1248877726, -565617999, 627514298, 1167593194, 1575076094, -1023249105, -2129465268, -1918658746, 1808202195, 65494927, 362126482, -1075086739, -1780852398, -735214658, 1490231668, 1227450848, -1908094775, 1969916354, -193431154, -1721024936, 668823993, -1095348255, -266883704, -916018144, 2108963534, 1662536415, -444452582, -1755303087, 1648721747, -1310689436, -1148932501, -31678335, -107730168, 1884842056, -1894122171, -1803064098, 1387788411, -1423715469, 1927414347, -480800993, 1714072405, -1308153621, 788775605, -2036696123, -744159177, 821200680, 598910399, 45771267, -312704490, -1976886065, -1483557767, -202313209, 1319232105, 1707996378, 114671109, -786472396, -997523802, 882725678, -1566550541, 87220618, -1535775754, 188345475, 1084944224, 1577492337, -1118760850, 1056541217, -1774385443, -575797954, 1296481766, -1850372780, 1896177092, 74437638, 1627329872, 421854104, -694687299, -1983102144, 1735892697, -1329773848, 126389129, -415737063, 2044456648, -1589179780, 2095648578, -121037180, 0, 159614592, 843640107, 514617361, 1817080410, -33816818, 257308805, 1025430958, 908540205, 174381327, 1747035740, -1680780197, 607792694, 212952842, -1827674281, -1261267218, 463376795, -2142255680, 1638015196, 1516850039, 471210514, -502613357, -1058723168, 1011081250, 303896347, 235605257, -223492213, 767142070, 348694814, 1468340721, -1353971851, -289677927, -1543675777, -140564991, 1555887474, 1153776486, 1530167035, -1955190461, -874723805, -1234633491, -1201409564, -674571215, 1108378979, 322970263, -2078273082, -2055396278, -755483205, -1374604551, -949116631, 491466654, -588042062, 233591430, 2010178497, 728503987, -1449543312, 301615252, 1193436393, -1463513860, -1608892432, 1457007741, 586125363, -2016981431, -641609416, -1929469238, -1741288492, -1496350219, -1524048262, -635007305, 1067761581, 753179962, 1343066744, 1788595295, 1415726718, -155053171, -1863796520, 777975609, -2097827901, -1614905251, 1769771984, 1873358293, -810347995, -935618132, 279411992, -395418724, -612648133, -855017434, 1861490777, -335431782, -2086102449, -429560171, -1434523905, 554225596, -270079979, -1160143897, 1255028335, -355202657, 701922480, 833598116, 707863359, -969894747, 901801634, 1949809742, -56178046, -525283184, 857069735, -246769660, 1106762476, 2131644621, 389019281, 1989006925, 1129165039, -866890326, -455146346, -1629243951, 1276872810, -1044898004, 1182749029, -1660622242, 22885772, -93096825, -80854773, -1285939865, -1840065829, -382511600, 1829980118, -1702075945, 930745505, 1502483704, -343327725, -823253079, -1221211807, -504503012, 2050797895, -1671831598, 1430221810, 410635796, 1941911495, 1407897079, 1599843069, -552308931, 2022103876, -897453137, -1187068824, 942421028, -1033944925, 376619805, -1140054558, 680216892, -12479219, 963707304, 148812556, -660806476, 1687208278, 2069988555, -714033614, 1215585388, -800958536};
|
||||||
|
private int ROUNDS;
|
||||||
|
private int[][] WorkingKey = (int[][])null;
|
||||||
|
private int C0;
|
||||||
|
private int C1;
|
||||||
|
private int C2;
|
||||||
|
private int C3;
|
||||||
|
private boolean forEncryption;
|
||||||
|
|
||||||
|
private int shift(int par1, int par2)
|
||||||
|
{
|
||||||
|
return par1 >>> par2 | par1 << -par2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int FFmulX(int par1)
|
||||||
|
{
|
||||||
|
return (par1 & 2139062143) << 1 ^ ((par1 & -2139062144) >>> 7) * 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int inv_mcol(int par1)
|
||||||
|
{
|
||||||
|
int var2 = this.FFmulX(par1);
|
||||||
|
int var3 = this.FFmulX(var2);
|
||||||
|
int var4 = this.FFmulX(var3);
|
||||||
|
int var5 = par1 ^ var4;
|
||||||
|
return var2 ^ var3 ^ var4 ^ this.shift(var2 ^ var5, 8) ^ this.shift(var3 ^ var5, 16) ^ this.shift(var5, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int subWord(int par1)
|
||||||
|
{
|
||||||
|
return S[par1 & 255] & 255 | (S[par1 >> 8 & 255] & 255) << 8 | (S[par1 >> 16 & 255] & 255) << 16 | S[par1 >> 24 & 255] << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[][] generateWorkingKey(byte[] par1ArrayOfByte, boolean par2)
|
||||||
|
{
|
||||||
|
int var3 = par1ArrayOfByte.length / 4;
|
||||||
|
|
||||||
|
if ((var3 == 4 || var3 == 6 || var3 == 8) && var3 * 4 == par1ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
this.ROUNDS = var3 + 6;
|
||||||
|
int[][] var5 = new int[this.ROUNDS + 1][4];
|
||||||
|
int var4 = 0;
|
||||||
|
int var6;
|
||||||
|
|
||||||
|
for (var6 = 0; var6 < par1ArrayOfByte.length; ++var4)
|
||||||
|
{
|
||||||
|
var5[var4 >> 2][var4 & 3] = par1ArrayOfByte[var6] & 255 | (par1ArrayOfByte[var6 + 1] & 255) << 8 | (par1ArrayOfByte[var6 + 2] & 255) << 16 | par1ArrayOfByte[var6 + 3] << 24;
|
||||||
|
var6 += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int var7 = this.ROUNDS + 1 << 2;
|
||||||
|
int var8;
|
||||||
|
|
||||||
|
for (var6 = var3; var6 < var7; ++var6)
|
||||||
|
{
|
||||||
|
var8 = var5[var6 - 1 >> 2][var6 - 1 & 3];
|
||||||
|
|
||||||
|
if (var6 % var3 == 0)
|
||||||
|
{
|
||||||
|
var8 = this.subWord(this.shift(var8, 8)) ^ rcon[var6 / var3 - 1];
|
||||||
|
}
|
||||||
|
else if (var3 > 6 && var6 % var3 == 4)
|
||||||
|
{
|
||||||
|
var8 = this.subWord(var8);
|
||||||
|
}
|
||||||
|
|
||||||
|
var5[var6 >> 2][var6 & 3] = var5[var6 - var3 >> 2][var6 - var3 & 3] ^ var8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!par2)
|
||||||
|
{
|
||||||
|
for (var8 = 1; var8 < this.ROUNDS; ++var8)
|
||||||
|
{
|
||||||
|
for (var6 = 0; var6 < 4; ++var6)
|
||||||
|
{
|
||||||
|
var5[var8][var6] = this.inv_mcol(var5[var8][var6]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return var5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Key length not 128/192/256 bits.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(boolean par1, CipherParameters par2CipherParameters) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
if (par2CipherParameters instanceof KeyParameter)
|
||||||
|
{
|
||||||
|
this.WorkingKey = this.generateWorkingKey(((KeyParameter)par2CipherParameters).getKey(), par1);
|
||||||
|
this.forEncryption = par1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("invalid parameter passed to AES init - " + par2CipherParameters.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of the algorithm the cipher implements.
|
||||||
|
*/
|
||||||
|
public String getAlgorithmName()
|
||||||
|
{
|
||||||
|
return "AES";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the block size for this cipher (in bytes).
|
||||||
|
*/
|
||||||
|
public int getBlockSize()
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int processBlock(byte[] par1ArrayOfByte, int par2, byte[] par3ArrayOfByte, int par4) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
if (this.WorkingKey == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("AES engine not initialised");
|
||||||
|
}
|
||||||
|
else if (par2 + 16 > par1ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("input buffer too short");
|
||||||
|
}
|
||||||
|
else if (par4 + 16 > par3ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("output buffer too short");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this.forEncryption)
|
||||||
|
{
|
||||||
|
this.unpackBlock(par1ArrayOfByte, par2);
|
||||||
|
this.encryptBlock(this.WorkingKey);
|
||||||
|
this.packBlock(par3ArrayOfByte, par4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.unpackBlock(par1ArrayOfByte, par2);
|
||||||
|
this.decryptBlock(this.WorkingKey);
|
||||||
|
this.packBlock(par3ArrayOfByte, par4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {}
|
||||||
|
|
||||||
|
private void unpackBlock(byte[] par1ArrayOfByte, int par2)
|
||||||
|
{
|
||||||
|
int var3 = par2 + 1;
|
||||||
|
this.C0 = par1ArrayOfByte[par2] & 255;
|
||||||
|
this.C0 |= (par1ArrayOfByte[var3++] & 255) << 8;
|
||||||
|
this.C0 |= (par1ArrayOfByte[var3++] & 255) << 16;
|
||||||
|
this.C0 |= par1ArrayOfByte[var3++] << 24;
|
||||||
|
this.C1 = par1ArrayOfByte[var3++] & 255;
|
||||||
|
this.C1 |= (par1ArrayOfByte[var3++] & 255) << 8;
|
||||||
|
this.C1 |= (par1ArrayOfByte[var3++] & 255) << 16;
|
||||||
|
this.C1 |= par1ArrayOfByte[var3++] << 24;
|
||||||
|
this.C2 = par1ArrayOfByte[var3++] & 255;
|
||||||
|
this.C2 |= (par1ArrayOfByte[var3++] & 255) << 8;
|
||||||
|
this.C2 |= (par1ArrayOfByte[var3++] & 255) << 16;
|
||||||
|
this.C2 |= par1ArrayOfByte[var3++] << 24;
|
||||||
|
this.C3 = par1ArrayOfByte[var3++] & 255;
|
||||||
|
this.C3 |= (par1ArrayOfByte[var3++] & 255) << 8;
|
||||||
|
this.C3 |= (par1ArrayOfByte[var3++] & 255) << 16;
|
||||||
|
this.C3 |= par1ArrayOfByte[var3++] << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void packBlock(byte[] par1ArrayOfByte, int par2)
|
||||||
|
{
|
||||||
|
int var3 = par2 + 1;
|
||||||
|
par1ArrayOfByte[par2] = (byte)this.C0;
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C0 >> 8);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C0 >> 16);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C0 >> 24);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)this.C1;
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C1 >> 8);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C1 >> 16);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C1 >> 24);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)this.C2;
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C2 >> 8);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C2 >> 16);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C2 >> 24);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)this.C3;
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C3 >> 8);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C3 >> 16);
|
||||||
|
par1ArrayOfByte[var3++] = (byte)(this.C3 >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void encryptBlock(int[][] par1ArrayOfInteger)
|
||||||
|
{
|
||||||
|
this.C0 ^= par1ArrayOfInteger[0][0];
|
||||||
|
this.C1 ^= par1ArrayOfInteger[0][1];
|
||||||
|
this.C2 ^= par1ArrayOfInteger[0][2];
|
||||||
|
this.C3 ^= par1ArrayOfInteger[0][3];
|
||||||
|
int var2;
|
||||||
|
int var3;
|
||||||
|
int var4;
|
||||||
|
int var5;
|
||||||
|
int var6;
|
||||||
|
|
||||||
|
for (var2 = 1; var2 < this.ROUNDS - 1; this.C3 = T0[var6 & 255] ^ T1[var3 >> 8 & 255] ^ T2[var4 >> 16 & 255] ^ T3[var5 >> 24 & 255] ^ par1ArrayOfInteger[var2++][3])
|
||||||
|
{
|
||||||
|
var3 = T0[this.C0 & 255] ^ T1[this.C1 >> 8 & 255] ^ T2[this.C2 >> 16 & 255] ^ T3[this.C3 >> 24 & 255] ^ par1ArrayOfInteger[var2][0];
|
||||||
|
var4 = T0[this.C1 & 255] ^ T1[this.C2 >> 8 & 255] ^ T2[this.C3 >> 16 & 255] ^ T3[this.C0 >> 24 & 255] ^ par1ArrayOfInteger[var2][1];
|
||||||
|
var5 = T0[this.C2 & 255] ^ T1[this.C3 >> 8 & 255] ^ T2[this.C0 >> 16 & 255] ^ T3[this.C1 >> 24 & 255] ^ par1ArrayOfInteger[var2][2];
|
||||||
|
var6 = T0[this.C3 & 255] ^ T1[this.C0 >> 8 & 255] ^ T2[this.C1 >> 16 & 255] ^ T3[this.C2 >> 24 & 255] ^ par1ArrayOfInteger[var2++][3];
|
||||||
|
this.C0 = T0[var3 & 255] ^ T1[var4 >> 8 & 255] ^ T2[var5 >> 16 & 255] ^ T3[var6 >> 24 & 255] ^ par1ArrayOfInteger[var2][0];
|
||||||
|
this.C1 = T0[var4 & 255] ^ T1[var5 >> 8 & 255] ^ T2[var6 >> 16 & 255] ^ T3[var3 >> 24 & 255] ^ par1ArrayOfInteger[var2][1];
|
||||||
|
this.C2 = T0[var5 & 255] ^ T1[var6 >> 8 & 255] ^ T2[var3 >> 16 & 255] ^ T3[var4 >> 24 & 255] ^ par1ArrayOfInteger[var2][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
var3 = T0[this.C0 & 255] ^ T1[this.C1 >> 8 & 255] ^ T2[this.C2 >> 16 & 255] ^ T3[this.C3 >> 24 & 255] ^ par1ArrayOfInteger[var2][0];
|
||||||
|
var4 = T0[this.C1 & 255] ^ T1[this.C2 >> 8 & 255] ^ T2[this.C3 >> 16 & 255] ^ T3[this.C0 >> 24 & 255] ^ par1ArrayOfInteger[var2][1];
|
||||||
|
var5 = T0[this.C2 & 255] ^ T1[this.C3 >> 8 & 255] ^ T2[this.C0 >> 16 & 255] ^ T3[this.C1 >> 24 & 255] ^ par1ArrayOfInteger[var2][2];
|
||||||
|
var6 = T0[this.C3 & 255] ^ T1[this.C0 >> 8 & 255] ^ T2[this.C1 >> 16 & 255] ^ T3[this.C2 >> 24 & 255] ^ par1ArrayOfInteger[var2++][3];
|
||||||
|
this.C0 = S[var3 & 255] & 255 ^ (S[var4 >> 8 & 255] & 255) << 8 ^ (S[var5 >> 16 & 255] & 255) << 16 ^ S[var6 >> 24 & 255] << 24 ^ par1ArrayOfInteger[var2][0];
|
||||||
|
this.C1 = S[var4 & 255] & 255 ^ (S[var5 >> 8 & 255] & 255) << 8 ^ (S[var6 >> 16 & 255] & 255) << 16 ^ S[var3 >> 24 & 255] << 24 ^ par1ArrayOfInteger[var2][1];
|
||||||
|
this.C2 = S[var5 & 255] & 255 ^ (S[var6 >> 8 & 255] & 255) << 8 ^ (S[var3 >> 16 & 255] & 255) << 16 ^ S[var4 >> 24 & 255] << 24 ^ par1ArrayOfInteger[var2][2];
|
||||||
|
this.C3 = S[var6 & 255] & 255 ^ (S[var3 >> 8 & 255] & 255) << 8 ^ (S[var4 >> 16 & 255] & 255) << 16 ^ S[var5 >> 24 & 255] << 24 ^ par1ArrayOfInteger[var2][3];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decryptBlock(int[][] par1ArrayOfInteger)
|
||||||
|
{
|
||||||
|
this.C0 ^= par1ArrayOfInteger[this.ROUNDS][0];
|
||||||
|
this.C1 ^= par1ArrayOfInteger[this.ROUNDS][1];
|
||||||
|
this.C2 ^= par1ArrayOfInteger[this.ROUNDS][2];
|
||||||
|
this.C3 ^= par1ArrayOfInteger[this.ROUNDS][3];
|
||||||
|
int var2;
|
||||||
|
int var3;
|
||||||
|
int var4;
|
||||||
|
int var5;
|
||||||
|
int var6;
|
||||||
|
|
||||||
|
for (var6 = this.ROUNDS - 1; var6 > 1; this.C3 = Tinv0[var5 & 255] ^ Tinv1[var4 >> 8 & 255] ^ Tinv2[var3 >> 16 & 255] ^ Tinv3[var2 >> 24 & 255] ^ par1ArrayOfInteger[var6--][3])
|
||||||
|
{
|
||||||
|
var2 = Tinv0[this.C0 & 255] ^ Tinv1[this.C3 >> 8 & 255] ^ Tinv2[this.C2 >> 16 & 255] ^ Tinv3[this.C1 >> 24 & 255] ^ par1ArrayOfInteger[var6][0];
|
||||||
|
var3 = Tinv0[this.C1 & 255] ^ Tinv1[this.C0 >> 8 & 255] ^ Tinv2[this.C3 >> 16 & 255] ^ Tinv3[this.C2 >> 24 & 255] ^ par1ArrayOfInteger[var6][1];
|
||||||
|
var4 = Tinv0[this.C2 & 255] ^ Tinv1[this.C1 >> 8 & 255] ^ Tinv2[this.C0 >> 16 & 255] ^ Tinv3[this.C3 >> 24 & 255] ^ par1ArrayOfInteger[var6][2];
|
||||||
|
var5 = Tinv0[this.C3 & 255] ^ Tinv1[this.C2 >> 8 & 255] ^ Tinv2[this.C1 >> 16 & 255] ^ Tinv3[this.C0 >> 24 & 255] ^ par1ArrayOfInteger[var6--][3];
|
||||||
|
this.C0 = Tinv0[var2 & 255] ^ Tinv1[var5 >> 8 & 255] ^ Tinv2[var4 >> 16 & 255] ^ Tinv3[var3 >> 24 & 255] ^ par1ArrayOfInteger[var6][0];
|
||||||
|
this.C1 = Tinv0[var3 & 255] ^ Tinv1[var2 >> 8 & 255] ^ Tinv2[var5 >> 16 & 255] ^ Tinv3[var4 >> 24 & 255] ^ par1ArrayOfInteger[var6][1];
|
||||||
|
this.C2 = Tinv0[var4 & 255] ^ Tinv1[var3 >> 8 & 255] ^ Tinv2[var2 >> 16 & 255] ^ Tinv3[var5 >> 24 & 255] ^ par1ArrayOfInteger[var6][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
var2 = Tinv0[this.C0 & 255] ^ Tinv1[this.C3 >> 8 & 255] ^ Tinv2[this.C2 >> 16 & 255] ^ Tinv3[this.C1 >> 24 & 255] ^ par1ArrayOfInteger[var6][0];
|
||||||
|
var3 = Tinv0[this.C1 & 255] ^ Tinv1[this.C0 >> 8 & 255] ^ Tinv2[this.C3 >> 16 & 255] ^ Tinv3[this.C2 >> 24 & 255] ^ par1ArrayOfInteger[var6][1];
|
||||||
|
var4 = Tinv0[this.C2 & 255] ^ Tinv1[this.C1 >> 8 & 255] ^ Tinv2[this.C0 >> 16 & 255] ^ Tinv3[this.C3 >> 24 & 255] ^ par1ArrayOfInteger[var6][2];
|
||||||
|
var5 = Tinv0[this.C3 & 255] ^ Tinv1[this.C2 >> 8 & 255] ^ Tinv2[this.C1 >> 16 & 255] ^ Tinv3[this.C0 >> 24 & 255] ^ par1ArrayOfInteger[var6][3];
|
||||||
|
this.C0 = Si[var2 & 255] & 255 ^ (Si[var5 >> 8 & 255] & 255) << 8 ^ (Si[var4 >> 16 & 255] & 255) << 16 ^ Si[var3 >> 24 & 255] << 24 ^ par1ArrayOfInteger[0][0];
|
||||||
|
this.C1 = Si[var3 & 255] & 255 ^ (Si[var2 >> 8 & 255] & 255) << 8 ^ (Si[var5 >> 16 & 255] & 255) << 16 ^ Si[var4 >> 24 & 255] << 24 ^ par1ArrayOfInteger[0][1];
|
||||||
|
this.C2 = Si[var4 & 255] & 255 ^ (Si[var3 >> 8 & 255] & 255) << 8 ^ (Si[var2 >> 16 & 255] & 255) << 16 ^ Si[var5 >> 24 & 255] << 24 ^ par1ArrayOfInteger[0][2];
|
||||||
|
this.C3 = Si[var5 & 255] & 255 ^ (Si[var4 >> 8 & 255] & 255) << 8 ^ (Si[var3 >> 16 & 255] & 255) << 16 ^ Si[var2 >> 24 & 255] << 24 ^ par1ArrayOfInteger[0][3];
|
||||||
|
}
|
||||||
|
}
|
178
src/teavm/java/org/bouncycastle/crypto/io/CipherInputStream.java
Normal file
178
src/teavm/java/org/bouncycastle/crypto/io/CipherInputStream.java
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
package org.bouncycastle.crypto.io;
|
||||||
|
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||||
|
import org.bouncycastle.crypto.StreamCipher;
|
||||||
|
|
||||||
|
public class CipherInputStream extends FilterInputStream
|
||||||
|
{
|
||||||
|
private BufferedBlockCipher theBufferedBlockCipher;
|
||||||
|
private StreamCipher theStreamCipher;
|
||||||
|
private byte[] buf;
|
||||||
|
private byte[] inBuf;
|
||||||
|
private int bufOff;
|
||||||
|
private int maxBuf;
|
||||||
|
private boolean finalized;
|
||||||
|
|
||||||
|
public CipherInputStream(InputStream par1InputStream, BufferedBlockCipher par2BufferedBlockCipher)
|
||||||
|
{
|
||||||
|
super(par1InputStream);
|
||||||
|
this.theBufferedBlockCipher = par2BufferedBlockCipher;
|
||||||
|
this.buf = new byte[par2BufferedBlockCipher.getOutputSize(2048)];
|
||||||
|
this.inBuf = new byte[2048];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextChunk() throws IOException
|
||||||
|
{
|
||||||
|
int var1 = super.available();
|
||||||
|
|
||||||
|
if (var1 <= 0)
|
||||||
|
{
|
||||||
|
var1 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var1 > this.inBuf.length)
|
||||||
|
{
|
||||||
|
var1 = super.read(this.inBuf, 0, this.inBuf.length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var1 = super.read(this.inBuf, 0, var1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var1 < 0)
|
||||||
|
{
|
||||||
|
if (this.finalized)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (this.theBufferedBlockCipher != null)
|
||||||
|
{
|
||||||
|
this.maxBuf = this.theBufferedBlockCipher.doFinal(this.buf, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.maxBuf = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception var4)
|
||||||
|
{
|
||||||
|
throw new IOException("error processing stream: " + var4.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bufOff = 0;
|
||||||
|
this.finalized = true;
|
||||||
|
|
||||||
|
if (this.bufOff == this.maxBuf)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.bufOff = 0;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (this.theBufferedBlockCipher != null)
|
||||||
|
{
|
||||||
|
this.maxBuf = this.theBufferedBlockCipher.processByte(this.inBuf, 0, var1, this.buf, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.theStreamCipher.processBytes(this.inBuf, 0, var1, this.buf, 0);
|
||||||
|
this.maxBuf = var1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception var3)
|
||||||
|
{
|
||||||
|
throw new IOException("error processing stream: " + var3.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.maxBuf == 0)
|
||||||
|
{
|
||||||
|
return this.nextChunk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.maxBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException
|
||||||
|
{
|
||||||
|
return this.bufOff == this.maxBuf && this.nextChunk() < 0 ? -1 : this.buf[this.bufOff++] & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] par1ArrayOfByte) throws IOException
|
||||||
|
{
|
||||||
|
return this.read(par1ArrayOfByte, 0, par1ArrayOfByte.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(byte[] par1ArrayOfByte, int par2, int par3) throws IOException
|
||||||
|
{
|
||||||
|
if (this.bufOff == this.maxBuf && this.nextChunk() < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int var4 = this.maxBuf - this.bufOff;
|
||||||
|
|
||||||
|
if (par3 > var4)
|
||||||
|
{
|
||||||
|
System.arraycopy(this.buf, this.bufOff, par1ArrayOfByte, par2, var4);
|
||||||
|
this.bufOff = this.maxBuf;
|
||||||
|
return var4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.arraycopy(this.buf, this.bufOff, par1ArrayOfByte, par2, par3);
|
||||||
|
this.bufOff += par3;
|
||||||
|
return par3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long skip(long par1) throws IOException
|
||||||
|
{
|
||||||
|
if (par1 <= 0L)
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int var3 = this.maxBuf - this.bufOff;
|
||||||
|
|
||||||
|
if (par1 > (long)var3)
|
||||||
|
{
|
||||||
|
this.bufOff = this.maxBuf;
|
||||||
|
return (long)var3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.bufOff += (int)par1;
|
||||||
|
return (long)((int)par1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int available() throws IOException
|
||||||
|
{
|
||||||
|
return this.maxBuf - this.bufOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean markSupported()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package org.bouncycastle.crypto.io;
|
||||||
|
|
||||||
|
import java.io.FilterOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||||
|
import org.bouncycastle.crypto.StreamCipher;
|
||||||
|
|
||||||
|
public class CipherOutputStream extends FilterOutputStream
|
||||||
|
{
|
||||||
|
private BufferedBlockCipher theBufferedBlockCipher;
|
||||||
|
private StreamCipher theStreamCipher;
|
||||||
|
private byte[] oneByte = new byte[1];
|
||||||
|
private byte[] buf;
|
||||||
|
|
||||||
|
public CipherOutputStream(OutputStream par1OutputStream, BufferedBlockCipher par2BufferedBlockCipher)
|
||||||
|
{
|
||||||
|
super(par1OutputStream);
|
||||||
|
this.theBufferedBlockCipher = par2BufferedBlockCipher;
|
||||||
|
this.buf = new byte[par2BufferedBlockCipher.getBlockSize()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int par1) throws IOException
|
||||||
|
{
|
||||||
|
this.oneByte[0] = (byte)par1;
|
||||||
|
|
||||||
|
if (this.theBufferedBlockCipher != null)
|
||||||
|
{
|
||||||
|
int var2 = this.theBufferedBlockCipher.processByte(this.oneByte, 0, 1, this.buf, 0);
|
||||||
|
|
||||||
|
if (var2 != 0)
|
||||||
|
{
|
||||||
|
this.out.write(this.buf, 0, var2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.out.write(this.theStreamCipher.returnByte((byte)par1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] par1) throws IOException
|
||||||
|
{
|
||||||
|
this.write(par1, 0, par1.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte[] par1, int par2, int par3) throws IOException
|
||||||
|
{
|
||||||
|
byte[] var4;
|
||||||
|
|
||||||
|
if (this.theBufferedBlockCipher != null)
|
||||||
|
{
|
||||||
|
var4 = new byte[this.theBufferedBlockCipher.getOutputSize(par3)];
|
||||||
|
int var5 = this.theBufferedBlockCipher.processByte(par1, par2, par3, var4, 0);
|
||||||
|
|
||||||
|
if (var5 != 0)
|
||||||
|
{
|
||||||
|
this.out.write(var4, 0, var5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var4 = new byte[par3];
|
||||||
|
this.theStreamCipher.processBytes(par1, par2, par3, var4, 0);
|
||||||
|
this.out.write(var4, 0, par3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException
|
||||||
|
{
|
||||||
|
super.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (this.theBufferedBlockCipher != null)
|
||||||
|
{
|
||||||
|
byte[] var1 = new byte[this.theBufferedBlockCipher.getOutputSize(0)];
|
||||||
|
int var2 = this.theBufferedBlockCipher.doFinal(var1, 0);
|
||||||
|
|
||||||
|
if (var2 != 0)
|
||||||
|
{
|
||||||
|
this.out.write(var1, 0, var2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception var3)
|
||||||
|
{
|
||||||
|
throw new IOException("Error closing stream: " + var3.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.flush();
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
}
|
139
src/teavm/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
Normal file
139
src/teavm/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
package org.bouncycastle.crypto.modes;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.BlockCipher;
|
||||||
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
|
import org.bouncycastle.crypto.DataLengthException;
|
||||||
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||||
|
|
||||||
|
public class CFBBlockCipher implements BlockCipher
|
||||||
|
{
|
||||||
|
private byte[] IV;
|
||||||
|
private byte[] cfbV;
|
||||||
|
private byte[] cfbOutV;
|
||||||
|
private int blockSize;
|
||||||
|
private BlockCipher cipher = null;
|
||||||
|
private boolean encrypting;
|
||||||
|
|
||||||
|
public CFBBlockCipher(BlockCipher par1BlockCipher, int par2)
|
||||||
|
{
|
||||||
|
this.cipher = par1BlockCipher;
|
||||||
|
this.blockSize = par2 / 8;
|
||||||
|
this.IV = new byte[par1BlockCipher.getBlockSize()];
|
||||||
|
this.cfbV = new byte[par1BlockCipher.getBlockSize()];
|
||||||
|
this.cfbOutV = new byte[par1BlockCipher.getBlockSize()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(boolean par1, CipherParameters par2CipherParameters) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
this.encrypting = par1;
|
||||||
|
|
||||||
|
if (par2CipherParameters instanceof ParametersWithIV)
|
||||||
|
{
|
||||||
|
ParametersWithIV var3 = (ParametersWithIV)par2CipherParameters;
|
||||||
|
byte[] var4 = var3.getIV();
|
||||||
|
|
||||||
|
if (var4.length < this.IV.length)
|
||||||
|
{
|
||||||
|
System.arraycopy(var4, 0, this.IV, this.IV.length - var4.length, var4.length);
|
||||||
|
|
||||||
|
for (int var5 = 0; var5 < this.IV.length - var4.length; ++var5)
|
||||||
|
{
|
||||||
|
this.IV[var5] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.arraycopy(var4, 0, this.IV, 0, this.IV.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reset();
|
||||||
|
|
||||||
|
if (var3.getParameters() != null)
|
||||||
|
{
|
||||||
|
this.cipher.init(true, var3.getParameters());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.reset();
|
||||||
|
this.cipher.init(true, par2CipherParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of the algorithm the cipher implements.
|
||||||
|
*/
|
||||||
|
public String getAlgorithmName()
|
||||||
|
{
|
||||||
|
return this.cipher.getAlgorithmName() + "/CFB" + this.blockSize * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the block size for this cipher (in bytes).
|
||||||
|
*/
|
||||||
|
public int getBlockSize()
|
||||||
|
{
|
||||||
|
return this.blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int processBlock(byte[] par1ArrayOfByte, int par2, byte[] par3ArrayOfByte, int par4) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
return this.encrypting ? this.encryptBlock(par1ArrayOfByte, par2, par3ArrayOfByte, par4) : this.decryptBlock(par1ArrayOfByte, par2, par3ArrayOfByte, par4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int encryptBlock(byte[] par1ArrayOfByte, int par2, byte[] par3ArrayOfByte, int par4) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
if (par2 + this.blockSize > par1ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("input buffer too short");
|
||||||
|
}
|
||||||
|
else if (par4 + this.blockSize > par3ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("output buffer too short");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.cipher.processBlock(this.cfbV, 0, this.cfbOutV, 0);
|
||||||
|
|
||||||
|
for (int var5 = 0; var5 < this.blockSize; ++var5)
|
||||||
|
{
|
||||||
|
par3ArrayOfByte[par4 + var5] = (byte)(this.cfbOutV[var5] ^ par1ArrayOfByte[par2 + var5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(this.cfbV, this.blockSize, this.cfbV, 0, this.cfbV.length - this.blockSize);
|
||||||
|
System.arraycopy(par3ArrayOfByte, par4, this.cfbV, this.cfbV.length - this.blockSize, this.blockSize);
|
||||||
|
return this.blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int decryptBlock(byte[] par1ArrayOfByte, int par2, byte[] par3ArrayOfByte, int par4) throws DataLengthException, IllegalStateException
|
||||||
|
{
|
||||||
|
if (par2 + this.blockSize > par1ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("input buffer too short");
|
||||||
|
}
|
||||||
|
else if (par4 + this.blockSize > par3ArrayOfByte.length)
|
||||||
|
{
|
||||||
|
throw new DataLengthException("output buffer too short");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.cipher.processBlock(this.cfbV, 0, this.cfbOutV, 0);
|
||||||
|
System.arraycopy(this.cfbV, this.blockSize, this.cfbV, 0, this.cfbV.length - this.blockSize);
|
||||||
|
System.arraycopy(par1ArrayOfByte, par2, this.cfbV, this.cfbV.length - this.blockSize, this.blockSize);
|
||||||
|
|
||||||
|
for (int var5 = 0; var5 < this.blockSize; ++var5)
|
||||||
|
{
|
||||||
|
par3ArrayOfByte[par4 + var5] = (byte)(this.cfbOutV[var5] ^ par1ArrayOfByte[par2 + var5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
System.arraycopy(this.IV, 0, this.cfbV, 0, this.IV.length);
|
||||||
|
this.cipher.reset();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.bouncycastle.crypto.params;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
|
|
||||||
|
public class KeyParameter implements CipherParameters
|
||||||
|
{
|
||||||
|
private byte[] key;
|
||||||
|
|
||||||
|
public KeyParameter(byte[] par1ArrayOfByte)
|
||||||
|
{
|
||||||
|
this(par1ArrayOfByte, 0, par1ArrayOfByte.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyParameter(byte[] par1ArrayOfByte, int par2, int par3)
|
||||||
|
{
|
||||||
|
this.key = new byte[par3];
|
||||||
|
System.arraycopy(par1ArrayOfByte, par2, this.key, 0, par3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getKey()
|
||||||
|
{
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.bouncycastle.crypto.params;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.CipherParameters;
|
||||||
|
|
||||||
|
public class ParametersWithIV implements CipherParameters
|
||||||
|
{
|
||||||
|
private byte[] iv;
|
||||||
|
private CipherParameters parameters;
|
||||||
|
|
||||||
|
public ParametersWithIV(CipherParameters par1CipherParameters, byte[] par2ArrayOfByte, int par3, int par4)
|
||||||
|
{
|
||||||
|
this.iv = new byte[par4];
|
||||||
|
this.parameters = par1CipherParameters;
|
||||||
|
System.arraycopy(par2ArrayOfByte, par3, this.iv, 0, par4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getIV()
|
||||||
|
{
|
||||||
|
return this.iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CipherParameters getParameters()
|
||||||
|
{
|
||||||
|
return this.parameters;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user