From 7b60d2ffc2996f31e001715b9cd02a8530ee5620 Mon Sep 17 00:00:00 2001
From: Sing Painter
Date: Fri, 28 Sep 2018 10:17:27 +0300
Subject: [PATCH] + new version (add createTx)
---
README.md | 47 +-
example.html | 31 +-
metahash.js | 128 ++-
metahash.min.js | 36 +
source/asn1-1.0.js | 1658 +++++++++++++++++++++++++++++
source/asn1hex-1.1.js | 709 +++++++++++++
source/base64x-1.1.js | 1173 +++++++++++++++++++++
source/build.md | 17 +
source/crypto-1.1.js | 1466 ++++++++++++++++++++++++++
source/cryptojs-312-core-fix.js | 711 +++++++++++++
source/ec.js | 318 ++++++
source/ecdsa-modified-1.0.js | 839 +++++++++++++++
source/ecparam-1.0.js | 248 +++++
source/jsbn.js | 561 ++++++++++
source/jsbn2.js | 658 ++++++++++++
source/keyutil-1.0.js | 1756 +++++++++++++++++++++++++++++++
source/pack.js | 384 +++++++
source/prng4.js | 47 +
source/rng.js | 81 ++
source/rsa.js | 212 ++++
source/sha256.js | 185 ++++
source/yahoo.js | 72 ++
22 files changed, 11327 insertions(+), 10 deletions(-)
create mode 100644 metahash.min.js
create mode 100644 source/asn1-1.0.js
create mode 100644 source/asn1hex-1.1.js
create mode 100644 source/base64x-1.1.js
create mode 100644 source/build.md
create mode 100644 source/crypto-1.1.js
create mode 100644 source/cryptojs-312-core-fix.js
create mode 100644 source/ec.js
create mode 100644 source/ecdsa-modified-1.0.js
create mode 100644 source/ecparam-1.0.js
create mode 100644 source/jsbn.js
create mode 100644 source/jsbn2.js
create mode 100644 source/keyutil-1.0.js
create mode 100644 source/pack.js
create mode 100644 source/prng4.js
create mode 100644 source/rng.js
create mode 100644 source/rsa.js
create mode 100644 source/sha256.js
create mode 100644 source/yahoo.js
diff --git a/README.md b/README.md
index 43a15b0..32f381f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
![logo_en](https://user-images.githubusercontent.com/2198826/46068471-e44d1900-c181-11e8-99cf-0234839623f5.png)
# [MetaHash](https://metahash.org/) JavaScript library
-### Версия 0.1.0
+### Версия 0.2.0
------------
@@ -13,7 +13,9 @@
## Использование
1. Подключить MetaHash JavaScript библиотеку:
```html
-
+
+или через CDN:
+
```
2. Если нужно изменить конфигурацию: адрес ноды, и т.д.:
```js
@@ -104,6 +106,45 @@ metahash.getTx('23fb8f98f1faecf04c23112ad47bba7b42ff7bcec0cdf22ce231061d02e9ad2c
});
```
+- ### createTx
+Создание транзакции.
+
+Параметры:
+***to***
+***value***
+***fee***
+***nonce***
+***data***
+***publicKeyHex***
+***privateKey***
+***youHashAddress***
+
+Пример использования:
+```js
+metahash.apiUrl = 'http://139.162.42.43:9999';
+let publicKeyBase64 = 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE8gBrTLUQxXDZQ4f/OpiFWe4dhNbEo11PtFkq/0NgXt+AxGwmiWUhojtI56Hj2H3QpxGZCqrjxldDC4IHzpyVfw=='; // from key.pub
+let to = '0x0003f6441039b7f944c82ac62f7c124918e02c203b5820f5ed';
+let value = 1000;
+let fee = 0;
+let nonce = null;
+let data = '';
+let publicKeyHex = metahash.base64toHex(publicKeyBase64); // convert from base64 to hex
+/*
+ 1. openssl ec -in key.pem -noout -text
+ 2. copy "priv" value:
+ 42:d1:ae:22:4c:27:fc:02:a4:bc:43:b9:ec:47:6b:
+ bd:21:b4:51:69:db:97:35:f9:c6:1d:31:a0:87:21:
+ 04:4f
+ 3. remove symbol ":"
+*/
+let privateKey = '42d1ae224c27fc02a4bc43b9ec476bbd21b45169db9735f9c61d31a08721044f';
+let youHashAddress = '0x009b84f533aa2192456a7e944eb471183abbceafe678a98984';
+metahash.createTx(to, value, fee, nonce, data, publicKeyHex, privateKey, youHashAddress, (res, err) => {
+ if (res) console.log('createTx', res, 'http://mhscan.com/?page=tx&id=' + res.params);
+ else console.error('createTx', err)
+});
+```
+
- ### balanceFormatter
Форматирование баланса в правильный вид.
@@ -123,6 +164,8 @@ BTC: [3LPVbQ8fu4um4aY16tpeie62kznGJywrai](bitcoin:3LPVbQ8fu4um4aY16tpeie62kznGJy
ETH: [0x230D2C5aE86fFB69C8e6d575aB634f345aE497e5](ethereum:0x230D2C5aE86fFB69C8e6d575aB634f345aE497e5)
+MHC: [0x00a1d0f653dd39c33255acac2f5ea4fb3c3ea5795908c3bf05](mhc:0x00a1d0f653dd39c33255acac2f5ea4fb3c3ea5795908c3bf05)
+
------------
## Контакты:
diff --git a/example.html b/example.html
index 0927ff7..46619ea 100644
--- a/example.html
+++ b/example.html
@@ -1,7 +1,9 @@
-
+
\ No newline at end of file
diff --git a/metahash.js b/metahash.js
index 9ef7bcc..a23faf1 100644
--- a/metahash.js
+++ b/metahash.js
@@ -7,7 +7,7 @@ class MetaHash {
request(method, callback, params) {
const query = {
- id: 1,
+ //id: 1,
method: method,
params: params
};
@@ -17,7 +17,11 @@ class MetaHash {
})
.then((response) => { return response.json(); })
.then((data) => {
- if (data.result) callback(data.result); else callback(null, data.error);
+ if ( ! data.error) {
+ if ( ! data.params) data = data.result;
+ callback(data);
+ }
+ else callback(null, data.error);
});
}
@@ -33,7 +37,7 @@ class MetaHash {
}
callback(res, err);
}, {
- address: address
+ address
});
}
@@ -48,7 +52,7 @@ class MetaHash {
}
callback(res, err);
}, {
- address: address
+ address
});
}
@@ -60,10 +64,122 @@ class MetaHash {
}
callback(res, err);
}, {
- hash: hash
+ hash
});
}
+ intToHexHandler(firstFormat, firstValue, secondFormat, SecondValue) {
+ return this.binToHex(pack(firstFormat, firstValue)) + (secondFormat ? this.binToHex(pack(secondFormat, SecondValue)) : '');
+ }
+
+ intToHex(value) {
+ if (value < 250) return this.intToHexHandler('C', value);
+ else if (value < 65536) return this.intToHexHandler('C', 250, 'v', value);
+ else if (value < 4294967296) return this.intToHexHandler('C', 251, 'V', value);
+ else return this.intToHexHandler('C', 252, '@', value);
+ }
+
+ strToHex(value) {
+ let str = '';
+ for (let i = 0 ; i < value.length ; i++ ) {
+ if (value.charCodeAt(i) < 256) str += '\\x' + value.charCodeAt(i).toString(16) + '';
+ else if (value.charCodeAt(i) < 4096) str += '\\u0' + value.charCodeAt(i).toString(16) + '';
+ else str += '\\u' + value.charCodeAt(i).toString(16) + '';
+ }
+ return str;
+ }
+
+ binToHex(value) {
+ let i, l, o = '', n;
+ value += '';
+ for (i = 0, l = value.length; i < l; i++) {
+ n = value.charCodeAt(i).toString(16);
+ o += n.length < 2 ? '0' + n : n;
+ }
+ return o;
+ }
+
+ base64toHex(base64) {
+ let raw = atob(base64);
+ let hex = '';
+ for (let i = 0; i < raw.length; i++ ) {
+ let _hex = raw.charCodeAt(i).toString(16);
+ hex += (_hex.length==2?_hex:'0'+_hex);
+ }
+ return hex;
+ }
+
+ createTx(to, value, fee, nonce, data, pubkey, privateKey, youHashAddress, callback) {
+ value = value.toString();
+ fee = fee.toString();
+ // need refactoring!
+ if ( ! nonce) {
+ this.apiUrl = 'http://172.104.224.65:5795';
+ const address = youHashAddress;
+ this.fetchBalance(address, (res, err) => {
+ this.apiUrl = 'http://139.162.42.43:9999';
+ res.count_spent++;
+ this.createTxHandler(to, value, fee, res.count_spent, data, pubkey, privateKey, callback)
+ });
+ }
+ else this.createTxHandler(to, value, fee, nonce, data, pubkey, privateKey, callback);
+ }
+
+ createTxHandler(to, value, fee, nonce, data, pubkey, privateKey, callback) {
+ nonce = nonce.toString();
+ const message = to.substr(2) + this.intToHex(value) + this.intToHex(fee) + this.intToHex(nonce) + '00';
+ const sig = new KJUR.crypto.Signature({'alg': 'SHA256withECDSA'});
+ sig.init({d: privateKey, curve: 'secp256k1'});
+ sig.updateHex(message);
+ const sign = sig.sign();
+ this.request('mhc_send', (res, err) => {
+ callback(res, err);
+ }, {
+ to,
+ value,
+ fee,
+ nonce,
+ data,
+ pubkey,
+ sign
+ });
+ }
+
}
-const metahash = new MetaHash();
\ No newline at end of file
+const metahash = new MetaHash();
+
+// Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+if(void 0===YAHOO)var YAHOO={};YAHOO.lang={extend:function(t,o,e){if(!o||!t)throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included.");var r=function(){};if(r.prototype=o.prototype,t.prototype=new r,t.prototype.constructor=t,t.superclass=o.prototype,o.prototype.constructor==Object.prototype.constructor&&(o.prototype.constructor=o),e){var n;for(n in e)t.prototype[n]=e[n];var p=function(){},c=["toString","valueOf"];try{/MSIE/.test(navigator.userAgent)&&(p=function(t,o){for(n=0;n>>2]>>>24-s%4*8&255;n[r+s>>>2]|=o<<24-(r+s)%4*8}else for(s=0;s>>2]=i[s>>>2];return this.sigBytes+=e,this},clamp:function(){var n=this.words,i=this.sigBytes;n[i>>>2]&=4294967295<<32-i%4*8,n.length=t.ceil(i/4)},clone:function(){var t=e.clone.call(this);return t.words=this.words.slice(0),t},random:function(n){for(var i=[],r=0;r>>2]>>>24-e%4*8&255;r.push((s>>>4).toString(16)),r.push((15&s).toString(16))}return r.join("")},parse:function(t){for(var n=t.length,i=[],r=0;r>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new s.init(i,n/2)}},c=o.Latin1={stringify:function(t){for(var n=t.words,i=t.sigBytes,r=[],e=0;e>>2]>>>24-e%4*8&255;r.push(String.fromCharCode(s))}return r.join("")},parse:function(t){for(var n=t.length,i=[],r=0;r>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new s.init(i,n)}},u=o.Utf8={stringify:function(t){try{return decodeURIComponent(escape(c.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return c.parse(unescape(encodeURIComponent(t)))}},f=r.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new s.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=u.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(n){var i=this._data,r=i.words,e=i.sigBytes,o=this.blockSize,a=e/(4*o),c=(a=n?t.ceil(a):t.max((0|a)-this._minBufferSize,0))*o,u=t.min(4*c,e);if(c){for(var f=0;f=0;){var s=i*this[t++]+r[o]+n;n=Math.floor(s/67108864),r[o++]=67108863&s}return n}function am2(t,i,r,o,n,e){for(var s=32767&i,h=i>>15;--e>=0;){var p=32767&this[t],a=this[t++]>>15,f=h*p+a*s;n=((p=s*p+((32767&f)<<15)+r[o]+(1073741823&n))>>>30)+(f>>>15)+h*a+(n>>>30),r[o++]=1073741823&p}return n}function am3(t,i,r,o,n,e){for(var s=16383&i,h=i>>14;--e>=0;){var p=16383&this[t],a=this[t++]>>14,f=h*p+a*s;n=((p=s*p+((16383&f)<<14)+r[o]+n)>>28)+(f>>14)+h*a,r[o++]=268435455&p}return n}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28),BigInteger.prototype.DB=dbits,BigInteger.prototype.DM=(1<=0;--i)t[i]=this[i];t.t=this.t,t.s=this.s}function bnpFromInt(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0}function nbv(t){var i=nbi();return i.fromInt(t),i}function bnpFromString(t,i){var r;if(16==i)r=4;else if(8==i)r=3;else if(256==i)r=8;else if(2==i)r=1;else if(32==i)r=5;else{if(4!=i)return void this.fromRadix(t,i);r=2}this.t=0,this.s=0;for(var o=t.length,n=!1,e=0;--o>=0;){var s=8==r?255&t[o]:intAt(t,o);s<0?"-"==t.charAt(o)&&(n=!0):(n=!1,0==e?this[this.t++]=s:e+r>this.DB?(this[this.t-1]|=(s&(1<>this.DB-e):this[this.t-1]|=s<=this.DB&&(e-=this.DB))}8==r&&0!=(128&t[0])&&(this.s=-1,e>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==t;)--this.t}function bnToString(t){if(this.s<0)return"-"+this.negate().toString(t);var i;if(16==t)i=4;else if(8==t)i=3;else if(2==t)i=1;else if(32==t)i=5;else{if(4!=t)return this.toRadix(t);i=2}var r,o=(1<0)for(h>h)>0&&(n=!0,e=int2char(r));s>=0;)h>(h+=this.DB-i)):(r=this[s]>>(h-=i)&o,h<=0&&(h+=this.DB,--s)),r>0&&(n=!0),n&&(e+=int2char(r));return n?e:"0"}function bnNegate(){var t=nbi();return BigInteger.ZERO.subTo(this,t),t}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(t){var i=this.s-t.s;if(0!=i)return i;var r=this.t;if(0!=(i=r-t.t))return this.s<0?-i:i;for(;--r>=0;)if(0!=(i=this[r]-t[r]))return i;return 0}function nbits(t){var i,r=1;return 0!=(i=t>>>16)&&(t=i,r+=16),0!=(i=t>>8)&&(t=i,r+=8),0!=(i=t>>4)&&(t=i,r+=4),0!=(i=t>>2)&&(t=i,r+=2),0!=(i=t>>1)&&(t=i,r+=1),r}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(t,i){var r;for(r=this.t-1;r>=0;--r)i[r+t]=this[r];for(r=t-1;r>=0;--r)i[r]=0;i.t=this.t+t,i.s=this.s}function bnpDRShiftTo(t,i){for(var r=t;r=0;--r)i[r+s+1]=this[r]>>n|h,h=(this[r]&e)<=0;--r)i[r]=0;i[s]=h,i.t=this.t+s+1,i.s=this.s,i.clamp()}function bnpRShiftTo(t,i){i.s=this.s;var r=Math.floor(t/this.DB);if(r>=this.t)i.t=0;else{var o=t%this.DB,n=this.DB-o,e=(1<>o;for(var s=r+1;s>o;o>0&&(i[this.t-r-1]|=(this.s&e)<>=this.DB;if(t.t>=this.DB;o+=this.s}else{for(o+=this.s;r>=this.DB;o-=t.s}i.s=o<0?-1:0,o<-1?i[r++]=this.DV+o:o>0&&(i[r++]=o),i.t=r,i.clamp()}function bnpMultiplyTo(t,i){var r=this.abs(),o=t.abs(),n=r.t;for(i.t=n+o.t;--n>=0;)i[n]=0;for(n=0;n=0;)t[r]=0;for(r=0;r=i.DV&&(t[r+i.t]-=i.DV,t[r+i.t+1]=1)}t.t>0&&(t[t.t-1]+=i.am(r,i[r],t,2*r,0,1)),t.s=0,t.clamp()}function bnpDivRemTo(t,i,r){var o=t.abs();if(!(o.t<=0)){var n=this.abs();if(n.t0?(o.lShiftTo(p,e),n.lShiftTo(p,r)):(o.copyTo(e),n.copyTo(r));var a=e.t,f=e[a-1];if(0!=f){var u=f*(1<1?e[a-2]>>this.F2:0),g=this.FV/u,m=(1<=0&&(r[r.t++]=1,r.subTo(l,r)),BigInteger.ONE.dlShiftTo(a,l),l.subTo(e,e);e.t=0;){var T=r[--v]==f?this.DM:Math.floor(r[v]*g+(r[v-1]+c)*m);if((r[v]+=e.am(0,T,r,b,0,a))0&&r.rShiftTo(p,r),s<0&&BigInteger.ZERO.subTo(r,r)}}}function bnMod(t){var i=nbi();return this.abs().divRemTo(t,null,i),this.s<0&&i.compareTo(BigInteger.ZERO)>0&&t.subTo(i,i),i}function Classic(t){this.m=t}function cConvert(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function cRevert(t){return t}function cReduce(t){t.divRemTo(this.m,null,t)}function cMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function cSqrTo(t,i){t.squareTo(i),this.reduce(i)}function bnpInvDigit(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var i=3&t;return(i=(i=(i=(i=i*(2-(15&t)*i)&15)*(2-(255&t)*i)&255)*(2-((65535&t)*i&65535))&65535)*(2-t*i%this.DV)%this.DV)>0?this.DV-i:-i}function Montgomery(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(i,i),i}function montRevert(t){var i=nbi();return t.copyTo(i),this.reduce(i),i}function montReduce(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var i=0;i>15)*this.mpl&this.um)<<15)&t.DM;for(t[r=i+this.m.t]+=this.m.am(0,o,t,i,0,this.m.t);t[r]>=t.DV;)t[r]-=t.DV,t[++r]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function montSqrTo(t,i){t.squareTo(i),this.reduce(i)}function montMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(t,i){if(t>4294967295||t<1)return BigInteger.ONE;var r=nbi(),o=nbi(),n=i.convert(this),e=nbits(t)-1;for(n.copyTo(r);--e>=0;)if(i.sqrTo(r,o),(t&1<0)i.mulTo(o,n,r);else{var s=r;r=o,o=s}return i.revert(r)}function bnModPowInt(t,i){var r;return r=t<256||i.isEven()?new Classic(i):new Montgomery(i),this.exp(t,r)}Classic.prototype.convert=cConvert,Classic.prototype.revert=cRevert,Classic.prototype.reduce=cReduce,Classic.prototype.mulTo=cMulTo,Classic.prototype.sqrTo=cSqrTo,Montgomery.prototype.convert=montConvert,Montgomery.prototype.revert=montRevert,Montgomery.prototype.reduce=montReduce,Montgomery.prototype.mulTo=montMulTo,Montgomery.prototype.sqrTo=montSqrTo,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,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,BigInteger.ZERO=nbv(0),BigInteger.ONE=nbv(1);
+// (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+function bnClone(){var t=nbi();return this.copyTo(t),t}function bnIntValue(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(t){return Math.floor(Math.LN2*this.DB/Math.log(t))}function bnSigNum(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function bnpToRadix(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var i=this.chunkSize(t),r=Math.pow(t,i),e=nbv(r),n=nbi(),o=nbi(),s="";for(this.divRemTo(e,n,o);n.signum()>0;)s=(r+o.intValue()).toString(t).substr(1)+s,n.divRemTo(e,n,o);return o.intValue().toString(t)+s}function bnpFromRadix(t,i){this.fromInt(0),null==i&&(i=10);for(var r=this.chunkSize(i),e=Math.pow(i,r),n=!1,o=0,s=0,h=0;h=r&&(this.dMultiply(e),this.dAddOffset(s,0),o=0,s=0))}o>0&&(this.dMultiply(Math.pow(i,o)),this.dAddOffset(s,0)),n&&BigInteger.ZERO.subTo(this,this)}function bnpFromNumber(t,i,r){if("number"==typeof i)if(t<2)this.fromInt(1);else for(this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(t-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(i);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(BigInteger.ONE.shiftLeft(t-1),this);else{var e=new Array,n=7&t;e.length=1+(t>>3),i.nextBytes(e),n>0?e[0]&=(1<0)for(e>e)!=(this.s&this.DM)>>e&&(i[n++]=r|this.s<=0;)e<8?(r=(this[t]&(1<>(e+=this.DB-8)):(r=this[t]>>(e-=8)&255,e<=0&&(e+=this.DB,--t)),0!=(128&r)&&(r|=-256),0==n&&(128&this.s)!=(128&r)&&++n,(n>0||r!=this.s)&&(i[n++]=r);return i}function bnEquals(t){return 0==this.compareTo(t)}function bnMin(t){return this.compareTo(t)<0?this:t}function bnMax(t){return this.compareTo(t)>0?this:t}function bnpBitwiseTo(t,i,r){var e,n,o=Math.min(t.t,this.t);for(e=0;e>=16,i+=16),0==(255&t)&&(t>>=8,i+=8),0==(15&t)&&(t>>=4,i+=4),0==(3&t)&&(t>>=2,i+=2),0==(1&t)&&++i,i}function bnGetLowestSetBit(){for(var t=0;t=this.t?0!=this.s:0!=(this[i]&1<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;r>=this.DB;e+=t.s}i.s=e<0?-1:0,e>0?i[r++]=e:e<-1&&(i[r++]=this.DV+e),i.t=r,i.clamp()}function bnAdd(t){var i=nbi();return this.addTo(t,i),i}function bnSubtract(t){var i=nbi();return this.subTo(t,i),i}function bnMultiply(t){var i=nbi();return this.multiplyTo(t,i),i}function bnSquare(){var t=nbi();return this.squareTo(t),t}function bnDivide(t){var i=nbi();return this.divRemTo(t,i,null),i}function bnRemainder(t){var i=nbi();return this.divRemTo(t,null,i),i}function bnDivideAndRemainder(t){var i=nbi(),r=nbi();return this.divRemTo(t,i,r),new Array(i,r)}function bnpDMultiply(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()}function bnpDAddOffset(t,i){if(0!=t){for(;this.t<=i;)this[this.t++]=0;for(this[i]+=t;this[i]>=this.DV;)this[i]-=this.DV,++i>=this.t&&(this[this.t++]=0),++this[i]}}function NullExp(){}function nNop(t){return t}function nMulTo(t,i,r){t.multiplyTo(i,r)}function nSqrTo(t,i){t.squareTo(i)}function bnPow(t){return this.exp(t,new NullExp)}function bnpMultiplyLowerTo(t,i,r){var e,n=Math.min(this.t+t.t,i);for(r.s=0,r.t=n;n>0;)r[--n]=0;for(e=r.t-this.t;n=0;)r[e]=0;for(e=Math.max(i-this.t,0);e2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var i=nbi();return t.copyTo(i),this.reduce(i),i}function barrettRevert(t){return t}function barrettReduce(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)}function barrettSqrTo(t,i){t.squareTo(i),this.reduce(i)}function barrettMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function bnModPow(t,i){var r,e,n=t.bitLength(),o=nbv(1);if(n<=0)return o;r=n<18?1:n<48?3:n<144?4:n<768?5:6,e=n<8?new Classic(i):i.isEven()?new Barrett(i):new Montgomery(i);var s=new Array,h=3,u=r-1,p=(1<1){var f=nbi();for(e.sqrTo(s[1],f);h<=p;)s[h]=nbi(),e.mulTo(f,s[h-2],s[h]),h+=2}var a,b,g=t.t-1,l=!0,m=nbi();for(n=nbits(t[g])-1;g>=0;){for(n>=u?a=t[g]>>n-u&p:(a=(t[g]&(1<0&&(a|=t[g-1]>>this.DB+n-u)),h=r;0==(1&a);)a>>=1,--h;if((n-=h)<0&&(n+=this.DB,--g),l)s[a].copyTo(o),l=!1;else{for(;h>1;)e.sqrTo(o,m),e.sqrTo(m,o),h-=2;h>0?e.sqrTo(o,m):(b=o,o=m,m=b),e.mulTo(m,s[a],o)}for(;g>=0&&0==(t[g]&1<0&&(i.rShiftTo(o,i),r.rShiftTo(o,r));i.signum()>0;)(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),(n=r.getLowestSetBit())>0&&r.rShiftTo(n,r),i.compareTo(r)>=0?(i.subTo(r,i),i.rShiftTo(1,i)):(r.subTo(i,r),r.rShiftTo(1,r));return o>0&&r.lShiftTo(o,r),r}function bnpModInt(t){if(t<=0)return 0;var i=this.DV%t,r=this.s<0?t-1:0;if(this.t>0)if(0==i)r=this[0]%t;else for(var e=this.t-1;e>=0;--e)r=(i*r+this[e])%t;return r}function bnModInverse(t){var i=t.isEven();if(this.isEven()&&i||0==t.signum())return BigInteger.ZERO;for(var r=t.clone(),e=this.clone(),n=nbv(1),o=nbv(0),s=nbv(0),h=nbv(1);0!=r.signum();){for(;r.isEven();)r.rShiftTo(1,r),i?(n.isEven()&&o.isEven()||(n.addTo(this,n),o.subTo(t,o)),n.rShiftTo(1,n)):o.isEven()||o.subTo(t,o),o.rShiftTo(1,o);for(;e.isEven();)e.rShiftTo(1,e),i?(s.isEven()&&h.isEven()||(s.addTo(this,s),h.subTo(t,h)),s.rShiftTo(1,s)):h.isEven()||h.subTo(t,h),h.rShiftTo(1,h);r.compareTo(e)>=0?(r.subTo(e,r),i&&n.subTo(s,n),o.subTo(h,o)):(e.subTo(r,e),i&&s.subTo(n,s),h.subTo(o,h))}return 0!=e.compareTo(BigInteger.ONE)?BigInteger.ZERO:h.compareTo(t)>=0?h.subtract(t):h.signum()<0?(h.addTo(t,h),h.signum()<0?h.add(t):h):h}NullExp.prototype.convert=nNop,NullExp.prototype.revert=nNop,NullExp.prototype.mulTo=nMulTo,NullExp.prototype.sqrTo=nSqrTo,Barrett.prototype.convert=barrettConvert,Barrett.prototype.revert=barrettRevert,Barrett.prototype.reduce=barrettReduce,Barrett.prototype.mulTo=barrettMulTo,Barrett.prototype.sqrTo=barrettSqrTo;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],lplim=(1<<26)/lowprimes[lowprimes.length-1];function bnIsProbablePrime(t){var i,r=this.abs();if(1==r.t&&r[0]<=lowprimes[lowprimes.length-1]){for(i=0;i>1)>lowprimes.length&&(t=lowprimes.length);for(var n=nbi(),o=0;o0;--e){u=u.twice();var s=n.testBit(e);s!=i.testBit(e)&&(u=u.add(s?this:r))}return u}function pointFpMultiplyTwo(t,e,i){var n;n=t.bitLength()>i.bitLength()?t.bitLength()-1:i.bitLength()-1;for(var r=this.curve.getInfinity(),u=this.add(e);n>=0;)r=r.twice(),t.testBit(n)?r=i.testBit(n)?r.add(u):r.add(this):i.testBit(n)&&(r=r.add(e)),--n;return r}function ECCurveFp(t,e,i){this.q=t,this.a=this.fromBigInteger(e),this.b=this.fromBigInteger(i),this.infinity=new ECPointFp(this,null,null)}function curveFpGetQ(){return this.q}function curveFpGetA(){return this.a}function curveFpGetB(){return this.b}function curveFpEquals(t){return t==this||this.q.equals(t.q)&&this.a.equals(t.a)&&this.b.equals(t.b)}function curveFpGetInfinity(){return this.infinity}function curveFpFromBigInteger(t){return new ECFieldElementFp(this.q,t)}function curveFpDecodePointHex(t){switch(parseInt(t.substr(0,2),16)){case 0:return this.infinity;case 2:case 3:return null;case 4:case 6:case 7:var e=(t.length-2)/2,i=t.substr(2,e),n=t.substr(e+2,e);return new ECPointFp(this,this.fromBigInteger(new BigInteger(i,16)),this.fromBigInteger(new BigInteger(n,16)));default:return null}}ECFieldElementFp.prototype.equals=feFpEquals,ECFieldElementFp.prototype.toBigInteger=feFpToBigInteger,ECFieldElementFp.prototype.negate=feFpNegate,ECFieldElementFp.prototype.add=feFpAdd,ECFieldElementFp.prototype.subtract=feFpSubtract,ECFieldElementFp.prototype.multiply=feFpMultiply,ECFieldElementFp.prototype.square=feFpSquare,ECFieldElementFp.prototype.divide=feFpDivide,ECPointFp.prototype.getX=pointFpGetX,ECPointFp.prototype.getY=pointFpGetY,ECPointFp.prototype.equals=pointFpEquals,ECPointFp.prototype.isInfinity=pointFpIsInfinity,ECPointFp.prototype.negate=pointFpNegate,ECPointFp.prototype.add=pointFpAdd,ECPointFp.prototype.twice=pointFpTwice,ECPointFp.prototype.multiply=pointFpMultiply,ECPointFp.prototype.multiplyTwo=pointFpMultiplyTwo,ECCurveFp.prototype.getQ=curveFpGetQ,ECCurveFp.prototype.getA=curveFpGetA,ECCurveFp.prototype.getB=curveFpGetB,ECCurveFp.prototype.equals=curveFpEquals,ECCurveFp.prototype.getInfinity=curveFpGetInfinity,ECCurveFp.prototype.fromBigInteger=curveFpFromBigInteger,ECCurveFp.prototype.decodePointHex=curveFpDecodePointHex;
+// ! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+function Arcfour(){this.i=0,this.j=0,this.S=new Array}function ARC4init(i){var t,s,h;for(t=0;t<256;++t)this.S[t]=t;for(s=0,t=0;t<256;++t)s=s+this.S[t]+i[t%i.length]&255,h=this.S[t],this.S[t]=this.S[s],this.S[s]=h;this.i=0,this.j=0}function ARC4next(){var i;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,i=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=i,this.S[i+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}Arcfour.prototype.init=ARC4init,Arcfour.prototype.next=ARC4next;var rng_psize=256;
+// (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+var rng_state,rng_pool,rng_pptr;function rng_seed_int(r){rng_pool[rng_pptr++]^=255&r,rng_pool[rng_pptr++]^=r>>8&255,rng_pool[rng_pptr++]^=r>>16&255,rng_pool[rng_pptr++]^=r>>24&255,rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}if(null==rng_pool){var t;if(rng_pool=new Array,rng_pptr=0,void 0!==window&&(void 0!==window.crypto||void 0!==window.msCrypto)){var crypto=window.crypto||window.msCrypto;if(crypto.getRandomValues){var ua=new Uint8Array(32);for(crypto.getRandomValues(ua),t=0;t<32;++t)rng_pool[rng_pptr++]=ua[t]}else if("Netscape"==navigator.appName&&navigator.appVersion<"5"){var z=window.crypto.random(32);for(t=0;t>>8,rng_pool[rng_pptr++]=255&t;rng_pptr=0,rng_seed_time()}function rng_get_byte(){if(null==rng_state){for(rng_seed_time(),(rng_state=prng_newstate()).init(rng_pool),rng_pptr=0;rng_pptr=0&&n>0;){var i=t.charCodeAt(e--);i<128?r[--n]=i:i>127&&i<2048?(r[--n]=63&i|128,r[--n]=i>>6|192):(r[--n]=63&i|128,r[--n]=i>>6&63|128,r[--n]=i>>12|224)}r[--n]=0;for(var o=new SecureRandom,l=new Array;n>2;){for(l[0]=0;0==l[0];)o.nextBytes(l);r[--n]=l[0]}return r[--n]=2,r[--n]=0,new BigInteger(r)}function oaep_mgf1_arr(t,n,r){for(var e="",i=0;e.length>24,(16711680&i)>>16,(65280&i)>>8,255&i]))),i+=1;return e}function oaep_pad(t,n,r,e){var i=KJUR.crypto.MessageDigest,o=KJUR.crypto.Util,l=null;if(r||(r="sha1"),"string"==typeof r&&(l=i.getCanonicalAlgName(r),e=i.getHashLength(l),r=function(t){return hextorstr(o.hashHex(rstrtohex(t),l))}),t.length+2*e+2>n)throw"Message too long for RSA";var u,a="";for(u=0;u0&&n.length>0))throw"Invalid RSA public key";this.n=parseBigInt(t,16),this.e=parseInt(n,16)}}function RSADoPublic(t){return t.modPowInt(this.e,this.n)}function RSAEncrypt(t){var n=pkcs1pad2(t,this.n.bitLength()+7>>3);if(null==n)return null;var r=this.doPublic(n);if(null==r)return null;var e=r.toString(16);return 0==(1&e.length)?e:"0"+e}function RSAEncryptOAEP(t,n,r){var e=oaep_pad(t,this.n.bitLength()+7>>3,n,r);if(null==e)return null;var i=this.doPublic(e);if(null==i)return null;var o=i.toString(16);return 0==(1&o.length)?o:"0"+o}RSAKey.prototype.doPublic=RSADoPublic,RSAKey.prototype.setPublic=RSASetPublic,RSAKey.prototype.encrypt=RSAEncrypt,RSAKey.prototype.encryptOAEP=RSAEncryptOAEP,RSAKey.prototype.type="RSA";
+// CryptoJS v3.1.2
+!function(r){var t=CryptoJS,e=t.lib,n=e.WordArray,o=e.Hasher,s=t.algo,a=[],i=[];!function(){function t(t){for(var e=r.sqrt(t),n=2;n<=e;n++)if(!(t%n))return!1;return!0}function e(r){return 4294967296*(r-(0|r))|0}for(var n=2,o=0;o<64;)t(n)&&(o<8&&(a[o]=e(r.pow(n,.5))),i[o]=e(r.pow(n,1/3)),o++),n++}();var h=[],c=s.SHA256=o.extend({_doReset:function(){this._hash=new n.init(a.slice(0))},_doProcessBlock:function(r,t){for(var e=this._hash.words,n=e[0],o=e[1],s=e[2],a=e[3],c=e[4],l=e[5],f=e[6],u=e[7],_=0;_<64;_++){if(_<16)h[_]=0|r[t+_];else{var v=h[_-15],d=(v<<25|v>>>7)^(v<<14|v>>>18)^v>>>3,H=h[_-2],p=(H<<15|H>>>17)^(H<<13|H>>>19)^H>>>10;h[_]=d+h[_-7]+p+h[_-16]}var w=n&o^n&s^o&s,y=(n<<30|n>>>2)^(n<<19|n>>>13)^(n<<10|n>>>22),g=u+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&l^~c&f)+i[_]+h[_];u=f,f=l,l=c,c=a+g|0,a=s,s=o,o=n,n=g+(y+w)|0}e[0]=e[0]+n|0,e[1]=e[1]+o|0,e[2]=e[2]+s|0,e[3]=e[3]+a|0,e[4]=e[4]+c|0,e[5]=e[5]+l|0,e[6]=e[6]+f|0,e[7]=e[7]+u|0},_doFinalize:function(){var t=this._data,e=t.words,n=8*this._nDataBytes,o=8*t.sigBytes;return e[o>>>5]|=128<<24-o%32,e[14+(o+64>>>9<<4)]=r.floor(n/4294967296),e[15+(o+64>>>9<<4)]=n,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var r=o.clone.call(this);return r._hash=this._hash.clone(),r}});t.SHA256=o._createHelper(c),t.HmacSHA256=o._createHmacHelper(c)}(Math);
+// asn1-1.0.14.js (c) 2013-2018 Kenji Urushima | kjur.github.com/jsrsasign/license
+"undefined"!=typeof KJUR&&KJUR||(KJUR={}),void 0!==KJUR.asn1&&KJUR.asn1||(KJUR.asn1={}),KJUR.asn1.ASN1Util=new function(){this.integerToByteHex=function(t){var e=t.toString(16);return e.length%2==1&&(e="0"+e),e},this.bigIntToMinTwosComplementsHex=function(t){var e=t.toString(16);if("-"!=e.substr(0,1))e.length%2==1?e="0"+e:e.match(/^[0-7]/)||(e="00"+e);else{var i=e.substr(1).length;i%2==1?i+=1:e.match(/^[0-7]/)||(i+=2);for(var n="",s=0;s15)throw"ASN.1 length too long to represent by 8x: n = "+t.toString(16);return(128+i).toString(16)+e},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},KJUR.asn1.DERAbstractString=function(t){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=utf8tohex(this.s).toLowerCase()},this.setStringHex=function(t){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t?this.setString(t):void 0!==t.str?this.setString(t.str):void 0!==t.hex&&this.setStringHex(t.hex))},YAHOO.lang.extend(KJUR.asn1.DERAbstractString,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractTime=function(t){KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);this.localDateToUTC=function(t){return utc=t.getTime()+6e4*t.getTimezoneOffset(),new Date(utc)},this.formatDate=function(t,e,i){var n=this.zeroPadding,s=this.localDateToUTC(t),r=String(s.getFullYear());"utc"==e&&(r=r.substr(2,2));var h=r+n(String(s.getMonth()+1),2)+n(String(s.getDate()),2)+n(String(s.getHours()),2)+n(String(s.getMinutes()),2)+n(String(s.getSeconds()),2);if(!0===i){var a=s.getMilliseconds();if(0!=a){var o=n(String(a),3);h=h+"."+(o=o.replace(/[0]+$/,""))}}return h+"Z"},this.zeroPadding=function(t,e){return t.length>=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,n,s,r){var h=new Date(Date.UTC(t,e-1,i,n,s,r,0));this.setByDate(h)},this.getFreshValueHex=function(){return this.hV}},YAHOO.lang.extend(KJUR.asn1.DERAbstractTime,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractStructured=function(t){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured,KJUR.asn1.ASN1Object),KJUR.asn1.DERBoolean=function(){KJUR.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},YAHOO.lang.extend(KJUR.asn1.DERBoolean,KJUR.asn1.ASN1Object),KJUR.asn1.DERInteger=function(t){KJUR.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new BigInteger(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},YAHOO.lang.extend(KJUR.asn1.DERInteger,KJUR.asn1.ASN1Object),KJUR.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=KJUR.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}KJUR.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7=2*u)break;if(g>=200)break;e.push(o),s=o,g++}return e},ASN1HEX.getNthChildIdx=function(t,r,n){return ASN1HEX.getChildIdx(t,r)[n]},ASN1HEX.getIdxbyList=function(t,r,n,e){var i,u,s=ASN1HEX;if(0==n.length){if(void 0!==e&&t.substr(r,2)!==e)throw"checking tag doesn't match: "+t.substr(r,2)+"!="+e;return r}return i=n.shift(),u=s.getChildIdx(t,r),s.getIdxbyList(t,u[i],n,e)},ASN1HEX.getTLVbyList=function(t,r,n,e){var i=ASN1HEX,u=i.getIdxbyList(t,r,n);if(void 0===u)throw"can't find nthList object";if(void 0!==e&&t.substr(u,2)!=e)throw"checking tag doesn't match: "+t.substr(u,2)+"!="+e;return i.getTLV(t,u)},ASN1HEX.getVbyList=function(t,r,n,e,i){var u,s,g=ASN1HEX;if(void 0===(u=g.getIdxbyList(t,r,n,e)))throw"can't find nthList object";return s=g.getV(t,u),!0===i&&(s=s.substr(2)),s},ASN1HEX.hextooidstr=function(t){var r=function(t,r){return t.length>=r?t:new Array(r-t.length+1).join("0")+t},n=[],e=t.substr(0,2),i=parseInt(e,16);n[0]=new String(Math.floor(i/40)),n[1]=new String(i%40);for(var u=t.substr(2),s=[],g=0;g0&&(f=f+"."+o.join(".")),f},ASN1HEX.dump=function(t,r,n,e){var i=ASN1HEX,u=i.getV,s=i.dump,g=i.getChildIdx,o=t;t instanceof KJUR.asn1.ASN1Object&&(o=t.getEncodedHex());var a=function(t,r){return t.length<=2*r?t:t.substr(0,r)+"..(total "+t.length/2+"bytes).."+t.substr(t.length-r,r)};void 0===r&&(r={ommit_long_octet:32}),void 0===n&&(n=0),void 0===e&&(e="");var f=r.ommit_long_octet;if("01"==o.substr(n,2))return"00"==(b=u(o,n))?e+"BOOLEAN FALSE\n":e+"BOOLEAN TRUE\n";if("02"==o.substr(n,2))return e+"INTEGER "+a(b=u(o,n),f)+"\n";if("03"==o.substr(n,2))return e+"BITSTRING "+a(b=u(o,n),f)+"\n";if("04"==o.substr(n,2)){var b=u(o,n);if(i.isASN1HEX(b)){var S=e+"OCTETSTRING, encapsulates\n";return S+=s(b,r,0,e+" ")}return e+"OCTETSTRING "+a(b,f)+"\n"}if("05"==o.substr(n,2))return e+"NULL\n";if("06"==o.substr(n,2)){var N=u(o,n),E=KJUR.asn1.ASN1Util.oidHexToInt(N),h=KJUR.asn1.x509.OID.oid2name(E),l=E.replace(/\./g," ");return""!=h?e+"ObjectIdentifier "+h+" ("+l+")\n":e+"ObjectIdentifier ("+l+")\n"}if("0c"==o.substr(n,2))return e+"UTF8String '"+hextoutf8(u(o,n))+"'\n";if("13"==o.substr(n,2))return e+"PrintableString '"+hextoutf8(u(o,n))+"'\n";if("14"==o.substr(n,2))return e+"TeletexString '"+hextoutf8(u(o,n))+"'\n";if("16"==o.substr(n,2))return e+"IA5String '"+hextoutf8(u(o,n))+"'\n";if("17"==o.substr(n,2))return e+"UTCTime "+hextoutf8(u(o,n))+"\n";if("18"==o.substr(n,2))return e+"GeneralizedTime "+hextoutf8(u(o,n))+"\n";if("30"==o.substr(n,2)){if("3000"==o.substr(n,4))return e+"SEQUENCE {}\n";S=e+"SEQUENCE\n";var d=r;if((2==(v=g(o,n)).length||3==v.length)&&"06"==o.substr(v[0],2)&&"04"==o.substr(v[v.length-1],2)){h=i.oidname(u(o,v[0]));var A=JSON.parse(JSON.stringify(r));A.x509ExtName=h,d=A}for(var c=0;co.length&&(o=n[r]);return(t=t.replace(o,"::")).slice(1,-1)}function hextoip(t){var e="malformed hex value";if(!t.match(/^([0-9A-Fa-f][0-9A-Fa-f]){1,}$/))throw e;if(8!=t.length)return 32==t.length?hextoipv6(t):t;try{return parseInt(t.substr(0,2),16)+"."+parseInt(t.substr(2,2),16)+"."+parseInt(t.substr(4,2),16)+"."+parseInt(t.substr(6,2),16)}catch(t){throw e}}function iptohex(t){var e="malformed IP address";if(!(t=t.toLowerCase(t)).match(/^[0-9.]+$/)){if(t.match(/^[0-9a-f:]+$/)&&-1!==t.indexOf(":"))return ipv6tohex(t);throw e}var r=t.split(".");if(4!==r.length)throw e;var n="";try{for(var o=0;o<4;o++){n+=("0"+parseInt(r[o]).toString(16)).slice(-2)}return n}catch(t){throw e}}function encodeURIComponentAll(t){for(var e=encodeURIComponent(t),r="",n=0;n"7"?"00"+t:t}function intarystrtohex(t){t=(t=(t=t.replace(/^\s*\[\s*/,"")).replace(/\s*\]\s*$/,"")).replace(/\s*/g,"");try{return t.split(/,/).map(function(t,e,r){var n=parseInt(t);if(n<0||255e.length&&(r=e.length);for(var n=0;nr)throw"key is too short for SigAlg: keylen="+e+","+s;for(var o="0001",a="00"+i,h="",n=r-o.length-a.length,p=0;p=0)return!1;if(r.compareTo(BigInteger.ONE)<0||r.compareTo(s)>=0)return!1;var a=r.modInverse(s),o=e.multiply(a).mod(s),u=t.multiply(a).mod(s);return n.multiply(o).add(i.multiply(u)).getX().toBigInteger().mod(s).equals(t)},this.serializeSig=function(e,t){var r=e.toByteArraySigned(),i=t.toByteArraySigned(),s=[];return s.push(2),s.push(r.length),(s=s.concat(r)).push(2),s.push(i.length),(s=s.concat(i)).unshift(s.length),s.unshift(48),s},this.parseSig=function(e){var t;if(48!=e[0])throw new Error("Signature not a valid DERSequence");if(2!=e[t=2])throw new Error("First element in signature must be a DERInteger");var r=e.slice(t+2,t+2+e[t+1]);if(2!=e[t+=2+e[t+1]])throw new Error("Second element in signature must be a DERInteger");var i=e.slice(t+2,t+2+e[t+1]);return t+=2+e[t+1],{r:BigInteger.fromByteArrayUnsigned(r),s:BigInteger.fromByteArrayUnsigned(i)}},this.parseSigCompact=function(e){if(65!==e.length)throw"Signature has the wrong length";var t=e[0]-27;if(t<0||t>7)throw"Invalid signature type";var r=this.ecparams.n;return{r:BigInteger.fromByteArrayUnsigned(e.slice(1,33)).mod(r),s:BigInteger.fromByteArrayUnsigned(e.slice(33,65)).mod(r),i:t}},this.readPKCS5PrvKeyHex=function(e){var t,r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{t=a(e,0,[2,0],"06"),r=a(e,0,[1],"04");try{i=a(e,0,[3,0],"03").substr(2)}catch(e){}}catch(e){throw"malformed PKCS#1/5 plain ECC private key"}if(this.curveName=n(t),void 0===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i),this.setPrivateKeyHex(r),this.isPublic=!1},this.readPKCS8PrvKeyHex=function(e){var t,r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{a(e,0,[1,0],"06"),t=a(e,0,[1,1],"06"),r=a(e,0,[2,0,1],"04");try{i=a(e,0,[2,0,2,0],"03").substr(2)}catch(e){}}catch(e){throw"malformed PKCS#8 plain ECC private key"}if(this.curveName=n(t),void 0===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i),this.setPrivateKeyHex(r),this.isPublic=!1},this.readPKCS8PubKeyHex=function(e){var t,r,i=ASN1HEX,s=KJUR.crypto.ECDSA.getName,n=i.getVbyList;if(!1===i.isASN1HEX(e))throw"not ASN.1 hex string";try{n(e,0,[0,0],"06"),t=n(e,0,[0,1],"06"),r=n(e,0,[1],"03").substr(2)}catch(e){throw"malformed PKCS#8 ECC public key"}if(this.curveName=s(t),null===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(r)},this.readCertPubKeyHex=function(e,t){5!==t&&(t=6);var r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{r=a(e,0,[0,t,0,1],"06"),i=a(e,0,[0,t,1],"03").substr(2)}catch(e){throw"malformed X.509 certificate ECC public key"}if(this.curveName=n(r),null===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i)},void 0!==e&&void 0!==e.curve&&(this.curveName=e.curve),void 0===this.curveName&&(this.curveName="secp256r1"),this.setNamedCurve(this.curveName),void 0!==e&&(void 0!==e.prv&&this.setPrivateKeyHex(e.prv),void 0!==e.pub&&this.setPublicKeyHex(e.pub))},KJUR.crypto.ECDSA.parseSigHex=function(e){var t=KJUR.crypto.ECDSA.parseSigHexInHexRS(e);return{r:new BigInteger(t.r,16),s:new BigInteger(t.s,16)}},KJUR.crypto.ECDSA.parseSigHexInHexRS=function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV;if("30"!=e.substr(0,2))throw"signature is not a ASN.1 sequence";var s=r(e,0);if(2!=s.length)throw"number of signature ASN.1 sequence elements seem wrong";var n=s[0],a=s[1];if("02"!=e.substr(n,2))throw"1st item of sequene of signature is not ASN.1 integer";if("02"!=e.substr(a,2))throw"2nd item of sequene of signature is not ASN.1 integer";return{r:i(e,n),s:i(e,a)}},KJUR.crypto.ECDSA.asn1SigToConcatSig=function(e){var t=KJUR.crypto.ECDSA.parseSigHexInHexRS(e),r=t.r,i=t.s;if("00"==r.substr(0,2)&&r.length%32==2&&(r=r.substr(2)),"00"==i.substr(0,2)&&i.length%32==2&&(i=i.substr(2)),r.length%32==30&&(r="00"+r),i.length%32==30&&(i="00"+i),r.length%32!=0)throw"unknown ECDSA sig r length error";if(i.length%32!=0)throw"unknown ECDSA sig s length error";return r+i},KJUR.crypto.ECDSA.concatSigToASN1Sig=function(e){if(e.length/2*8%128!=0)throw"unknown ECDSA concatinated r-s sig length error";var t=e.substr(0,e.length/2),r=e.substr(e.length/2);return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(t,r)},KJUR.crypto.ECDSA.hexRSSigToASN1Sig=function(e,t){var r=new BigInteger(e,16),i=new BigInteger(t,16);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r,i)},KJUR.crypto.ECDSA.biRSSigToASN1Sig=function(e,t){var r=KJUR.asn1,i=new r.DERInteger({bigint:e}),s=new r.DERInteger({bigint:t});return new r.DERSequence({array:[i,s]}).getEncodedHex()},KJUR.crypto.ECDSA.getName=function(e){return"2a8648ce3d030107"===e?"secp256r1":"2b8104000a"===e?"secp256k1":"2b81040022"===e?"secp384r1":-1!=="|secp256r1|NIST P-256|P-256|prime256v1|".indexOf(e)?"secp256r1":-1!=="|secp256k1|".indexOf(e)?"secp256k1":-1!=="|secp384r1|NIST P-384|P-384|".indexOf(e)?"secp384r1":null};
+// ecparam-1.0.0.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
+"undefined"!=typeof KJUR&&KJUR||(KJUR={}),void 0!==KJUR.crypto&&KJUR.crypto||(KJUR.crypto={}),KJUR.crypto.ECParameterDB=new function(){var F={},B={};function E(F){return new BigInteger(F,16)}this.getByName=function(E){var C=E;if(void 0!==B[C]&&(C=B[E]),void 0!==F[C])return F[C];throw"unregistered EC curve name: "+C},this.regist=function(C,D,A,e,r,t,c,a,i,p,o,s){F[C]={};var d=E(A),f=E(e),n=E(r),m=E(t),P=E(c),v=new ECCurveFp(d,f,n),y=v.decodePointHex("04"+a+i);F[C].name=C,F[C].keylen=D,F[C].curve=v,F[C].G=y,F[C].n=m,F[C].h=P,F[C].oid=o,F[C].info=s;for(var J=0;J=2*d)break}var v={};return v.keyhex=c.substr(0,2*n[e].keylen),v.ivhex=c.substr(2*n[e].keylen,2*n[e].ivlen),v},d=function(e,t,r,i){var o=CryptoJS.enc.Base64.parse(e),a=CryptoJS.enc.Hex.stringify(o);return(0,n[t].proc)(a,r,i)};return{version:"1.0.0",parsePKCS5PEM:function(e){return o(e)},getKeyAndUnusedIvByPasscodeAndIvsalt:function(e,t,r){return a(e,t,r)},decryptKeyB64:function(e,t,r,i){return d(e,t,r,i)},getDecryptedKeyHex:function(e,t){var r=o(e),i=(r.type,r.cipher),n=r.ivsalt,c=r.data,u=a(i,t,n).keyhex;return d(c,i,u,n)},getEncryptedPKCS5PEMFromPrvKeyHex:function(e,t,r,i,o){var d,c,u="";if(void 0!==i&&null!=i||(i="AES-256-CBC"),void 0===n[i])throw"KEYUTIL unsupported algorithm: "+i;if(void 0===o||null==o){var p=n[i].ivlen;o=(d=p,c=CryptoJS.lib.WordArray.random(d),CryptoJS.enc.Hex.stringify(c)).toUpperCase()}var v,s,f,E=a(i,r,o).keyhex;u="-----BEGIN "+e+" PRIVATE KEY-----\r\n";return u+="Proc-Type: 4,ENCRYPTED\r\n",u+="DEK-Info: "+i+","+o+"\r\n",u+="\r\n",u+=(v=t,s=E,f=o,(0,n[i].eproc)(v,s,f)).replace(/(.{64})/g,"$1\r\n"),u+="\r\n-----END "+e+" PRIVATE KEY-----\r\n"},parseHexOfEncryptedPKCS8:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={},o=r(e,0);if(2!=o.length)throw"malformed format: SEQUENCE(0).items != 2: "+o.length;n.ciphertext=i(e,o[1]);var a=r(e,o[0]);if(2!=a.length)throw"malformed format: SEQUENCE(0.0).items != 2: "+a.length;if("2a864886f70d01050d"!=i(e,a[0]))throw"this only supports pkcs5PBES2";var d=r(e,a[1]);if(2!=a.length)throw"malformed format: SEQUENCE(0.0.1).items != 2: "+d.length;var c=r(e,d[1]);if(2!=c.length)throw"malformed format: SEQUENCE(0.0.1.1).items != 2: "+c.length;if("2a864886f70d0307"!=i(e,c[0]))throw"this only supports TripleDES";n.encryptionSchemeAlg="TripleDES",n.encryptionSchemeIV=i(e,c[1]);var u=r(e,d[0]);if(2!=u.length)throw"malformed format: SEQUENCE(0.0.1.0).items != 2: "+u.length;if("2a864886f70d01050c"!=i(e,u[0]))throw"this only supports pkcs5PBKDF2";var p=r(e,u[1]);if(p.length<2)throw"malformed format: SEQUENCE(0.0.1.0.1).items < 2: "+p.length;n.pbkdf2Salt=i(e,p[0]);var v=i(e,p[1]);try{n.pbkdf2Iter=parseInt(v,16)}catch(e){throw"malformed format pbkdf2Iter: "+v}return n},getPBKDF2KeyHexFromParam:function(e,t){var r=CryptoJS.enc.Hex.parse(e.pbkdf2Salt),i=e.pbkdf2Iter,n=CryptoJS.PBKDF2(t,r,{keySize:6,iterations:i});return CryptoJS.enc.Hex.stringify(n)},_getPlainPKCS8HexFromEncryptedPKCS8PEM:function(e,t){var r=pemtohex(e,"ENCRYPTED PRIVATE KEY"),i=this.parseHexOfEncryptedPKCS8(r),n=KEYUTIL.getPBKDF2KeyHexFromParam(i,t),o={};o.ciphertext=CryptoJS.enc.Hex.parse(i.ciphertext);var a=CryptoJS.enc.Hex.parse(n),d=CryptoJS.enc.Hex.parse(i.encryptionSchemeIV),c=CryptoJS.TripleDES.decrypt(o,a,{iv:d});return CryptoJS.enc.Hex.stringify(c)},getKeyFromEncryptedPKCS8PEM:function(e,t){var r=this._getPlainPKCS8HexFromEncryptedPKCS8PEM(e,t);return this.getKeyFromPlainPrivatePKCS8Hex(r)},parsePlainPrivatePKCS8Hex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={};if(n.algparam=null,"30"!=e.substr(0,2))throw"malformed plain PKCS8 private key(code:001)";var o=r(e,0);if(3!=o.length)throw"malformed plain PKCS8 private key(code:002)";if("30"!=e.substr(o[1],2))throw"malformed PKCS8 private key(code:003)";var a=r(e,o[1]);if(2!=a.length)throw"malformed PKCS8 private key(code:004)";if("06"!=e.substr(a[0],2))throw"malformed PKCS8 private key(code:005)";if(n.algoid=i(e,a[0]),"06"==e.substr(a[1],2)&&(n.algparam=i(e,a[1])),"04"!=e.substr(o[2],2))throw"malformed PKCS8 private key(code:006)";return n.keyidx=t.getVidx(e,o[2]),n},getKeyFromPlainPrivatePKCS8PEM:function(e){var t=pemtohex(e,"PRIVATE KEY");return this.getKeyFromPlainPrivatePKCS8Hex(t)},getKeyFromPlainPrivatePKCS8Hex:function(e){var t,r=this.parsePlainPrivatePKCS8Hex(e);if("2a864886f70d010101"==r.algoid)t=new RSAKey;else if("2a8648ce380401"==r.algoid)t=new KJUR.crypto.DSA;else{if("2a8648ce3d0201"!=r.algoid)throw"unsupported private key algorithm";t=new KJUR.crypto.ECDSA}return t.readPKCS8PrvKeyHex(e),t},_getKeyFromPublicPKCS8Hex:function(e){var t,r=ASN1HEX.getVbyList(e,0,[0,0],"06");if("2a864886f70d010101"===r)t=new RSAKey;else if("2a8648ce380401"===r)t=new KJUR.crypto.DSA;else{if("2a8648ce3d0201"!==r)throw"unsupported PKCS#8 public key hex";t=new KJUR.crypto.ECDSA}return t.readPKCS8PubKeyHex(e),t},parsePublicRawRSAKeyHex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={};if("30"!=e.substr(0,2))throw"malformed RSA key(code:001)";var o=r(e,0);if(2!=o.length)throw"malformed RSA key(code:002)";if("02"!=e.substr(o[0],2))throw"malformed RSA key(code:003)";if(n.n=i(e,o[0]),"02"!=e.substr(o[1],2))throw"malformed RSA key(code:004)";return n.e=i(e,o[1]),n},parsePublicPKCS8Hex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={algparam:null},o=r(e,0);if(2!=o.length)throw"outer DERSequence shall have 2 elements: "+o.length;var a=o[0];if("30"!=e.substr(a,2))throw"malformed PKCS8 public key(code:001)";var d=r(e,a);if(2!=d.length)throw"malformed PKCS8 public key(code:002)";if("06"!=e.substr(d[0],2))throw"malformed PKCS8 public key(code:003)";if(n.algoid=i(e,d[0]),"06"==e.substr(d[1],2)?n.algparam=i(e,d[1]):"30"==e.substr(d[1],2)&&(n.algparam={},n.algparam.p=t.getVbyList(e,d[1],[0],"02"),n.algparam.q=t.getVbyList(e,d[1],[1],"02"),n.algparam.g=t.getVbyList(e,d[1],[2],"02")),"03"!=e.substr(o[1],2))throw"malformed PKCS8 public key(code:004)";return n.key=i(e,o[1]).substr(2),n}}}();KEYUTIL.getKey=function(e,t,r){var i=(x=ASN1HEX).getChildIdx,n=(x.getV,x.getVbyList),o=KJUR.crypto,a=o.ECDSA,d=o.DSA,c=RSAKey,u=pemtohex,p=KEYUTIL;if(void 0!==c&&e instanceof c)return e;if(void 0!==a&&e instanceof a)return e;if(void 0!==d&&e instanceof d)return e;if(void 0!==e.curve&&void 0!==e.xy&&void 0===e.d)return new a({pub:e.xy,curve:e.curve});if(void 0!==e.curve&&void 0!==e.d)return new a({prv:e.d,curve:e.curve});if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0===e.d)return(A=new c).setPublic(e.n,e.e),A;if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0!==e.p&&void 0!==e.q&&void 0!==e.dp&&void 0!==e.dq&&void 0!==e.co&&void 0===e.qi)return(A=new c).setPrivateEx(e.n,e.e,e.d,e.p,e.q,e.dp,e.dq,e.co),A;if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0===e.p)return(A=new c).setPrivate(e.n,e.e,e.d),A;if(void 0!==e.p&&void 0!==e.q&&void 0!==e.g&&void 0!==e.y&&void 0===e.x)return(A=new d).setPublic(e.p,e.q,e.g,e.y),A;if(void 0!==e.p&&void 0!==e.q&&void 0!==e.g&&void 0!==e.y&&void 0!==e.x)return(A=new d).setPrivate(e.p,e.q,e.g,e.y,e.x),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0===e.d)return(A=new c).setPublic(b64utohex(e.n),b64utohex(e.e)),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0!==e.p&&void 0!==e.q&&void 0!==e.dp&&void 0!==e.dq&&void 0!==e.qi)return(A=new c).setPrivateEx(b64utohex(e.n),b64utohex(e.e),b64utohex(e.d),b64utohex(e.p),b64utohex(e.q),b64utohex(e.dp),b64utohex(e.dq),b64utohex(e.qi)),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d)return(A=new c).setPrivate(b64utohex(e.n),b64utohex(e.e),b64utohex(e.d)),A;if("EC"===e.kty&&void 0!==e.crv&&void 0!==e.x&&void 0!==e.y&&void 0===e.d){var v=(R=new a({curve:e.crv})).ecparams.keylen/4,s="04"+("0000000000"+b64utohex(e.x)).slice(-v)+("0000000000"+b64utohex(e.y)).slice(-v);return R.setPublicKeyHex(s),R}if("EC"===e.kty&&void 0!==e.crv&&void 0!==e.x&&void 0!==e.y&&void 0!==e.d){v=(R=new a({curve:e.crv})).ecparams.keylen/4,s="04"+("0000000000"+b64utohex(e.x)).slice(-v)+("0000000000"+b64utohex(e.y)).slice(-v);var f=("0000000000"+b64utohex(e.d)).slice(-v);return R.setPublicKeyHex(s),R.setPrivateKeyHex(f),R}if("pkcs5prv"===r){var E,y=e,x=ASN1HEX;if(9===(E=i(y,0)).length)(A=new c).readPKCS5PrvKeyHex(y);else if(6===E.length)(A=new d).readPKCS5PrvKeyHex(y);else{if(!(E.length>2&&"04"===y.substr(E[1],2)))throw"unsupported PKCS#1/5 hexadecimal key";(A=new a).readPKCS5PrvKeyHex(y)}return A}if("pkcs8prv"===r)return A=p.getKeyFromPlainPrivatePKCS8Hex(e);if("pkcs8pub"===r)return p._getKeyFromPublicPKCS8Hex(e);if("x509pub"===r)return X509.getPublicKeyFromCertHex(e);if(-1!=e.indexOf("-END CERTIFICATE-",0)||-1!=e.indexOf("-END X509 CERTIFICATE-",0)||-1!=e.indexOf("-END TRUSTED CERTIFICATE-",0))return X509.getPublicKeyFromCertPEM(e);if(-1!=e.indexOf("-END PUBLIC KEY-")){var P=pemtohex(e,"PUBLIC KEY");return p._getKeyFromPublicPKCS8Hex(P)}if(-1!=e.indexOf("-END RSA PRIVATE KEY-")&&-1==e.indexOf("4,ENCRYPTED")){var S=u(e,"RSA PRIVATE KEY");return p.getKey(S,null,"pkcs5prv")}if(-1!=e.indexOf("-END DSA PRIVATE KEY-")&&-1==e.indexOf("4,ENCRYPTED")){var l=n(I=u(e,"DSA PRIVATE KEY"),0,[1],"02"),g=n(I,0,[2],"02"),K=n(I,0,[3],"02"),C=n(I,0,[4],"02"),h=n(I,0,[5],"02");return(A=new d).setPrivate(new BigInteger(l,16),new BigInteger(g,16),new BigInteger(K,16),new BigInteger(C,16),new BigInteger(h,16)),A}if(-1!=e.indexOf("-END PRIVATE KEY-"))return p.getKeyFromPlainPrivatePKCS8PEM(e);if(-1!=e.indexOf("-END RSA PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var m=p.getDecryptedKeyHex(e,t),b=new RSAKey;return b.readPKCS5PrvKeyHex(m),b}if(-1!=e.indexOf("-END EC PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var R,A=n(I=p.getDecryptedKeyHex(e,t),0,[1],"04"),H=n(I,0,[2,0],"06"),w=n(I,0,[3,0],"03").substr(2);if(void 0===KJUR.crypto.OID.oidhex2name[H])throw"undefined OID(hex) in KJUR.crypto.OID: "+H;return(R=new a({curve:KJUR.crypto.OID.oidhex2name[H]})).setPublicKeyHex(w),R.setPrivateKeyHex(A),R.isPublic=!1,R}if(-1!=e.indexOf("-END DSA PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var I;l=n(I=p.getDecryptedKeyHex(e,t),0,[1],"02"),g=n(I,0,[2],"02"),K=n(I,0,[3],"02"),C=n(I,0,[4],"02"),h=n(I,0,[5],"02");return(A=new d).setPrivate(new BigInteger(l,16),new BigInteger(g,16),new BigInteger(K,16),new BigInteger(C,16),new BigInteger(h,16)),A}if(-1!=e.indexOf("-END ENCRYPTED PRIVATE KEY-"))return p.getKeyFromEncryptedPKCS8PEM(e,t);throw"not supported argument"},KEYUTIL.generateKeypair=function(e,t){if("RSA"==e){var r=t;(a=new RSAKey).generate(r,"10001"),a.isPrivate=!0,a.isPublic=!0;var i=new RSAKey,n=a.n.toString(16),o=a.e.toString(16);return i.setPublic(n,o),i.isPrivate=!1,i.isPublic=!0,(d={}).prvKeyObj=a,d.pubKeyObj=i,d}if("EC"==e){var a,d,c=t,u=new KJUR.crypto.ECDSA({curve:c}).generateKeyPairHex();return(a=new KJUR.crypto.ECDSA({curve:c})).setPublicKeyHex(u.ecpubhex),a.setPrivateKeyHex(u.ecprvhex),a.isPrivate=!0,a.isPublic=!1,(i=new KJUR.crypto.ECDSA({curve:c})).setPublicKeyHex(u.ecpubhex),i.isPrivate=!1,i.isPublic=!0,(d={}).prvKeyObj=a,d.pubKeyObj=i,d}throw"unknown algorithm: "+e},KEYUTIL.getPEM=function(e,t,r,i,n,o){var a=KJUR,d=a.asn1,c=d.DERObjectIdentifier,u=d.DERInteger,p=d.ASN1Util.newObject,v=d.x509.SubjectPublicKeyInfo,s=a.crypto,f=s.DSA,E=s.ECDSA,y=RSAKey;function x(e){return p({seq:[{int:0},{int:{bigint:e.n}},{int:e.e},{int:{bigint:e.d}},{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.dmp1}},{int:{bigint:e.dmq1}},{int:{bigint:e.coeff}}]})}function P(e){return p({seq:[{int:1},{octstr:{hex:e.prvKeyHex}},{tag:["a0",!0,{oid:{name:e.curveName}}]},{tag:["a1",!0,{bitstr:{hex:"00"+e.pubKeyHex}}]}]})}function S(e){return p({seq:[{int:0},{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.g}},{int:{bigint:e.y}},{int:{bigint:e.x}}]})}if((void 0!==y&&e instanceof y||void 0!==f&&e instanceof f||void 0!==E&&e instanceof E)&&1==e.isPublic&&(void 0===t||"PKCS8PUB"==t)){var l=new v(e).getEncodedHex();return hextopem(l,"PUBLIC KEY")}if("PKCS1PRV"==t&&void 0!==y&&e instanceof y&&(void 0===r||null==r)&&1==e.isPrivate){l=x(e).getEncodedHex();return hextopem(l,"RSA PRIVATE KEY")}if("PKCS1PRV"==t&&void 0!==E&&e instanceof E&&(void 0===r||null==r)&&1==e.isPrivate){var g=new c({name:e.curveName}).getEncodedHex(),K=P(e).getEncodedHex(),C="";return C+=hextopem(g,"EC PARAMETERS"),C+=hextopem(K,"EC PRIVATE KEY")}if("PKCS1PRV"==t&&void 0!==f&&e instanceof f&&(void 0===r||null==r)&&1==e.isPrivate){l=S(e).getEncodedHex();return hextopem(l,"DSA PRIVATE KEY")}if("PKCS5PRV"==t&&void 0!==y&&e instanceof y&&void 0!==r&&null!=r&&1==e.isPrivate){l=x(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("RSA",l,r,i,o)}if("PKCS5PRV"==t&&void 0!==E&&e instanceof E&&void 0!==r&&null!=r&&1==e.isPrivate){l=P(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("EC",l,r,i,o)}if("PKCS5PRV"==t&&void 0!==f&&e instanceof f&&void 0!==r&&null!=r&&1==e.isPrivate){l=S(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("DSA",l,r,i,o)}var h=function(e,t){var r=m(e,t);return new p({seq:[{seq:[{oid:{name:"pkcs5PBES2"}},{seq:[{seq:[{oid:{name:"pkcs5PBKDF2"}},{seq:[{octstr:{hex:r.pbkdf2Salt}},{int:r.pbkdf2Iter}]}]},{seq:[{oid:{name:"des-EDE3-CBC"}},{octstr:{hex:r.encryptionSchemeIV}}]}]}]},{octstr:{hex:r.ciphertext}}]}).getEncodedHex()},m=function(e,t){var r=CryptoJS.lib.WordArray.random(8),i=CryptoJS.lib.WordArray.random(8),n=CryptoJS.PBKDF2(t,r,{keySize:6,iterations:100}),o=CryptoJS.enc.Hex.parse(e),a=CryptoJS.TripleDES.encrypt(o,n,{iv:i})+"",d={};return d.ciphertext=a,d.pbkdf2Salt=CryptoJS.enc.Hex.stringify(r),d.pbkdf2Iter=100,d.encryptionSchemeAlg="DES-EDE3-CBC",d.encryptionSchemeIV=CryptoJS.enc.Hex.stringify(i),d};if("PKCS8PRV"==t&&void 0!=y&&e instanceof y&&1==e.isPrivate){var b=x(e).getEncodedHex();l=p({seq:[{int:0},{seq:[{oid:{name:"rsaEncryption"}},{null:!0}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}if("PKCS8PRV"==t&&void 0!==E&&e instanceof E&&1==e.isPrivate){b=new p({seq:[{int:1},{octstr:{hex:e.prvKeyHex}},{tag:["a1",!0,{bitstr:{hex:"00"+e.pubKeyHex}}]}]}).getEncodedHex(),l=p({seq:[{int:0},{seq:[{oid:{name:"ecPublicKey"}},{oid:{name:e.curveName}}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}if("PKCS8PRV"==t&&void 0!==f&&e instanceof f&&1==e.isPrivate){b=new u({bigint:e.x}).getEncodedHex(),l=p({seq:[{int:0},{seq:[{oid:{name:"dsa"}},{seq:[{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.g}}]}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}throw"unsupported object nor format"},KEYUTIL.getKeyFromCSRPEM=function(e){var t=pemtohex(e,"CERTIFICATE REQUEST");return KEYUTIL.getKeyFromCSRHex(t)},KEYUTIL.getKeyFromCSRHex=function(e){var t=KEYUTIL.parseCSRHex(e);return KEYUTIL.getKey(t.p8pubkeyhex,null,"pkcs8pub")},KEYUTIL.parseCSRHex=function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getTLV,n={},o=e;if("30"!=o.substr(0,2))throw"malformed CSR(code:001)";var a=r(o,0);if(a.length<1)throw"malformed CSR(code:002)";if("30"!=o.substr(a[0],2))throw"malformed CSR(code:003)";var d=r(o,a[0]);if(d.length<3)throw"malformed CSR(code:004)";return n.p8pubkeyhex=i(o,d[2]),n},KEYUTIL.getJWKFromKey=function(e){var t={};if(e instanceof RSAKey&&e.isPrivate)return t.kty="RSA",t.n=hextob64u(e.n.toString(16)),t.e=hextob64u(e.e.toString(16)),t.d=hextob64u(e.d.toString(16)),t.p=hextob64u(e.p.toString(16)),t.q=hextob64u(e.q.toString(16)),t.dp=hextob64u(e.dmp1.toString(16)),t.dq=hextob64u(e.dmq1.toString(16)),t.qi=hextob64u(e.coeff.toString(16)),t;if(e instanceof RSAKey&&e.isPublic)return t.kty="RSA",t.n=hextob64u(e.n.toString(16)),t.e=hextob64u(e.e.toString(16)),t;if(e instanceof KJUR.crypto.ECDSA&&e.isPrivate){if("P-256"!==(i=e.getShortNISTPCurveName())&&"P-384"!==i)throw"unsupported curve name for JWT: "+i;var r=e.getPublicKeyXYHex();return t.kty="EC",t.crv=i,t.x=hextob64u(r.x),t.y=hextob64u(r.y),t.d=hextob64u(e.prvKeyHex),t}if(e instanceof KJUR.crypto.ECDSA&&e.isPublic){var i;if("P-256"!==(i=e.getShortNISTPCurveName())&&"P-384"!==i)throw"unsupported curve name for JWT: "+i;r=e.getPublicKeyXYHex();return t.kty="EC",t.crv=i,t.x=hextob64u(r.x),t.y=hextob64u(r.y),t}throw"not supported key object"};
+// discuss at: http://locutus.io/php/pack/
+function pack(r){for(var e,o,n,a,t,g,h,i,f,c,s,w,C,l,d,p,m,k,u,S,b,y,E=0,W=1,T="",v="",A=0,M=[];Ev.length)throw new Error("Warning: pack() Type "+e+": not enough characters in string");for(A=0;A=o||void 0===v[A+1]?n+="0":n+=v[A+1],"h"===e&&(n=n[1]+n[0]),T+=String.fromCharCode(parseInt(n,16));W++;break;case"c":case"C":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;Aarguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),W++;break;case"n":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),T+=String.fromCharCode(255&arguments[W]),W++;break;case"i":case"I":case"l":case"L":case"V":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),T+=String.fromCharCode(arguments[W]>>16&255),T+=String.fromCharCode(arguments[W]>>24&255),W++;break;case"N":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>24&255),T+=String.fromCharCode(arguments[W]>>16&255),T+=String.fromCharCode(arguments[W]>>8&255),T+=String.fromCharCode(255&arguments[W]),W++;break;case"f":case"d":if(a=23,t=8,"d"===e&&(a=52,t=11),"*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A0&&b;--m)C[++b]=((m*=2)>=1)-0;for(b=-1;++b=i&&s<=f?b+1:h+1-(s=i-1)))+1]){if(!(u=C[k]))for(S=k+2;!u&&S=0;(C[S]=!C[S]-0)&&(u=0));}for(b=b-2<0?-1:b-3;++b=i&&s<=f?++b:s>=1;for(d=0,S=0,b=(y=(l?"1":"0")+y+C.slice(b,b+a).join("")).length,M=[];b;)d+=(1<T.length)for(g=o-T.length,A=0;At.json()).then(t=>{t.error?e(null,t.error):(t.params||(t=t.result),e(t))})}balanceFormatter(t){return(t/1e6).toFixed(6)+(this.tokenPrefix?" "+this.tokenPrefix:"")}fetchBalance(t,e){this.request("fetch-balance",(t,r)=>{t&&(t.balance=this.balanceFormatter(t.received-t.spent),t.transaction_count=t.count_received+t.count_spent),e(t,r)},{address:t})}fetchHistory(t,e){this.request("fetch-history",(t,r)=>{if(t){t=t.reverse();for(let e=0;e{t&&((t=t.transaction).value=this.balanceFormatter(t.value)),e(t,r)},{hash:t})}intToHexHandler(t,e,r,n){return this.binToHex(pack(t,e))+(r?this.binToHex(pack(r,n)):"")}intToHex(t){return t<250?this.intToHexHandler("C",t):t<65536?this.intToHexHandler("C",250,"v",t):t<4294967296?this.intToHexHandler("C",251,"V",t):this.intToHexHandler("C",252,"@",t)}strToHex(t){let e="";for(let r=0;r{this.apiUrl="http://139.162.42.43:9999",n.count_spent++,this.createTxHandler(t,e,r,n.count_spent,a,i,s,h)})}}createTxHandler(t,e,r,n,a,i,s,o){n=n.toString();const h=t.substr(2)+this.intToHex(e)+this.intToHex(r)+this.intToHex(n)+"00",c=new KJUR.crypto.Signature({alg:"SHA256withECDSA"});c.init({d:s,curve:"secp256k1"}),c.updateHex(h);const l=c.sign();this.request("mhc_send",(t,e)=>{o(t,e)},{to:t,value:e,fee:r,nonce:n,data:a,pubkey:i,sign:l})}}const metahash=new MetaHash;
+
+// Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+if(void 0===YAHOO)var YAHOO={};YAHOO.lang={extend:function(t,o,e){if(!o||!t)throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included.");var r=function(){};if(r.prototype=o.prototype,t.prototype=new r,t.prototype.constructor=t,t.superclass=o.prototype,o.prototype.constructor==Object.prototype.constructor&&(o.prototype.constructor=o),e){var n;for(n in e)t.prototype[n]=e[n];var p=function(){},c=["toString","valueOf"];try{/MSIE/.test(navigator.userAgent)&&(p=function(t,o){for(n=0;n>>2]>>>24-s%4*8&255;n[r+s>>>2]|=o<<24-(r+s)%4*8}else for(s=0;s>>2]=i[s>>>2];return this.sigBytes+=e,this},clamp:function(){var n=this.words,i=this.sigBytes;n[i>>>2]&=4294967295<<32-i%4*8,n.length=t.ceil(i/4)},clone:function(){var t=e.clone.call(this);return t.words=this.words.slice(0),t},random:function(n){for(var i=[],r=0;r>>2]>>>24-e%4*8&255;r.push((s>>>4).toString(16)),r.push((15&s).toString(16))}return r.join("")},parse:function(t){for(var n=t.length,i=[],r=0;r>>3]|=parseInt(t.substr(r,2),16)<<24-r%8*4;return new s.init(i,n/2)}},c=o.Latin1={stringify:function(t){for(var n=t.words,i=t.sigBytes,r=[],e=0;e>>2]>>>24-e%4*8&255;r.push(String.fromCharCode(s))}return r.join("")},parse:function(t){for(var n=t.length,i=[],r=0;r>>2]|=(255&t.charCodeAt(r))<<24-r%4*8;return new s.init(i,n)}},u=o.Utf8={stringify:function(t){try{return decodeURIComponent(escape(c.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return c.parse(unescape(encodeURIComponent(t)))}},f=r.BufferedBlockAlgorithm=e.extend({reset:function(){this._data=new s.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=u.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(n){var i=this._data,r=i.words,e=i.sigBytes,o=this.blockSize,a=e/(4*o),c=(a=n?t.ceil(a):t.max((0|a)-this._minBufferSize,0))*o,u=t.min(4*c,e);if(c){for(var f=0;f=0;){var s=i*this[t++]+r[o]+n;n=Math.floor(s/67108864),r[o++]=67108863&s}return n}function am2(t,i,r,o,n,e){for(var s=32767&i,h=i>>15;--e>=0;){var p=32767&this[t],a=this[t++]>>15,f=h*p+a*s;n=((p=s*p+((32767&f)<<15)+r[o]+(1073741823&n))>>>30)+(f>>>15)+h*a+(n>>>30),r[o++]=1073741823&p}return n}function am3(t,i,r,o,n,e){for(var s=16383&i,h=i>>14;--e>=0;){var p=16383&this[t],a=this[t++]>>14,f=h*p+a*s;n=((p=s*p+((16383&f)<<14)+r[o]+n)>>28)+(f>>14)+h*a,r[o++]=268435455&p}return n}j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28),BigInteger.prototype.DB=dbits,BigInteger.prototype.DM=(1<=0;--i)t[i]=this[i];t.t=this.t,t.s=this.s}function bnpFromInt(t){this.t=1,this.s=t<0?-1:0,t>0?this[0]=t:t<-1?this[0]=t+this.DV:this.t=0}function nbv(t){var i=nbi();return i.fromInt(t),i}function bnpFromString(t,i){var r;if(16==i)r=4;else if(8==i)r=3;else if(256==i)r=8;else if(2==i)r=1;else if(32==i)r=5;else{if(4!=i)return void this.fromRadix(t,i);r=2}this.t=0,this.s=0;for(var o=t.length,n=!1,e=0;--o>=0;){var s=8==r?255&t[o]:intAt(t,o);s<0?"-"==t.charAt(o)&&(n=!0):(n=!1,0==e?this[this.t++]=s:e+r>this.DB?(this[this.t-1]|=(s&(1<>this.DB-e):this[this.t-1]|=s<=this.DB&&(e-=this.DB))}8==r&&0!=(128&t[0])&&(this.s=-1,e>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==t;)--this.t}function bnToString(t){if(this.s<0)return"-"+this.negate().toString(t);var i;if(16==t)i=4;else if(8==t)i=3;else if(2==t)i=1;else if(32==t)i=5;else{if(4!=t)return this.toRadix(t);i=2}var r,o=(1<0)for(h>h)>0&&(n=!0,e=int2char(r));s>=0;)h>(h+=this.DB-i)):(r=this[s]>>(h-=i)&o,h<=0&&(h+=this.DB,--s)),r>0&&(n=!0),n&&(e+=int2char(r));return n?e:"0"}function bnNegate(){var t=nbi();return BigInteger.ZERO.subTo(this,t),t}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(t){var i=this.s-t.s;if(0!=i)return i;var r=this.t;if(0!=(i=r-t.t))return this.s<0?-i:i;for(;--r>=0;)if(0!=(i=this[r]-t[r]))return i;return 0}function nbits(t){var i,r=1;return 0!=(i=t>>>16)&&(t=i,r+=16),0!=(i=t>>8)&&(t=i,r+=8),0!=(i=t>>4)&&(t=i,r+=4),0!=(i=t>>2)&&(t=i,r+=2),0!=(i=t>>1)&&(t=i,r+=1),r}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(t,i){var r;for(r=this.t-1;r>=0;--r)i[r+t]=this[r];for(r=t-1;r>=0;--r)i[r]=0;i.t=this.t+t,i.s=this.s}function bnpDRShiftTo(t,i){for(var r=t;r=0;--r)i[r+s+1]=this[r]>>n|h,h=(this[r]&e)<=0;--r)i[r]=0;i[s]=h,i.t=this.t+s+1,i.s=this.s,i.clamp()}function bnpRShiftTo(t,i){i.s=this.s;var r=Math.floor(t/this.DB);if(r>=this.t)i.t=0;else{var o=t%this.DB,n=this.DB-o,e=(1<>o;for(var s=r+1;s>o;o>0&&(i[this.t-r-1]|=(this.s&e)<>=this.DB;if(t.t>=this.DB;o+=this.s}else{for(o+=this.s;r>=this.DB;o-=t.s}i.s=o<0?-1:0,o<-1?i[r++]=this.DV+o:o>0&&(i[r++]=o),i.t=r,i.clamp()}function bnpMultiplyTo(t,i){var r=this.abs(),o=t.abs(),n=r.t;for(i.t=n+o.t;--n>=0;)i[n]=0;for(n=0;n=0;)t[r]=0;for(r=0;r=i.DV&&(t[r+i.t]-=i.DV,t[r+i.t+1]=1)}t.t>0&&(t[t.t-1]+=i.am(r,i[r],t,2*r,0,1)),t.s=0,t.clamp()}function bnpDivRemTo(t,i,r){var o=t.abs();if(!(o.t<=0)){var n=this.abs();if(n.t0?(o.lShiftTo(p,e),n.lShiftTo(p,r)):(o.copyTo(e),n.copyTo(r));var a=e.t,f=e[a-1];if(0!=f){var u=f*(1<1?e[a-2]>>this.F2:0),g=this.FV/u,m=(1<=0&&(r[r.t++]=1,r.subTo(l,r)),BigInteger.ONE.dlShiftTo(a,l),l.subTo(e,e);e.t=0;){var T=r[--v]==f?this.DM:Math.floor(r[v]*g+(r[v-1]+c)*m);if((r[v]+=e.am(0,T,r,b,0,a))0&&r.rShiftTo(p,r),s<0&&BigInteger.ZERO.subTo(r,r)}}}function bnMod(t){var i=nbi();return this.abs().divRemTo(t,null,i),this.s<0&&i.compareTo(BigInteger.ZERO)>0&&t.subTo(i,i),i}function Classic(t){this.m=t}function cConvert(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function cRevert(t){return t}function cReduce(t){t.divRemTo(this.m,null,t)}function cMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function cSqrTo(t,i){t.squareTo(i),this.reduce(i)}function bnpInvDigit(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var i=3&t;return(i=(i=(i=(i=i*(2-(15&t)*i)&15)*(2-(255&t)*i)&255)*(2-((65535&t)*i&65535))&65535)*(2-t*i%this.DV)%this.DV)>0?this.DV-i:-i}function Montgomery(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(i,i),i}function montRevert(t){var i=nbi();return t.copyTo(i),this.reduce(i),i}function montReduce(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var i=0;i>15)*this.mpl&this.um)<<15)&t.DM;for(t[r=i+this.m.t]+=this.m.am(0,o,t,i,0,this.m.t);t[r]>=t.DV;)t[r]-=t.DV,t[++r]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function montSqrTo(t,i){t.squareTo(i),this.reduce(i)}function montMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(t,i){if(t>4294967295||t<1)return BigInteger.ONE;var r=nbi(),o=nbi(),n=i.convert(this),e=nbits(t)-1;for(n.copyTo(r);--e>=0;)if(i.sqrTo(r,o),(t&1<0)i.mulTo(o,n,r);else{var s=r;r=o,o=s}return i.revert(r)}function bnModPowInt(t,i){var r;return r=t<256||i.isEven()?new Classic(i):new Montgomery(i),this.exp(t,r)}Classic.prototype.convert=cConvert,Classic.prototype.revert=cRevert,Classic.prototype.reduce=cReduce,Classic.prototype.mulTo=cMulTo,Classic.prototype.sqrTo=cSqrTo,Montgomery.prototype.convert=montConvert,Montgomery.prototype.revert=montRevert,Montgomery.prototype.reduce=montReduce,Montgomery.prototype.mulTo=montMulTo,Montgomery.prototype.sqrTo=montSqrTo,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,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,BigInteger.ZERO=nbv(0),BigInteger.ONE=nbv(1);
+// (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+function bnClone(){var t=nbi();return this.copyTo(t),t}function bnIntValue(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(t){return Math.floor(Math.LN2*this.DB/Math.log(t))}function bnSigNum(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function bnpToRadix(t){if(null==t&&(t=10),0==this.signum()||t<2||t>36)return"0";var i=this.chunkSize(t),r=Math.pow(t,i),e=nbv(r),n=nbi(),o=nbi(),s="";for(this.divRemTo(e,n,o);n.signum()>0;)s=(r+o.intValue()).toString(t).substr(1)+s,n.divRemTo(e,n,o);return o.intValue().toString(t)+s}function bnpFromRadix(t,i){this.fromInt(0),null==i&&(i=10);for(var r=this.chunkSize(i),e=Math.pow(i,r),n=!1,o=0,s=0,h=0;h=r&&(this.dMultiply(e),this.dAddOffset(s,0),o=0,s=0))}o>0&&(this.dMultiply(Math.pow(i,o)),this.dAddOffset(s,0)),n&&BigInteger.ZERO.subTo(this,this)}function bnpFromNumber(t,i,r){if("number"==typeof i)if(t<2)this.fromInt(1);else for(this.fromNumber(t,r),this.testBit(t-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(t-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(i);)this.dAddOffset(2,0),this.bitLength()>t&&this.subTo(BigInteger.ONE.shiftLeft(t-1),this);else{var e=new Array,n=7&t;e.length=1+(t>>3),i.nextBytes(e),n>0?e[0]&=(1<0)for(e>e)!=(this.s&this.DM)>>e&&(i[n++]=r|this.s<=0;)e<8?(r=(this[t]&(1<>(e+=this.DB-8)):(r=this[t]>>(e-=8)&255,e<=0&&(e+=this.DB,--t)),0!=(128&r)&&(r|=-256),0==n&&(128&this.s)!=(128&r)&&++n,(n>0||r!=this.s)&&(i[n++]=r);return i}function bnEquals(t){return 0==this.compareTo(t)}function bnMin(t){return this.compareTo(t)<0?this:t}function bnMax(t){return this.compareTo(t)>0?this:t}function bnpBitwiseTo(t,i,r){var e,n,o=Math.min(t.t,this.t);for(e=0;e>=16,i+=16),0==(255&t)&&(t>>=8,i+=8),0==(15&t)&&(t>>=4,i+=4),0==(3&t)&&(t>>=2,i+=2),0==(1&t)&&++i,i}function bnGetLowestSetBit(){for(var t=0;t=this.t?0!=this.s:0!=(this[i]&1<>=this.DB;if(t.t>=this.DB;e+=this.s}else{for(e+=this.s;r>=this.DB;e+=t.s}i.s=e<0?-1:0,e>0?i[r++]=e:e<-1&&(i[r++]=this.DV+e),i.t=r,i.clamp()}function bnAdd(t){var i=nbi();return this.addTo(t,i),i}function bnSubtract(t){var i=nbi();return this.subTo(t,i),i}function bnMultiply(t){var i=nbi();return this.multiplyTo(t,i),i}function bnSquare(){var t=nbi();return this.squareTo(t),t}function bnDivide(t){var i=nbi();return this.divRemTo(t,i,null),i}function bnRemainder(t){var i=nbi();return this.divRemTo(t,null,i),i}function bnDivideAndRemainder(t){var i=nbi(),r=nbi();return this.divRemTo(t,i,r),new Array(i,r)}function bnpDMultiply(t){this[this.t]=this.am(0,t-1,this,0,0,this.t),++this.t,this.clamp()}function bnpDAddOffset(t,i){if(0!=t){for(;this.t<=i;)this[this.t++]=0;for(this[i]+=t;this[i]>=this.DV;)this[i]-=this.DV,++i>=this.t&&(this[this.t++]=0),++this[i]}}function NullExp(){}function nNop(t){return t}function nMulTo(t,i,r){t.multiplyTo(i,r)}function nSqrTo(t,i){t.squareTo(i)}function bnPow(t){return this.exp(t,new NullExp)}function bnpMultiplyLowerTo(t,i,r){var e,n=Math.min(this.t+t.t,i);for(r.s=0,r.t=n;n>0;)r[--n]=0;for(e=r.t-this.t;n=0;)r[e]=0;for(e=Math.max(i-this.t,0);e2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var i=nbi();return t.copyTo(i),this.reduce(i),i}function barrettRevert(t){return t}function barrettReduce(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);t.compareTo(this.m)>=0;)t.subTo(this.m,t)}function barrettSqrTo(t,i){t.squareTo(i),this.reduce(i)}function barrettMulTo(t,i,r){t.multiplyTo(i,r),this.reduce(r)}function bnModPow(t,i){var r,e,n=t.bitLength(),o=nbv(1);if(n<=0)return o;r=n<18?1:n<48?3:n<144?4:n<768?5:6,e=n<8?new Classic(i):i.isEven()?new Barrett(i):new Montgomery(i);var s=new Array,h=3,u=r-1,p=(1<1){var f=nbi();for(e.sqrTo(s[1],f);h<=p;)s[h]=nbi(),e.mulTo(f,s[h-2],s[h]),h+=2}var a,b,g=t.t-1,l=!0,m=nbi();for(n=nbits(t[g])-1;g>=0;){for(n>=u?a=t[g]>>n-u&p:(a=(t[g]&(1<0&&(a|=t[g-1]>>this.DB+n-u)),h=r;0==(1&a);)a>>=1,--h;if((n-=h)<0&&(n+=this.DB,--g),l)s[a].copyTo(o),l=!1;else{for(;h>1;)e.sqrTo(o,m),e.sqrTo(m,o),h-=2;h>0?e.sqrTo(o,m):(b=o,o=m,m=b),e.mulTo(m,s[a],o)}for(;g>=0&&0==(t[g]&1<0&&(i.rShiftTo(o,i),r.rShiftTo(o,r));i.signum()>0;)(n=i.getLowestSetBit())>0&&i.rShiftTo(n,i),(n=r.getLowestSetBit())>0&&r.rShiftTo(n,r),i.compareTo(r)>=0?(i.subTo(r,i),i.rShiftTo(1,i)):(r.subTo(i,r),r.rShiftTo(1,r));return o>0&&r.lShiftTo(o,r),r}function bnpModInt(t){if(t<=0)return 0;var i=this.DV%t,r=this.s<0?t-1:0;if(this.t>0)if(0==i)r=this[0]%t;else for(var e=this.t-1;e>=0;--e)r=(i*r+this[e])%t;return r}function bnModInverse(t){var i=t.isEven();if(this.isEven()&&i||0==t.signum())return BigInteger.ZERO;for(var r=t.clone(),e=this.clone(),n=nbv(1),o=nbv(0),s=nbv(0),h=nbv(1);0!=r.signum();){for(;r.isEven();)r.rShiftTo(1,r),i?(n.isEven()&&o.isEven()||(n.addTo(this,n),o.subTo(t,o)),n.rShiftTo(1,n)):o.isEven()||o.subTo(t,o),o.rShiftTo(1,o);for(;e.isEven();)e.rShiftTo(1,e),i?(s.isEven()&&h.isEven()||(s.addTo(this,s),h.subTo(t,h)),s.rShiftTo(1,s)):h.isEven()||h.subTo(t,h),h.rShiftTo(1,h);r.compareTo(e)>=0?(r.subTo(e,r),i&&n.subTo(s,n),o.subTo(h,o)):(e.subTo(r,e),i&&s.subTo(n,s),h.subTo(o,h))}return 0!=e.compareTo(BigInteger.ONE)?BigInteger.ZERO:h.compareTo(t)>=0?h.subtract(t):h.signum()<0?(h.addTo(t,h),h.signum()<0?h.add(t):h):h}NullExp.prototype.convert=nNop,NullExp.prototype.revert=nNop,NullExp.prototype.mulTo=nMulTo,NullExp.prototype.sqrTo=nSqrTo,Barrett.prototype.convert=barrettConvert,Barrett.prototype.revert=barrettRevert,Barrett.prototype.reduce=barrettReduce,Barrett.prototype.mulTo=barrettMulTo,Barrett.prototype.sqrTo=barrettSqrTo;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],lplim=(1<<26)/lowprimes[lowprimes.length-1];function bnIsProbablePrime(t){var i,r=this.abs();if(1==r.t&&r[0]<=lowprimes[lowprimes.length-1]){for(i=0;i>1)>lowprimes.length&&(t=lowprimes.length);for(var n=nbi(),o=0;o0;--e){u=u.twice();var s=n.testBit(e);s!=i.testBit(e)&&(u=u.add(s?this:r))}return u}function pointFpMultiplyTwo(t,e,i){var n;n=t.bitLength()>i.bitLength()?t.bitLength()-1:i.bitLength()-1;for(var r=this.curve.getInfinity(),u=this.add(e);n>=0;)r=r.twice(),t.testBit(n)?r=i.testBit(n)?r.add(u):r.add(this):i.testBit(n)&&(r=r.add(e)),--n;return r}function ECCurveFp(t,e,i){this.q=t,this.a=this.fromBigInteger(e),this.b=this.fromBigInteger(i),this.infinity=new ECPointFp(this,null,null)}function curveFpGetQ(){return this.q}function curveFpGetA(){return this.a}function curveFpGetB(){return this.b}function curveFpEquals(t){return t==this||this.q.equals(t.q)&&this.a.equals(t.a)&&this.b.equals(t.b)}function curveFpGetInfinity(){return this.infinity}function curveFpFromBigInteger(t){return new ECFieldElementFp(this.q,t)}function curveFpDecodePointHex(t){switch(parseInt(t.substr(0,2),16)){case 0:return this.infinity;case 2:case 3:return null;case 4:case 6:case 7:var e=(t.length-2)/2,i=t.substr(2,e),n=t.substr(e+2,e);return new ECPointFp(this,this.fromBigInteger(new BigInteger(i,16)),this.fromBigInteger(new BigInteger(n,16)));default:return null}}ECFieldElementFp.prototype.equals=feFpEquals,ECFieldElementFp.prototype.toBigInteger=feFpToBigInteger,ECFieldElementFp.prototype.negate=feFpNegate,ECFieldElementFp.prototype.add=feFpAdd,ECFieldElementFp.prototype.subtract=feFpSubtract,ECFieldElementFp.prototype.multiply=feFpMultiply,ECFieldElementFp.prototype.square=feFpSquare,ECFieldElementFp.prototype.divide=feFpDivide,ECPointFp.prototype.getX=pointFpGetX,ECPointFp.prototype.getY=pointFpGetY,ECPointFp.prototype.equals=pointFpEquals,ECPointFp.prototype.isInfinity=pointFpIsInfinity,ECPointFp.prototype.negate=pointFpNegate,ECPointFp.prototype.add=pointFpAdd,ECPointFp.prototype.twice=pointFpTwice,ECPointFp.prototype.multiply=pointFpMultiply,ECPointFp.prototype.multiplyTwo=pointFpMultiplyTwo,ECCurveFp.prototype.getQ=curveFpGetQ,ECCurveFp.prototype.getA=curveFpGetA,ECCurveFp.prototype.getB=curveFpGetB,ECCurveFp.prototype.equals=curveFpEquals,ECCurveFp.prototype.getInfinity=curveFpGetInfinity,ECCurveFp.prototype.fromBigInteger=curveFpFromBigInteger,ECCurveFp.prototype.decodePointHex=curveFpDecodePointHex;
+// ! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+function Arcfour(){this.i=0,this.j=0,this.S=new Array}function ARC4init(i){var t,s,h;for(t=0;t<256;++t)this.S[t]=t;for(s=0,t=0;t<256;++t)s=s+this.S[t]+i[t%i.length]&255,h=this.S[t],this.S[t]=this.S[s],this.S[s]=h;this.i=0,this.j=0}function ARC4next(){var i;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,i=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=i,this.S[i+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}Arcfour.prototype.init=ARC4init,Arcfour.prototype.next=ARC4next;var rng_psize=256;
+// (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+var rng_state,rng_pool,rng_pptr;function rng_seed_int(r){rng_pool[rng_pptr++]^=255&r,rng_pool[rng_pptr++]^=r>>8&255,rng_pool[rng_pptr++]^=r>>16&255,rng_pool[rng_pptr++]^=r>>24&255,rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}if(null==rng_pool){var t;if(rng_pool=new Array,rng_pptr=0,void 0!==window&&(void 0!==window.crypto||void 0!==window.msCrypto)){var crypto=window.crypto||window.msCrypto;if(crypto.getRandomValues){var ua=new Uint8Array(32);for(crypto.getRandomValues(ua),t=0;t<32;++t)rng_pool[rng_pptr++]=ua[t]}else if("Netscape"==navigator.appName&&navigator.appVersion<"5"){var z=window.crypto.random(32);for(t=0;t>>8,rng_pool[rng_pptr++]=255&t;rng_pptr=0,rng_seed_time()}function rng_get_byte(){if(null==rng_state){for(rng_seed_time(),(rng_state=prng_newstate()).init(rng_pool),rng_pptr=0;rng_pptr=0&&n>0;){var i=t.charCodeAt(e--);i<128?r[--n]=i:i>127&&i<2048?(r[--n]=63&i|128,r[--n]=i>>6|192):(r[--n]=63&i|128,r[--n]=i>>6&63|128,r[--n]=i>>12|224)}r[--n]=0;for(var o=new SecureRandom,l=new Array;n>2;){for(l[0]=0;0==l[0];)o.nextBytes(l);r[--n]=l[0]}return r[--n]=2,r[--n]=0,new BigInteger(r)}function oaep_mgf1_arr(t,n,r){for(var e="",i=0;e.length>24,(16711680&i)>>16,(65280&i)>>8,255&i]))),i+=1;return e}function oaep_pad(t,n,r,e){var i=KJUR.crypto.MessageDigest,o=KJUR.crypto.Util,l=null;if(r||(r="sha1"),"string"==typeof r&&(l=i.getCanonicalAlgName(r),e=i.getHashLength(l),r=function(t){return hextorstr(o.hashHex(rstrtohex(t),l))}),t.length+2*e+2>n)throw"Message too long for RSA";var u,a="";for(u=0;u0&&n.length>0))throw"Invalid RSA public key";this.n=parseBigInt(t,16),this.e=parseInt(n,16)}}function RSADoPublic(t){return t.modPowInt(this.e,this.n)}function RSAEncrypt(t){var n=pkcs1pad2(t,this.n.bitLength()+7>>3);if(null==n)return null;var r=this.doPublic(n);if(null==r)return null;var e=r.toString(16);return 0==(1&e.length)?e:"0"+e}function RSAEncryptOAEP(t,n,r){var e=oaep_pad(t,this.n.bitLength()+7>>3,n,r);if(null==e)return null;var i=this.doPublic(e);if(null==i)return null;var o=i.toString(16);return 0==(1&o.length)?o:"0"+o}RSAKey.prototype.doPublic=RSADoPublic,RSAKey.prototype.setPublic=RSASetPublic,RSAKey.prototype.encrypt=RSAEncrypt,RSAKey.prototype.encryptOAEP=RSAEncryptOAEP,RSAKey.prototype.type="RSA";
+// CryptoJS v3.1.2
+!function(r){var t=CryptoJS,e=t.lib,n=e.WordArray,o=e.Hasher,s=t.algo,a=[],i=[];!function(){function t(t){for(var e=r.sqrt(t),n=2;n<=e;n++)if(!(t%n))return!1;return!0}function e(r){return 4294967296*(r-(0|r))|0}for(var n=2,o=0;o<64;)t(n)&&(o<8&&(a[o]=e(r.pow(n,.5))),i[o]=e(r.pow(n,1/3)),o++),n++}();var h=[],c=s.SHA256=o.extend({_doReset:function(){this._hash=new n.init(a.slice(0))},_doProcessBlock:function(r,t){for(var e=this._hash.words,n=e[0],o=e[1],s=e[2],a=e[3],c=e[4],l=e[5],f=e[6],u=e[7],_=0;_<64;_++){if(_<16)h[_]=0|r[t+_];else{var v=h[_-15],d=(v<<25|v>>>7)^(v<<14|v>>>18)^v>>>3,H=h[_-2],p=(H<<15|H>>>17)^(H<<13|H>>>19)^H>>>10;h[_]=d+h[_-7]+p+h[_-16]}var w=n&o^n&s^o&s,y=(n<<30|n>>>2)^(n<<19|n>>>13)^(n<<10|n>>>22),g=u+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&l^~c&f)+i[_]+h[_];u=f,f=l,l=c,c=a+g|0,a=s,s=o,o=n,n=g+(y+w)|0}e[0]=e[0]+n|0,e[1]=e[1]+o|0,e[2]=e[2]+s|0,e[3]=e[3]+a|0,e[4]=e[4]+c|0,e[5]=e[5]+l|0,e[6]=e[6]+f|0,e[7]=e[7]+u|0},_doFinalize:function(){var t=this._data,e=t.words,n=8*this._nDataBytes,o=8*t.sigBytes;return e[o>>>5]|=128<<24-o%32,e[14+(o+64>>>9<<4)]=r.floor(n/4294967296),e[15+(o+64>>>9<<4)]=n,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var r=o.clone.call(this);return r._hash=this._hash.clone(),r}});t.SHA256=o._createHelper(c),t.HmacSHA256=o._createHmacHelper(c)}(Math);
+// asn1-1.0.14.js (c) 2013-2018 Kenji Urushima | kjur.github.com/jsrsasign/license
+"undefined"!=typeof KJUR&&KJUR||(KJUR={}),void 0!==KJUR.asn1&&KJUR.asn1||(KJUR.asn1={}),KJUR.asn1.ASN1Util=new function(){this.integerToByteHex=function(t){var e=t.toString(16);return e.length%2==1&&(e="0"+e),e},this.bigIntToMinTwosComplementsHex=function(t){var e=t.toString(16);if("-"!=e.substr(0,1))e.length%2==1?e="0"+e:e.match(/^[0-7]/)||(e="00"+e);else{var i=e.substr(1).length;i%2==1?i+=1:e.match(/^[0-7]/)||(i+=2);for(var n="",s=0;s15)throw"ASN.1 length too long to represent by 8x: n = "+t.toString(16);return(128+i).toString(16)+e},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},KJUR.asn1.DERAbstractString=function(t){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=utf8tohex(this.s).toLowerCase()},this.setStringHex=function(t){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&("string"==typeof t?this.setString(t):void 0!==t.str?this.setString(t.str):void 0!==t.hex&&this.setStringHex(t.hex))},YAHOO.lang.extend(KJUR.asn1.DERAbstractString,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractTime=function(t){KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);this.localDateToUTC=function(t){return utc=t.getTime()+6e4*t.getTimezoneOffset(),new Date(utc)},this.formatDate=function(t,e,i){var n=this.zeroPadding,s=this.localDateToUTC(t),r=String(s.getFullYear());"utc"==e&&(r=r.substr(2,2));var h=r+n(String(s.getMonth()+1),2)+n(String(s.getDate()),2)+n(String(s.getHours()),2)+n(String(s.getMinutes()),2)+n(String(s.getSeconds()),2);if(!0===i){var a=s.getMilliseconds();if(0!=a){var o=n(String(a),3);h=h+"."+(o=o.replace(/[0]+$/,""))}}return h+"Z"},this.zeroPadding=function(t,e){return t.length>=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,n,s,r){var h=new Date(Date.UTC(t,e-1,i,n,s,r,0));this.setByDate(h)},this.getFreshValueHex=function(){return this.hV}},YAHOO.lang.extend(KJUR.asn1.DERAbstractTime,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractStructured=function(t){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured,KJUR.asn1.ASN1Object),KJUR.asn1.DERBoolean=function(){KJUR.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},YAHOO.lang.extend(KJUR.asn1.DERBoolean,KJUR.asn1.ASN1Object),KJUR.asn1.DERInteger=function(t){KJUR.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new BigInteger(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},YAHOO.lang.extend(KJUR.asn1.DERInteger,KJUR.asn1.ASN1Object),KJUR.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=KJUR.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}KJUR.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7=2*u)break;if(g>=200)break;e.push(o),s=o,g++}return e},ASN1HEX.getNthChildIdx=function(t,r,n){return ASN1HEX.getChildIdx(t,r)[n]},ASN1HEX.getIdxbyList=function(t,r,n,e){var i,u,s=ASN1HEX;if(0==n.length){if(void 0!==e&&t.substr(r,2)!==e)throw"checking tag doesn't match: "+t.substr(r,2)+"!="+e;return r}return i=n.shift(),u=s.getChildIdx(t,r),s.getIdxbyList(t,u[i],n,e)},ASN1HEX.getTLVbyList=function(t,r,n,e){var i=ASN1HEX,u=i.getIdxbyList(t,r,n);if(void 0===u)throw"can't find nthList object";if(void 0!==e&&t.substr(u,2)!=e)throw"checking tag doesn't match: "+t.substr(u,2)+"!="+e;return i.getTLV(t,u)},ASN1HEX.getVbyList=function(t,r,n,e,i){var u,s,g=ASN1HEX;if(void 0===(u=g.getIdxbyList(t,r,n,e)))throw"can't find nthList object";return s=g.getV(t,u),!0===i&&(s=s.substr(2)),s},ASN1HEX.hextooidstr=function(t){var r=function(t,r){return t.length>=r?t:new Array(r-t.length+1).join("0")+t},n=[],e=t.substr(0,2),i=parseInt(e,16);n[0]=new String(Math.floor(i/40)),n[1]=new String(i%40);for(var u=t.substr(2),s=[],g=0;g0&&(f=f+"."+o.join(".")),f},ASN1HEX.dump=function(t,r,n,e){var i=ASN1HEX,u=i.getV,s=i.dump,g=i.getChildIdx,o=t;t instanceof KJUR.asn1.ASN1Object&&(o=t.getEncodedHex());var a=function(t,r){return t.length<=2*r?t:t.substr(0,r)+"..(total "+t.length/2+"bytes).."+t.substr(t.length-r,r)};void 0===r&&(r={ommit_long_octet:32}),void 0===n&&(n=0),void 0===e&&(e="");var f=r.ommit_long_octet;if("01"==o.substr(n,2))return"00"==(b=u(o,n))?e+"BOOLEAN FALSE\n":e+"BOOLEAN TRUE\n";if("02"==o.substr(n,2))return e+"INTEGER "+a(b=u(o,n),f)+"\n";if("03"==o.substr(n,2))return e+"BITSTRING "+a(b=u(o,n),f)+"\n";if("04"==o.substr(n,2)){var b=u(o,n);if(i.isASN1HEX(b)){var S=e+"OCTETSTRING, encapsulates\n";return S+=s(b,r,0,e+" ")}return e+"OCTETSTRING "+a(b,f)+"\n"}if("05"==o.substr(n,2))return e+"NULL\n";if("06"==o.substr(n,2)){var N=u(o,n),E=KJUR.asn1.ASN1Util.oidHexToInt(N),h=KJUR.asn1.x509.OID.oid2name(E),l=E.replace(/\./g," ");return""!=h?e+"ObjectIdentifier "+h+" ("+l+")\n":e+"ObjectIdentifier ("+l+")\n"}if("0c"==o.substr(n,2))return e+"UTF8String '"+hextoutf8(u(o,n))+"'\n";if("13"==o.substr(n,2))return e+"PrintableString '"+hextoutf8(u(o,n))+"'\n";if("14"==o.substr(n,2))return e+"TeletexString '"+hextoutf8(u(o,n))+"'\n";if("16"==o.substr(n,2))return e+"IA5String '"+hextoutf8(u(o,n))+"'\n";if("17"==o.substr(n,2))return e+"UTCTime "+hextoutf8(u(o,n))+"\n";if("18"==o.substr(n,2))return e+"GeneralizedTime "+hextoutf8(u(o,n))+"\n";if("30"==o.substr(n,2)){if("3000"==o.substr(n,4))return e+"SEQUENCE {}\n";S=e+"SEQUENCE\n";var d=r;if((2==(v=g(o,n)).length||3==v.length)&&"06"==o.substr(v[0],2)&&"04"==o.substr(v[v.length-1],2)){h=i.oidname(u(o,v[0]));var A=JSON.parse(JSON.stringify(r));A.x509ExtName=h,d=A}for(var c=0;co.length&&(o=n[r]);return(t=t.replace(o,"::")).slice(1,-1)}function hextoip(t){var e="malformed hex value";if(!t.match(/^([0-9A-Fa-f][0-9A-Fa-f]){1,}$/))throw e;if(8!=t.length)return 32==t.length?hextoipv6(t):t;try{return parseInt(t.substr(0,2),16)+"."+parseInt(t.substr(2,2),16)+"."+parseInt(t.substr(4,2),16)+"."+parseInt(t.substr(6,2),16)}catch(t){throw e}}function iptohex(t){var e="malformed IP address";if(!(t=t.toLowerCase(t)).match(/^[0-9.]+$/)){if(t.match(/^[0-9a-f:]+$/)&&-1!==t.indexOf(":"))return ipv6tohex(t);throw e}var r=t.split(".");if(4!==r.length)throw e;var n="";try{for(var o=0;o<4;o++){n+=("0"+parseInt(r[o]).toString(16)).slice(-2)}return n}catch(t){throw e}}function encodeURIComponentAll(t){for(var e=encodeURIComponent(t),r="",n=0;n"7"?"00"+t:t}function intarystrtohex(t){t=(t=(t=t.replace(/^\s*\[\s*/,"")).replace(/\s*\]\s*$/,"")).replace(/\s*/g,"");try{return t.split(/,/).map(function(t,e,r){var n=parseInt(t);if(n<0||255e.length&&(r=e.length);for(var n=0;nr)throw"key is too short for SigAlg: keylen="+e+","+s;for(var o="0001",a="00"+i,h="",n=r-o.length-a.length,p=0;p=0)return!1;if(r.compareTo(BigInteger.ONE)<0||r.compareTo(s)>=0)return!1;var a=r.modInverse(s),o=e.multiply(a).mod(s),u=t.multiply(a).mod(s);return n.multiply(o).add(i.multiply(u)).getX().toBigInteger().mod(s).equals(t)},this.serializeSig=function(e,t){var r=e.toByteArraySigned(),i=t.toByteArraySigned(),s=[];return s.push(2),s.push(r.length),(s=s.concat(r)).push(2),s.push(i.length),(s=s.concat(i)).unshift(s.length),s.unshift(48),s},this.parseSig=function(e){var t;if(48!=e[0])throw new Error("Signature not a valid DERSequence");if(2!=e[t=2])throw new Error("First element in signature must be a DERInteger");var r=e.slice(t+2,t+2+e[t+1]);if(2!=e[t+=2+e[t+1]])throw new Error("Second element in signature must be a DERInteger");var i=e.slice(t+2,t+2+e[t+1]);return t+=2+e[t+1],{r:BigInteger.fromByteArrayUnsigned(r),s:BigInteger.fromByteArrayUnsigned(i)}},this.parseSigCompact=function(e){if(65!==e.length)throw"Signature has the wrong length";var t=e[0]-27;if(t<0||t>7)throw"Invalid signature type";var r=this.ecparams.n;return{r:BigInteger.fromByteArrayUnsigned(e.slice(1,33)).mod(r),s:BigInteger.fromByteArrayUnsigned(e.slice(33,65)).mod(r),i:t}},this.readPKCS5PrvKeyHex=function(e){var t,r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{t=a(e,0,[2,0],"06"),r=a(e,0,[1],"04");try{i=a(e,0,[3,0],"03").substr(2)}catch(e){}}catch(e){throw"malformed PKCS#1/5 plain ECC private key"}if(this.curveName=n(t),void 0===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i),this.setPrivateKeyHex(r),this.isPublic=!1},this.readPKCS8PrvKeyHex=function(e){var t,r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{a(e,0,[1,0],"06"),t=a(e,0,[1,1],"06"),r=a(e,0,[2,0,1],"04");try{i=a(e,0,[2,0,2,0],"03").substr(2)}catch(e){}}catch(e){throw"malformed PKCS#8 plain ECC private key"}if(this.curveName=n(t),void 0===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i),this.setPrivateKeyHex(r),this.isPublic=!1},this.readPKCS8PubKeyHex=function(e){var t,r,i=ASN1HEX,s=KJUR.crypto.ECDSA.getName,n=i.getVbyList;if(!1===i.isASN1HEX(e))throw"not ASN.1 hex string";try{n(e,0,[0,0],"06"),t=n(e,0,[0,1],"06"),r=n(e,0,[1],"03").substr(2)}catch(e){throw"malformed PKCS#8 ECC public key"}if(this.curveName=s(t),null===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(r)},this.readCertPubKeyHex=function(e,t){5!==t&&(t=6);var r,i,s=ASN1HEX,n=KJUR.crypto.ECDSA.getName,a=s.getVbyList;if(!1===s.isASN1HEX(e))throw"not ASN.1 hex string";try{r=a(e,0,[0,t,0,1],"06"),i=a(e,0,[0,t,1],"03").substr(2)}catch(e){throw"malformed X.509 certificate ECC public key"}if(this.curveName=n(r),null===this.curveName)throw"unsupported curve name";this.setNamedCurve(this.curveName),this.setPublicKeyHex(i)},void 0!==e&&void 0!==e.curve&&(this.curveName=e.curve),void 0===this.curveName&&(this.curveName="secp256r1"),this.setNamedCurve(this.curveName),void 0!==e&&(void 0!==e.prv&&this.setPrivateKeyHex(e.prv),void 0!==e.pub&&this.setPublicKeyHex(e.pub))},KJUR.crypto.ECDSA.parseSigHex=function(e){var t=KJUR.crypto.ECDSA.parseSigHexInHexRS(e);return{r:new BigInteger(t.r,16),s:new BigInteger(t.s,16)}},KJUR.crypto.ECDSA.parseSigHexInHexRS=function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV;if("30"!=e.substr(0,2))throw"signature is not a ASN.1 sequence";var s=r(e,0);if(2!=s.length)throw"number of signature ASN.1 sequence elements seem wrong";var n=s[0],a=s[1];if("02"!=e.substr(n,2))throw"1st item of sequene of signature is not ASN.1 integer";if("02"!=e.substr(a,2))throw"2nd item of sequene of signature is not ASN.1 integer";return{r:i(e,n),s:i(e,a)}},KJUR.crypto.ECDSA.asn1SigToConcatSig=function(e){var t=KJUR.crypto.ECDSA.parseSigHexInHexRS(e),r=t.r,i=t.s;if("00"==r.substr(0,2)&&r.length%32==2&&(r=r.substr(2)),"00"==i.substr(0,2)&&i.length%32==2&&(i=i.substr(2)),r.length%32==30&&(r="00"+r),i.length%32==30&&(i="00"+i),r.length%32!=0)throw"unknown ECDSA sig r length error";if(i.length%32!=0)throw"unknown ECDSA sig s length error";return r+i},KJUR.crypto.ECDSA.concatSigToASN1Sig=function(e){if(e.length/2*8%128!=0)throw"unknown ECDSA concatinated r-s sig length error";var t=e.substr(0,e.length/2),r=e.substr(e.length/2);return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(t,r)},KJUR.crypto.ECDSA.hexRSSigToASN1Sig=function(e,t){var r=new BigInteger(e,16),i=new BigInteger(t,16);return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r,i)},KJUR.crypto.ECDSA.biRSSigToASN1Sig=function(e,t){var r=KJUR.asn1,i=new r.DERInteger({bigint:e}),s=new r.DERInteger({bigint:t});return new r.DERSequence({array:[i,s]}).getEncodedHex()},KJUR.crypto.ECDSA.getName=function(e){return"2a8648ce3d030107"===e?"secp256r1":"2b8104000a"===e?"secp256k1":"2b81040022"===e?"secp384r1":-1!=="|secp256r1|NIST P-256|P-256|prime256v1|".indexOf(e)?"secp256r1":-1!=="|secp256k1|".indexOf(e)?"secp256k1":-1!=="|secp384r1|NIST P-384|P-384|".indexOf(e)?"secp384r1":null};
+// ecparam-1.0.0.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
+"undefined"!=typeof KJUR&&KJUR||(KJUR={}),void 0!==KJUR.crypto&&KJUR.crypto||(KJUR.crypto={}),KJUR.crypto.ECParameterDB=new function(){var F={},B={};function E(F){return new BigInteger(F,16)}this.getByName=function(E){var C=E;if(void 0!==B[C]&&(C=B[E]),void 0!==F[C])return F[C];throw"unregistered EC curve name: "+C},this.regist=function(C,D,A,e,r,t,c,a,i,p,o,s){F[C]={};var d=E(A),f=E(e),n=E(r),m=E(t),P=E(c),v=new ECCurveFp(d,f,n),y=v.decodePointHex("04"+a+i);F[C].name=C,F[C].keylen=D,F[C].curve=v,F[C].G=y,F[C].n=m,F[C].h=P,F[C].oid=o,F[C].info=s;for(var J=0;J=2*d)break}var v={};return v.keyhex=c.substr(0,2*n[e].keylen),v.ivhex=c.substr(2*n[e].keylen,2*n[e].ivlen),v},d=function(e,t,r,i){var o=CryptoJS.enc.Base64.parse(e),a=CryptoJS.enc.Hex.stringify(o);return(0,n[t].proc)(a,r,i)};return{version:"1.0.0",parsePKCS5PEM:function(e){return o(e)},getKeyAndUnusedIvByPasscodeAndIvsalt:function(e,t,r){return a(e,t,r)},decryptKeyB64:function(e,t,r,i){return d(e,t,r,i)},getDecryptedKeyHex:function(e,t){var r=o(e),i=(r.type,r.cipher),n=r.ivsalt,c=r.data,u=a(i,t,n).keyhex;return d(c,i,u,n)},getEncryptedPKCS5PEMFromPrvKeyHex:function(e,t,r,i,o){var d,c,u="";if(void 0!==i&&null!=i||(i="AES-256-CBC"),void 0===n[i])throw"KEYUTIL unsupported algorithm: "+i;if(void 0===o||null==o){var p=n[i].ivlen;o=(d=p,c=CryptoJS.lib.WordArray.random(d),CryptoJS.enc.Hex.stringify(c)).toUpperCase()}var v,s,f,E=a(i,r,o).keyhex;u="-----BEGIN "+e+" PRIVATE KEY-----\r\n";return u+="Proc-Type: 4,ENCRYPTED\r\n",u+="DEK-Info: "+i+","+o+"\r\n",u+="\r\n",u+=(v=t,s=E,f=o,(0,n[i].eproc)(v,s,f)).replace(/(.{64})/g,"$1\r\n"),u+="\r\n-----END "+e+" PRIVATE KEY-----\r\n"},parseHexOfEncryptedPKCS8:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={},o=r(e,0);if(2!=o.length)throw"malformed format: SEQUENCE(0).items != 2: "+o.length;n.ciphertext=i(e,o[1]);var a=r(e,o[0]);if(2!=a.length)throw"malformed format: SEQUENCE(0.0).items != 2: "+a.length;if("2a864886f70d01050d"!=i(e,a[0]))throw"this only supports pkcs5PBES2";var d=r(e,a[1]);if(2!=a.length)throw"malformed format: SEQUENCE(0.0.1).items != 2: "+d.length;var c=r(e,d[1]);if(2!=c.length)throw"malformed format: SEQUENCE(0.0.1.1).items != 2: "+c.length;if("2a864886f70d0307"!=i(e,c[0]))throw"this only supports TripleDES";n.encryptionSchemeAlg="TripleDES",n.encryptionSchemeIV=i(e,c[1]);var u=r(e,d[0]);if(2!=u.length)throw"malformed format: SEQUENCE(0.0.1.0).items != 2: "+u.length;if("2a864886f70d01050c"!=i(e,u[0]))throw"this only supports pkcs5PBKDF2";var p=r(e,u[1]);if(p.length<2)throw"malformed format: SEQUENCE(0.0.1.0.1).items < 2: "+p.length;n.pbkdf2Salt=i(e,p[0]);var v=i(e,p[1]);try{n.pbkdf2Iter=parseInt(v,16)}catch(e){throw"malformed format pbkdf2Iter: "+v}return n},getPBKDF2KeyHexFromParam:function(e,t){var r=CryptoJS.enc.Hex.parse(e.pbkdf2Salt),i=e.pbkdf2Iter,n=CryptoJS.PBKDF2(t,r,{keySize:6,iterations:i});return CryptoJS.enc.Hex.stringify(n)},_getPlainPKCS8HexFromEncryptedPKCS8PEM:function(e,t){var r=pemtohex(e,"ENCRYPTED PRIVATE KEY"),i=this.parseHexOfEncryptedPKCS8(r),n=KEYUTIL.getPBKDF2KeyHexFromParam(i,t),o={};o.ciphertext=CryptoJS.enc.Hex.parse(i.ciphertext);var a=CryptoJS.enc.Hex.parse(n),d=CryptoJS.enc.Hex.parse(i.encryptionSchemeIV),c=CryptoJS.TripleDES.decrypt(o,a,{iv:d});return CryptoJS.enc.Hex.stringify(c)},getKeyFromEncryptedPKCS8PEM:function(e,t){var r=this._getPlainPKCS8HexFromEncryptedPKCS8PEM(e,t);return this.getKeyFromPlainPrivatePKCS8Hex(r)},parsePlainPrivatePKCS8Hex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={};if(n.algparam=null,"30"!=e.substr(0,2))throw"malformed plain PKCS8 private key(code:001)";var o=r(e,0);if(3!=o.length)throw"malformed plain PKCS8 private key(code:002)";if("30"!=e.substr(o[1],2))throw"malformed PKCS8 private key(code:003)";var a=r(e,o[1]);if(2!=a.length)throw"malformed PKCS8 private key(code:004)";if("06"!=e.substr(a[0],2))throw"malformed PKCS8 private key(code:005)";if(n.algoid=i(e,a[0]),"06"==e.substr(a[1],2)&&(n.algparam=i(e,a[1])),"04"!=e.substr(o[2],2))throw"malformed PKCS8 private key(code:006)";return n.keyidx=t.getVidx(e,o[2]),n},getKeyFromPlainPrivatePKCS8PEM:function(e){var t=pemtohex(e,"PRIVATE KEY");return this.getKeyFromPlainPrivatePKCS8Hex(t)},getKeyFromPlainPrivatePKCS8Hex:function(e){var t,r=this.parsePlainPrivatePKCS8Hex(e);if("2a864886f70d010101"==r.algoid)t=new RSAKey;else if("2a8648ce380401"==r.algoid)t=new KJUR.crypto.DSA;else{if("2a8648ce3d0201"!=r.algoid)throw"unsupported private key algorithm";t=new KJUR.crypto.ECDSA}return t.readPKCS8PrvKeyHex(e),t},_getKeyFromPublicPKCS8Hex:function(e){var t,r=ASN1HEX.getVbyList(e,0,[0,0],"06");if("2a864886f70d010101"===r)t=new RSAKey;else if("2a8648ce380401"===r)t=new KJUR.crypto.DSA;else{if("2a8648ce3d0201"!==r)throw"unsupported PKCS#8 public key hex";t=new KJUR.crypto.ECDSA}return t.readPKCS8PubKeyHex(e),t},parsePublicRawRSAKeyHex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={};if("30"!=e.substr(0,2))throw"malformed RSA key(code:001)";var o=r(e,0);if(2!=o.length)throw"malformed RSA key(code:002)";if("02"!=e.substr(o[0],2))throw"malformed RSA key(code:003)";if(n.n=i(e,o[0]),"02"!=e.substr(o[1],2))throw"malformed RSA key(code:004)";return n.e=i(e,o[1]),n},parsePublicPKCS8Hex:function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getV,n={algparam:null},o=r(e,0);if(2!=o.length)throw"outer DERSequence shall have 2 elements: "+o.length;var a=o[0];if("30"!=e.substr(a,2))throw"malformed PKCS8 public key(code:001)";var d=r(e,a);if(2!=d.length)throw"malformed PKCS8 public key(code:002)";if("06"!=e.substr(d[0],2))throw"malformed PKCS8 public key(code:003)";if(n.algoid=i(e,d[0]),"06"==e.substr(d[1],2)?n.algparam=i(e,d[1]):"30"==e.substr(d[1],2)&&(n.algparam={},n.algparam.p=t.getVbyList(e,d[1],[0],"02"),n.algparam.q=t.getVbyList(e,d[1],[1],"02"),n.algparam.g=t.getVbyList(e,d[1],[2],"02")),"03"!=e.substr(o[1],2))throw"malformed PKCS8 public key(code:004)";return n.key=i(e,o[1]).substr(2),n}}}();KEYUTIL.getKey=function(e,t,r){var i=(x=ASN1HEX).getChildIdx,n=(x.getV,x.getVbyList),o=KJUR.crypto,a=o.ECDSA,d=o.DSA,c=RSAKey,u=pemtohex,p=KEYUTIL;if(void 0!==c&&e instanceof c)return e;if(void 0!==a&&e instanceof a)return e;if(void 0!==d&&e instanceof d)return e;if(void 0!==e.curve&&void 0!==e.xy&&void 0===e.d)return new a({pub:e.xy,curve:e.curve});if(void 0!==e.curve&&void 0!==e.d)return new a({prv:e.d,curve:e.curve});if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0===e.d)return(A=new c).setPublic(e.n,e.e),A;if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0!==e.p&&void 0!==e.q&&void 0!==e.dp&&void 0!==e.dq&&void 0!==e.co&&void 0===e.qi)return(A=new c).setPrivateEx(e.n,e.e,e.d,e.p,e.q,e.dp,e.dq,e.co),A;if(void 0===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0===e.p)return(A=new c).setPrivate(e.n,e.e,e.d),A;if(void 0!==e.p&&void 0!==e.q&&void 0!==e.g&&void 0!==e.y&&void 0===e.x)return(A=new d).setPublic(e.p,e.q,e.g,e.y),A;if(void 0!==e.p&&void 0!==e.q&&void 0!==e.g&&void 0!==e.y&&void 0!==e.x)return(A=new d).setPrivate(e.p,e.q,e.g,e.y,e.x),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0===e.d)return(A=new c).setPublic(b64utohex(e.n),b64utohex(e.e)),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d&&void 0!==e.p&&void 0!==e.q&&void 0!==e.dp&&void 0!==e.dq&&void 0!==e.qi)return(A=new c).setPrivateEx(b64utohex(e.n),b64utohex(e.e),b64utohex(e.d),b64utohex(e.p),b64utohex(e.q),b64utohex(e.dp),b64utohex(e.dq),b64utohex(e.qi)),A;if("RSA"===e.kty&&void 0!==e.n&&void 0!==e.e&&void 0!==e.d)return(A=new c).setPrivate(b64utohex(e.n),b64utohex(e.e),b64utohex(e.d)),A;if("EC"===e.kty&&void 0!==e.crv&&void 0!==e.x&&void 0!==e.y&&void 0===e.d){var v=(R=new a({curve:e.crv})).ecparams.keylen/4,s="04"+("0000000000"+b64utohex(e.x)).slice(-v)+("0000000000"+b64utohex(e.y)).slice(-v);return R.setPublicKeyHex(s),R}if("EC"===e.kty&&void 0!==e.crv&&void 0!==e.x&&void 0!==e.y&&void 0!==e.d){v=(R=new a({curve:e.crv})).ecparams.keylen/4,s="04"+("0000000000"+b64utohex(e.x)).slice(-v)+("0000000000"+b64utohex(e.y)).slice(-v);var f=("0000000000"+b64utohex(e.d)).slice(-v);return R.setPublicKeyHex(s),R.setPrivateKeyHex(f),R}if("pkcs5prv"===r){var E,y=e,x=ASN1HEX;if(9===(E=i(y,0)).length)(A=new c).readPKCS5PrvKeyHex(y);else if(6===E.length)(A=new d).readPKCS5PrvKeyHex(y);else{if(!(E.length>2&&"04"===y.substr(E[1],2)))throw"unsupported PKCS#1/5 hexadecimal key";(A=new a).readPKCS5PrvKeyHex(y)}return A}if("pkcs8prv"===r)return A=p.getKeyFromPlainPrivatePKCS8Hex(e);if("pkcs8pub"===r)return p._getKeyFromPublicPKCS8Hex(e);if("x509pub"===r)return X509.getPublicKeyFromCertHex(e);if(-1!=e.indexOf("-END CERTIFICATE-",0)||-1!=e.indexOf("-END X509 CERTIFICATE-",0)||-1!=e.indexOf("-END TRUSTED CERTIFICATE-",0))return X509.getPublicKeyFromCertPEM(e);if(-1!=e.indexOf("-END PUBLIC KEY-")){var P=pemtohex(e,"PUBLIC KEY");return p._getKeyFromPublicPKCS8Hex(P)}if(-1!=e.indexOf("-END RSA PRIVATE KEY-")&&-1==e.indexOf("4,ENCRYPTED")){var S=u(e,"RSA PRIVATE KEY");return p.getKey(S,null,"pkcs5prv")}if(-1!=e.indexOf("-END DSA PRIVATE KEY-")&&-1==e.indexOf("4,ENCRYPTED")){var l=n(I=u(e,"DSA PRIVATE KEY"),0,[1],"02"),g=n(I,0,[2],"02"),K=n(I,0,[3],"02"),C=n(I,0,[4],"02"),h=n(I,0,[5],"02");return(A=new d).setPrivate(new BigInteger(l,16),new BigInteger(g,16),new BigInteger(K,16),new BigInteger(C,16),new BigInteger(h,16)),A}if(-1!=e.indexOf("-END PRIVATE KEY-"))return p.getKeyFromPlainPrivatePKCS8PEM(e);if(-1!=e.indexOf("-END RSA PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var m=p.getDecryptedKeyHex(e,t),b=new RSAKey;return b.readPKCS5PrvKeyHex(m),b}if(-1!=e.indexOf("-END EC PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var R,A=n(I=p.getDecryptedKeyHex(e,t),0,[1],"04"),H=n(I,0,[2,0],"06"),w=n(I,0,[3,0],"03").substr(2);if(void 0===KJUR.crypto.OID.oidhex2name[H])throw"undefined OID(hex) in KJUR.crypto.OID: "+H;return(R=new a({curve:KJUR.crypto.OID.oidhex2name[H]})).setPublicKeyHex(w),R.setPrivateKeyHex(A),R.isPublic=!1,R}if(-1!=e.indexOf("-END DSA PRIVATE KEY-")&&-1!=e.indexOf("4,ENCRYPTED")){var I;l=n(I=p.getDecryptedKeyHex(e,t),0,[1],"02"),g=n(I,0,[2],"02"),K=n(I,0,[3],"02"),C=n(I,0,[4],"02"),h=n(I,0,[5],"02");return(A=new d).setPrivate(new BigInteger(l,16),new BigInteger(g,16),new BigInteger(K,16),new BigInteger(C,16),new BigInteger(h,16)),A}if(-1!=e.indexOf("-END ENCRYPTED PRIVATE KEY-"))return p.getKeyFromEncryptedPKCS8PEM(e,t);throw"not supported argument"},KEYUTIL.generateKeypair=function(e,t){if("RSA"==e){var r=t;(a=new RSAKey).generate(r,"10001"),a.isPrivate=!0,a.isPublic=!0;var i=new RSAKey,n=a.n.toString(16),o=a.e.toString(16);return i.setPublic(n,o),i.isPrivate=!1,i.isPublic=!0,(d={}).prvKeyObj=a,d.pubKeyObj=i,d}if("EC"==e){var a,d,c=t,u=new KJUR.crypto.ECDSA({curve:c}).generateKeyPairHex();return(a=new KJUR.crypto.ECDSA({curve:c})).setPublicKeyHex(u.ecpubhex),a.setPrivateKeyHex(u.ecprvhex),a.isPrivate=!0,a.isPublic=!1,(i=new KJUR.crypto.ECDSA({curve:c})).setPublicKeyHex(u.ecpubhex),i.isPrivate=!1,i.isPublic=!0,(d={}).prvKeyObj=a,d.pubKeyObj=i,d}throw"unknown algorithm: "+e},KEYUTIL.getPEM=function(e,t,r,i,n,o){var a=KJUR,d=a.asn1,c=d.DERObjectIdentifier,u=d.DERInteger,p=d.ASN1Util.newObject,v=d.x509.SubjectPublicKeyInfo,s=a.crypto,f=s.DSA,E=s.ECDSA,y=RSAKey;function x(e){return p({seq:[{int:0},{int:{bigint:e.n}},{int:e.e},{int:{bigint:e.d}},{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.dmp1}},{int:{bigint:e.dmq1}},{int:{bigint:e.coeff}}]})}function P(e){return p({seq:[{int:1},{octstr:{hex:e.prvKeyHex}},{tag:["a0",!0,{oid:{name:e.curveName}}]},{tag:["a1",!0,{bitstr:{hex:"00"+e.pubKeyHex}}]}]})}function S(e){return p({seq:[{int:0},{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.g}},{int:{bigint:e.y}},{int:{bigint:e.x}}]})}if((void 0!==y&&e instanceof y||void 0!==f&&e instanceof f||void 0!==E&&e instanceof E)&&1==e.isPublic&&(void 0===t||"PKCS8PUB"==t)){var l=new v(e).getEncodedHex();return hextopem(l,"PUBLIC KEY")}if("PKCS1PRV"==t&&void 0!==y&&e instanceof y&&(void 0===r||null==r)&&1==e.isPrivate){l=x(e).getEncodedHex();return hextopem(l,"RSA PRIVATE KEY")}if("PKCS1PRV"==t&&void 0!==E&&e instanceof E&&(void 0===r||null==r)&&1==e.isPrivate){var g=new c({name:e.curveName}).getEncodedHex(),K=P(e).getEncodedHex(),C="";return C+=hextopem(g,"EC PARAMETERS"),C+=hextopem(K,"EC PRIVATE KEY")}if("PKCS1PRV"==t&&void 0!==f&&e instanceof f&&(void 0===r||null==r)&&1==e.isPrivate){l=S(e).getEncodedHex();return hextopem(l,"DSA PRIVATE KEY")}if("PKCS5PRV"==t&&void 0!==y&&e instanceof y&&void 0!==r&&null!=r&&1==e.isPrivate){l=x(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("RSA",l,r,i,o)}if("PKCS5PRV"==t&&void 0!==E&&e instanceof E&&void 0!==r&&null!=r&&1==e.isPrivate){l=P(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("EC",l,r,i,o)}if("PKCS5PRV"==t&&void 0!==f&&e instanceof f&&void 0!==r&&null!=r&&1==e.isPrivate){l=S(e).getEncodedHex();return void 0===i&&(i="DES-EDE3-CBC"),this.getEncryptedPKCS5PEMFromPrvKeyHex("DSA",l,r,i,o)}var h=function(e,t){var r=m(e,t);return new p({seq:[{seq:[{oid:{name:"pkcs5PBES2"}},{seq:[{seq:[{oid:{name:"pkcs5PBKDF2"}},{seq:[{octstr:{hex:r.pbkdf2Salt}},{int:r.pbkdf2Iter}]}]},{seq:[{oid:{name:"des-EDE3-CBC"}},{octstr:{hex:r.encryptionSchemeIV}}]}]}]},{octstr:{hex:r.ciphertext}}]}).getEncodedHex()},m=function(e,t){var r=CryptoJS.lib.WordArray.random(8),i=CryptoJS.lib.WordArray.random(8),n=CryptoJS.PBKDF2(t,r,{keySize:6,iterations:100}),o=CryptoJS.enc.Hex.parse(e),a=CryptoJS.TripleDES.encrypt(o,n,{iv:i})+"",d={};return d.ciphertext=a,d.pbkdf2Salt=CryptoJS.enc.Hex.stringify(r),d.pbkdf2Iter=100,d.encryptionSchemeAlg="DES-EDE3-CBC",d.encryptionSchemeIV=CryptoJS.enc.Hex.stringify(i),d};if("PKCS8PRV"==t&&void 0!=y&&e instanceof y&&1==e.isPrivate){var b=x(e).getEncodedHex();l=p({seq:[{int:0},{seq:[{oid:{name:"rsaEncryption"}},{null:!0}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}if("PKCS8PRV"==t&&void 0!==E&&e instanceof E&&1==e.isPrivate){b=new p({seq:[{int:1},{octstr:{hex:e.prvKeyHex}},{tag:["a1",!0,{bitstr:{hex:"00"+e.pubKeyHex}}]}]}).getEncodedHex(),l=p({seq:[{int:0},{seq:[{oid:{name:"ecPublicKey"}},{oid:{name:e.curveName}}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}if("PKCS8PRV"==t&&void 0!==f&&e instanceof f&&1==e.isPrivate){b=new u({bigint:e.x}).getEncodedHex(),l=p({seq:[{int:0},{seq:[{oid:{name:"dsa"}},{seq:[{int:{bigint:e.p}},{int:{bigint:e.q}},{int:{bigint:e.g}}]}]},{octstr:{hex:b}}]}).getEncodedHex();if(void 0===r||null==r)return hextopem(l,"PRIVATE KEY");K=h(l,r);return hextopem(K,"ENCRYPTED PRIVATE KEY")}throw"unsupported object nor format"},KEYUTIL.getKeyFromCSRPEM=function(e){var t=pemtohex(e,"CERTIFICATE REQUEST");return KEYUTIL.getKeyFromCSRHex(t)},KEYUTIL.getKeyFromCSRHex=function(e){var t=KEYUTIL.parseCSRHex(e);return KEYUTIL.getKey(t.p8pubkeyhex,null,"pkcs8pub")},KEYUTIL.parseCSRHex=function(e){var t=ASN1HEX,r=t.getChildIdx,i=t.getTLV,n={},o=e;if("30"!=o.substr(0,2))throw"malformed CSR(code:001)";var a=r(o,0);if(a.length<1)throw"malformed CSR(code:002)";if("30"!=o.substr(a[0],2))throw"malformed CSR(code:003)";var d=r(o,a[0]);if(d.length<3)throw"malformed CSR(code:004)";return n.p8pubkeyhex=i(o,d[2]),n},KEYUTIL.getJWKFromKey=function(e){var t={};if(e instanceof RSAKey&&e.isPrivate)return t.kty="RSA",t.n=hextob64u(e.n.toString(16)),t.e=hextob64u(e.e.toString(16)),t.d=hextob64u(e.d.toString(16)),t.p=hextob64u(e.p.toString(16)),t.q=hextob64u(e.q.toString(16)),t.dp=hextob64u(e.dmp1.toString(16)),t.dq=hextob64u(e.dmq1.toString(16)),t.qi=hextob64u(e.coeff.toString(16)),t;if(e instanceof RSAKey&&e.isPublic)return t.kty="RSA",t.n=hextob64u(e.n.toString(16)),t.e=hextob64u(e.e.toString(16)),t;if(e instanceof KJUR.crypto.ECDSA&&e.isPrivate){if("P-256"!==(i=e.getShortNISTPCurveName())&&"P-384"!==i)throw"unsupported curve name for JWT: "+i;var r=e.getPublicKeyXYHex();return t.kty="EC",t.crv=i,t.x=hextob64u(r.x),t.y=hextob64u(r.y),t.d=hextob64u(e.prvKeyHex),t}if(e instanceof KJUR.crypto.ECDSA&&e.isPublic){var i;if("P-256"!==(i=e.getShortNISTPCurveName())&&"P-384"!==i)throw"unsupported curve name for JWT: "+i;r=e.getPublicKeyXYHex();return t.kty="EC",t.crv=i,t.x=hextob64u(r.x),t.y=hextob64u(r.y),t}throw"not supported key object"};
+// discuss at: http://locutus.io/php/pack/
+function pack(r){for(var e,o,n,a,t,g,h,i,f,c,s,w,C,l,d,p,m,k,u,S,b,y,E=0,W=1,T="",v="",A=0,M=[];Ev.length)throw new Error("Warning: pack() Type "+e+": not enough characters in string");for(A=0;A=o||void 0===v[A+1]?n+="0":n+=v[A+1],"h"===e&&(n=n[1]+n[0]),T+=String.fromCharCode(parseInt(n,16));W++;break;case"c":case"C":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;Aarguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),W++;break;case"n":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),T+=String.fromCharCode(255&arguments[W]),W++;break;case"i":case"I":case"l":case"L":case"V":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>8&255),T+=String.fromCharCode(arguments[W]>>16&255),T+=String.fromCharCode(arguments[W]>>24&255),W++;break;case"N":if("*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A>24&255),T+=String.fromCharCode(arguments[W]>>16&255),T+=String.fromCharCode(arguments[W]>>8&255),T+=String.fromCharCode(255&arguments[W]),W++;break;case"f":case"d":if(a=23,t=8,"d"===e&&(a=52,t=11),"*"===o&&(o=arguments.length-W),o>arguments.length-W)throw new Error("Warning: pack() Type "+e+": too few arguments");for(A=0;A0&&b;--m)C[++b]=((m*=2)>=1)-0;for(b=-1;++b=i&&s<=f?b+1:h+1-(s=i-1)))+1]){if(!(u=C[k]))for(S=k+2;!u&&S=0;(C[S]=!C[S]-0)&&(u=0));}for(b=b-2<0?-1:b-3;++b=i&&s<=f?++b:s>=1;for(d=0,S=0,b=(y=(l?"1":"0")+y+C.slice(b,b+a).join("")).length,M=[];b;)d+=(1<T.length)for(g=o-T.length,A=0;AMIT License
+ */
+
+/**
+ * kjur's class library name space
+ *
+ * This name space provides following name spaces:
+ *
+ * - {@link KJUR.asn1} - ASN.1 primitive hexadecimal encoder
+ * - {@link KJUR.asn1.x509} - ASN.1 structure for X.509 certificate and CRL
+ * - {@link KJUR.crypto} - Java Cryptographic Extension(JCE) style MessageDigest/Signature
+ * class and utilities
+ *
+ *
+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
+ * @name KJUR
+ * @namespace kjur's class library name space
+ */
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+
+/**
+ * kjur's ASN.1 class library name space
+ *
+ * This is ITU-T X.690 ASN.1 DER encoder class library and
+ * class structure and methods is very similar to
+ * org.bouncycastle.asn1 package of
+ * well known BouncyCaslte Cryptography Library.
+ *
PROVIDING ASN.1 PRIMITIVES
+ * Here are ASN.1 DER primitive classes.
+ *
+ * - 0x01 {@link KJUR.asn1.DERBoolean}
+ * - 0x02 {@link KJUR.asn1.DERInteger}
+ * - 0x03 {@link KJUR.asn1.DERBitString}
+ * - 0x04 {@link KJUR.asn1.DEROctetString}
+ * - 0x05 {@link KJUR.asn1.DERNull}
+ * - 0x06 {@link KJUR.asn1.DERObjectIdentifier}
+ * - 0x0a {@link KJUR.asn1.DEREnumerated}
+ * - 0x0c {@link KJUR.asn1.DERUTF8String}
+ * - 0x12 {@link KJUR.asn1.DERNumericString}
+ * - 0x13 {@link KJUR.asn1.DERPrintableString}
+ * - 0x14 {@link KJUR.asn1.DERTeletexString}
+ * - 0x16 {@link KJUR.asn1.DERIA5String}
+ * - 0x17 {@link KJUR.asn1.DERUTCTime}
+ * - 0x18 {@link KJUR.asn1.DERGeneralizedTime}
+ * - 0x30 {@link KJUR.asn1.DERSequence}
+ * - 0x31 {@link KJUR.asn1.DERSet}
+ *
+ * OTHER ASN.1 CLASSES
+ *
+ * - {@link KJUR.asn1.ASN1Object}
+ * - {@link KJUR.asn1.DERAbstractString}
+ * - {@link KJUR.asn1.DERAbstractTime}
+ * - {@link KJUR.asn1.DERAbstractStructured}
+ * - {@link KJUR.asn1.DERTaggedObject}
+ *
+ * SUB NAME SPACES
+ *
+ * - {@link KJUR.asn1.cades} - CAdES long term signature format
+ * - {@link KJUR.asn1.cms} - Cryptographic Message Syntax
+ * - {@link KJUR.asn1.csr} - Certificate Signing Request (CSR/PKCS#10)
+ * - {@link KJUR.asn1.tsp} - RFC 3161 Timestamping Protocol Format
+ * - {@link KJUR.asn1.x509} - RFC 5280 X.509 certificate and CRL
+ *
+ *
+ * NOTE: Please ignore method summary and document of this namespace.
+ * This caused by a bug of jsdoc2.
+ * @name KJUR.asn1
+ * @namespace
+ */
+if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {};
+
+/**
+ * ASN1 utilities class
+ * @name KJUR.asn1.ASN1Util
+ * @class ASN1 utilities class
+ * @since asn1 1.0.2
+ */
+KJUR.asn1.ASN1Util = new function() {
+ this.integerToByteHex = function(i) {
+ var h = i.toString(16);
+ if ((h.length % 2) == 1) h = '0' + h;
+ return h;
+ };
+ this.bigIntToMinTwosComplementsHex = function(bigIntegerValue) {
+ var h = bigIntegerValue.toString(16);
+ if (h.substr(0, 1) != '-') {
+ if (h.length % 2 == 1) {
+ h = '0' + h;
+ } else {
+ if (! h.match(/^[0-7]/)) {
+ h = '00' + h;
+ }
+ }
+ } else {
+ var hPos = h.substr(1);
+ var xorLen = hPos.length;
+ if (xorLen % 2 == 1) {
+ xorLen += 1;
+ } else {
+ if (! h.match(/^[0-7]/)) {
+ xorLen += 2;
+ }
+ }
+ var hMask = '';
+ for (var i = 0; i < xorLen; i++) {
+ hMask += 'f';
+ }
+ var biMask = new BigInteger(hMask, 16);
+ var biNeg = biMask.xor(bigIntegerValue).add(BigInteger.ONE);
+ h = biNeg.toString(16).replace(/^-/, '');
+ }
+ return h;
+ };
+ /**
+ * get PEM string from hexadecimal data and header string
+ * @name getPEMStringFromHex
+ * @memberOf KJUR.asn1.ASN1Util
+ * @function
+ * @param {String} dataHex hexadecimal string of PEM body
+ * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY')
+ * @return {String} PEM formatted string of input data
+ * @description
+ * This method converts a hexadecimal string to a PEM string with
+ * a specified header. Its line break will be CRLF("\r\n").
+ * @example
+ * var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex('616161', 'RSA PRIVATE KEY');
+ * // value of pem will be:
+ * -----BEGIN PRIVATE KEY-----
+ * YWFh
+ * -----END PRIVATE KEY-----
+ */
+ this.getPEMStringFromHex = function(dataHex, pemHeader) {
+ return hextopem(dataHex, pemHeader);
+ };
+
+ /**
+ * generate ASN1Object specifed by JSON parameters
+ * @name newObject
+ * @memberOf KJUR.asn1.ASN1Util
+ * @function
+ * @param {Array} param JSON parameter to generate ASN1Object
+ * @return {KJUR.asn1.ASN1Object} generated object
+ * @since asn1 1.0.3
+ * @description
+ * generate any ASN1Object specified by JSON param
+ * including ASN.1 primitive or structured.
+ * Generally 'param' can be described as follows:
+ *
+ * {TYPE-OF-ASNOBJ: ASN1OBJ-PARAMETER}
+ *
+ * 'TYPE-OF-ASN1OBJ' can be one of following symbols:
+ *
+ * - 'bool' - DERBoolean
+ * - 'int' - DERInteger
+ * - 'bitstr' - DERBitString
+ * - 'octstr' - DEROctetString
+ * - 'null' - DERNull
+ * - 'oid' - DERObjectIdentifier
+ * - 'enum' - DEREnumerated
+ * - 'utf8str' - DERUTF8String
+ * - 'numstr' - DERNumericString
+ * - 'prnstr' - DERPrintableString
+ * - 'telstr' - DERTeletexString
+ * - 'ia5str' - DERIA5String
+ * - 'utctime' - DERUTCTime
+ * - 'gentime' - DERGeneralizedTime
+ * - 'seq' - DERSequence
+ * - 'set' - DERSet
+ * - 'tag' - DERTaggedObject
+ *
+ * @example
+ * newObject({'prnstr': 'aaa'});
+ * newObject({'seq': [{'int': 3}, {'prnstr': 'aaa'}]})
+ * // ASN.1 Tagged Object
+ * newObject({'tag': {'tag': 'a1',
+ * 'explicit': true,
+ * 'obj': {'seq': [{'int': 3}, {'prnstr': 'aaa'}]}}});
+ * // more simple representation of ASN.1 Tagged Object
+ * newObject({'tag': ['a1',
+ * true,
+ * {'seq': [
+ * {'int': 3},
+ * {'prnstr': 'aaa'}]}
+ * ]});
+ */
+ this.newObject = function(param) {
+ var _KJUR = KJUR,
+ _KJUR_asn1 = _KJUR.asn1,
+ _DERBoolean = _KJUR_asn1.DERBoolean,
+ _DERInteger = _KJUR_asn1.DERInteger,
+ _DERBitString = _KJUR_asn1.DERBitString,
+ _DEROctetString = _KJUR_asn1.DEROctetString,
+ _DERNull = _KJUR_asn1.DERNull,
+ _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier,
+ _DEREnumerated = _KJUR_asn1.DEREnumerated,
+ _DERUTF8String = _KJUR_asn1.DERUTF8String,
+ _DERNumericString = _KJUR_asn1.DERNumericString,
+ _DERPrintableString = _KJUR_asn1.DERPrintableString,
+ _DERTeletexString = _KJUR_asn1.DERTeletexString,
+ _DERIA5String = _KJUR_asn1.DERIA5String,
+ _DERUTCTime = _KJUR_asn1.DERUTCTime,
+ _DERGeneralizedTime = _KJUR_asn1.DERGeneralizedTime,
+ _DERSequence = _KJUR_asn1.DERSequence,
+ _DERSet = _KJUR_asn1.DERSet,
+ _DERTaggedObject = _KJUR_asn1.DERTaggedObject,
+ _newObject = _KJUR_asn1.ASN1Util.newObject;
+
+ var keys = Object.keys(param);
+ if (keys.length != 1)
+ throw "key of param shall be only one.";
+ var key = keys[0];
+
+ if (":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1)
+ throw "undefined key: " + key;
+
+ if (key == "bool") return new _DERBoolean(param[key]);
+ if (key == "int") return new _DERInteger(param[key]);
+ if (key == "bitstr") return new _DERBitString(param[key]);
+ if (key == "octstr") return new _DEROctetString(param[key]);
+ if (key == "null") return new _DERNull(param[key]);
+ if (key == "oid") return new _DERObjectIdentifier(param[key]);
+ if (key == "enum") return new _DEREnumerated(param[key]);
+ if (key == "utf8str") return new _DERUTF8String(param[key]);
+ if (key == "numstr") return new _DERNumericString(param[key]);
+ if (key == "prnstr") return new _DERPrintableString(param[key]);
+ if (key == "telstr") return new _DERTeletexString(param[key]);
+ if (key == "ia5str") return new _DERIA5String(param[key]);
+ if (key == "utctime") return new _DERUTCTime(param[key]);
+ if (key == "gentime") return new _DERGeneralizedTime(param[key]);
+
+ if (key == "seq") {
+ var paramList = param[key];
+ var a = [];
+ for (var i = 0; i < paramList.length; i++) {
+ var asn1Obj = _newObject(paramList[i]);
+ a.push(asn1Obj);
+ }
+ return new _DERSequence({'array': a});
+ }
+
+ if (key == "set") {
+ var paramList = param[key];
+ var a = [];
+ for (var i = 0; i < paramList.length; i++) {
+ var asn1Obj = _newObject(paramList[i]);
+ a.push(asn1Obj);
+ }
+ return new _DERSet({'array': a});
+ }
+
+ if (key == "tag") {
+ var tagParam = param[key];
+ if (Object.prototype.toString.call(tagParam) === '[object Array]' &&
+ tagParam.length == 3) {
+ var obj = _newObject(tagParam[2]);
+ return new _DERTaggedObject({tag: tagParam[0],
+ explicit: tagParam[1],
+ obj: obj});
+ } else {
+ var newParam = {};
+ if (tagParam.explicit !== undefined)
+ newParam.explicit = tagParam.explicit;
+ if (tagParam.tag !== undefined)
+ newParam.tag = tagParam.tag;
+ if (tagParam.obj === undefined)
+ throw "obj shall be specified for 'tag'.";
+ newParam.obj = _newObject(tagParam.obj);
+ return new _DERTaggedObject(newParam);
+ }
+ }
+ };
+
+ /**
+ * get encoded hexadecimal string of ASN1Object specifed by JSON parameters
+ * @name jsonToASN1HEX
+ * @memberOf KJUR.asn1.ASN1Util
+ * @function
+ * @param {Array} param JSON parameter to generate ASN1Object
+ * @return hexadecimal string of ASN1Object
+ * @since asn1 1.0.4
+ * @description
+ * As for ASN.1 object representation of JSON object,
+ * please see {@link newObject}.
+ * @example
+ * jsonToASN1HEX({'prnstr': 'aaa'});
+ */
+ this.jsonToASN1HEX = function(param) {
+ var asn1Obj = this.newObject(param);
+ return asn1Obj.getEncodedHex();
+ };
+};
+
+/**
+ * get dot noted oid number string from hexadecimal value of OID
+ * @name oidHexToInt
+ * @memberOf KJUR.asn1.ASN1Util
+ * @function
+ * @param {String} hex hexadecimal value of object identifier
+ * @return {String} dot noted string of object identifier
+ * @since jsrsasign 4.8.3 asn1 1.0.7
+ * @description
+ * This static method converts from hexadecimal string representation of
+ * ASN.1 value of object identifier to oid number string.
+ * @example
+ * KJUR.asn1.ASN1Util.oidHexToInt('550406') → "2.5.4.6"
+ */
+KJUR.asn1.ASN1Util.oidHexToInt = function(hex) {
+ var s = "";
+ var i01 = parseInt(hex.substr(0, 2), 16);
+ var i0 = Math.floor(i01 / 40);
+ var i1 = i01 % 40;
+ var s = i0 + "." + i1;
+
+ var binbuf = "";
+ for (var i = 2; i < hex.length; i += 2) {
+ var value = parseInt(hex.substr(i, 2), 16);
+ var bin = ("00000000" + value.toString(2)).slice(- 8);
+ binbuf = binbuf + bin.substr(1, 7);
+ if (bin.substr(0, 1) == "0") {
+ var bi = new BigInteger(binbuf, 2);
+ s = s + "." + bi.toString(10);
+ binbuf = "";
+ }
+ };
+
+ return s;
+};
+
+/**
+ * get hexadecimal value of object identifier from dot noted oid value
+ * @name oidIntToHex
+ * @memberOf KJUR.asn1.ASN1Util
+ * @function
+ * @param {String} oidString dot noted string of object identifier
+ * @return {String} hexadecimal value of object identifier
+ * @since jsrsasign 4.8.3 asn1 1.0.7
+ * @description
+ * This static method converts from object identifier value string.
+ * to hexadecimal string representation of it.
+ * @example
+ * KJUR.asn1.ASN1Util.oidIntToHex("2.5.4.6") → "550406"
+ */
+KJUR.asn1.ASN1Util.oidIntToHex = function(oidString) {
+ var itox = function(i) {
+ var h = i.toString(16);
+ if (h.length == 1) h = '0' + h;
+ return h;
+ };
+
+ var roidtox = function(roid) {
+ var h = '';
+ var bi = new BigInteger(roid, 10);
+ var b = bi.toString(2);
+ var padLen = 7 - b.length % 7;
+ if (padLen == 7) padLen = 0;
+ var bPad = '';
+ for (var i = 0; i < padLen; i++) bPad += '0';
+ b = bPad + b;
+ for (var i = 0; i < b.length - 1; i += 7) {
+ var b8 = b.substr(i, 7);
+ if (i != b.length - 7) b8 = '1' + b8;
+ h += itox(parseInt(b8, 2));
+ }
+ return h;
+ };
+
+ if (! oidString.match(/^[0-9.]+$/)) {
+ throw "malformed oid string: " + oidString;
+ }
+ var h = '';
+ var a = oidString.split('.');
+ var i0 = parseInt(a[0]) * 40 + parseInt(a[1]);
+ h += itox(i0);
+ a.splice(0, 2);
+ for (var i = 0; i < a.length; i++) {
+ h += roidtox(a[i]);
+ }
+ return h;
+};
+
+
+// ********************************************************************
+// Abstract ASN.1 Classes
+// ********************************************************************
+
+// ********************************************************************
+
+/**
+ * base class for ASN.1 DER encoder object
+ * @name KJUR.asn1.ASN1Object
+ * @class base class for ASN.1 DER encoder object
+ * @property {Boolean} isModified flag whether internal data was changed
+ * @property {String} hTLV hexadecimal string of ASN.1 TLV
+ * @property {String} hT hexadecimal string of ASN.1 TLV tag(T)
+ * @property {String} hL hexadecimal string of ASN.1 TLV length(L)
+ * @property {String} hV hexadecimal string of ASN.1 TLV value(V)
+ * @description
+ */
+KJUR.asn1.ASN1Object = function() {
+ var isModified = true;
+ var hTLV = null;
+ var hT = '00';
+ var hL = '00';
+ var hV = '';
+
+ /**
+ * get hexadecimal ASN.1 TLV length(L) bytes from TLV value(V)
+ * @name getLengthHexFromValue
+ * @memberOf KJUR.asn1.ASN1Object#
+ * @function
+ * @return {String} hexadecimal string of ASN.1 TLV length(L)
+ */
+ this.getLengthHexFromValue = function() {
+ if (typeof this.hV == "undefined" || this.hV == null) {
+ throw "this.hV is null or undefined.";
+ }
+ if (this.hV.length % 2 == 1) {
+ throw "value hex must be even length: n=" + hV.length + ",v=" + this.hV;
+ }
+ var n = this.hV.length / 2;
+ var hN = n.toString(16);
+ if (hN.length % 2 == 1) {
+ hN = "0" + hN;
+ }
+ if (n < 128) {
+ return hN;
+ } else {
+ var hNlen = hN.length / 2;
+ if (hNlen > 15) {
+ throw "ASN.1 length too long to represent by 8x: n = " + n.toString(16);
+ }
+ var head = 128 + hNlen;
+ return head.toString(16) + hN;
+ }
+ };
+
+ /**
+ * get hexadecimal string of ASN.1 TLV bytes
+ * @name getEncodedHex
+ * @memberOf KJUR.asn1.ASN1Object#
+ * @function
+ * @return {String} hexadecimal string of ASN.1 TLV
+ */
+ this.getEncodedHex = function() {
+ if (this.hTLV == null || this.isModified) {
+ this.hV = this.getFreshValueHex();
+ this.hL = this.getLengthHexFromValue();
+ this.hTLV = this.hT + this.hL + this.hV;
+ this.isModified = false;
+ //alert("first time: " + this.hTLV);
+ }
+ return this.hTLV;
+ };
+
+ /**
+ * get hexadecimal string of ASN.1 TLV value(V) bytes
+ * @name getValueHex
+ * @memberOf KJUR.asn1.ASN1Object#
+ * @function
+ * @return {String} hexadecimal string of ASN.1 TLV value(V) bytes
+ */
+ this.getValueHex = function() {
+ this.getEncodedHex();
+ return this.hV;
+ }
+
+ this.getFreshValueHex = function() {
+ return '';
+ };
+};
+
+// == BEGIN DERAbstractString ================================================
+/**
+ * base class for ASN.1 DER string classes
+ * @name KJUR.asn1.DERAbstractString
+ * @class base class for ASN.1 DER string classes
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @property {String} s internal string of value
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - str - specify initial ASN.1 value(V) by a string
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ *
+ * NOTE: 'params' can be omitted.
+ */
+KJUR.asn1.DERAbstractString = function(params) {
+ KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
+ var s = null;
+ var hV = null;
+
+ /**
+ * get string value of this string object
+ * @name getString
+ * @memberOf KJUR.asn1.DERAbstractString#
+ * @function
+ * @return {String} string value of this string object
+ */
+ this.getString = function() {
+ return this.s;
+ };
+
+ /**
+ * set value by a string
+ * @name setString
+ * @memberOf KJUR.asn1.DERAbstractString#
+ * @function
+ * @param {String} newS value by a string to set
+ * @description
+ * This method set value by string.
+ * NOTE: This method assumes that the argument string is
+ * UTF-8 encoded even though ASN.1 primitive
+ * such as IA5String or PrintableString doesn't
+ * support all of UTF-8 characters.
+ * @example
+ * o = new KJUR.asn1.DERIA5String();
+ * o.setString("abc");
+ * o.setString("あいう");
+ */
+ this.setString = function(newS) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.s = newS;
+ this.hV = utf8tohex(this.s).toLowerCase();
+ };
+
+ /**
+ * set value by a hexadecimal string
+ * @name setStringHex
+ * @memberOf KJUR.asn1.DERAbstractString#
+ * @function
+ * @param {String} newHexString value by a hexadecimal string to set
+ */
+ this.setStringHex = function(newHexString) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.s = null;
+ this.hV = newHexString;
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params == "string") {
+ this.setString(params);
+ } else if (typeof params['str'] != "undefined") {
+ this.setString(params['str']);
+ } else if (typeof params['hex'] != "undefined") {
+ this.setStringHex(params['hex']);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERAbstractString, KJUR.asn1.ASN1Object);
+// == END DERAbstractString ================================================
+
+// == BEGIN DERAbstractTime ==================================================
+/**
+ * base class for ASN.1 DER Generalized/UTCTime class
+ * @name KJUR.asn1.DERAbstractTime
+ * @class base class for ASN.1 DER Generalized/UTCTime class
+ * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ * @see KJUR.asn1.ASN1Object - superclass
+ */
+KJUR.asn1.DERAbstractTime = function(params) {
+ KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);
+ var s = null;
+ var date = null;
+
+ // --- PRIVATE METHODS --------------------
+ this.localDateToUTC = function(d) {
+ utc = d.getTime() + (d.getTimezoneOffset() * 60000);
+ var utcDate = new Date(utc);
+ return utcDate;
+ };
+
+ /*
+ * format date string by Data object
+ * @name formatDate
+ * @memberOf KJUR.asn1.AbstractTime;
+ * @param {Date} dateObject
+ * @param {string} type 'utc' or 'gen'
+ * @param {boolean} withMillis flag for with millisections or not
+ * @description
+ * 'withMillis' flag is supported from asn1 1.0.6.
+ */
+ this.formatDate = function(dateObject, type, withMillis) {
+ var pad = this.zeroPadding;
+ var d = this.localDateToUTC(dateObject);
+ var year = String(d.getFullYear());
+ if (type == 'utc') year = year.substr(2, 2);
+ var month = pad(String(d.getMonth() + 1), 2);
+ var day = pad(String(d.getDate()), 2);
+ var hour = pad(String(d.getHours()), 2);
+ var min = pad(String(d.getMinutes()), 2);
+ var sec = pad(String(d.getSeconds()), 2);
+ var s = year + month + day + hour + min + sec;
+ if (withMillis === true) {
+ var millis = d.getMilliseconds();
+ if (millis != 0) {
+ var sMillis = pad(String(millis), 3);
+ sMillis = sMillis.replace(/[0]+$/, "");
+ s = s + "." + sMillis;
+ }
+ }
+ return s + "Z";
+ };
+
+ this.zeroPadding = function(s, len) {
+ if (s.length >= len) return s;
+ return new Array(len - s.length + 1).join('0') + s;
+ };
+
+ // --- PUBLIC METHODS --------------------
+ /**
+ * get string value of this string object
+ * @name getString
+ * @memberOf KJUR.asn1.DERAbstractTime#
+ * @function
+ * @return {String} string value of this time object
+ */
+ this.getString = function() {
+ return this.s;
+ };
+
+ /**
+ * set value by a string
+ * @name setString
+ * @memberOf KJUR.asn1.DERAbstractTime#
+ * @function
+ * @param {String} newS value by a string to set such like "130430235959Z"
+ */
+ this.setString = function(newS) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.s = newS;
+ this.hV = stohex(newS);
+ };
+
+ /**
+ * set value by a Date object
+ * @name setByDateValue
+ * @memberOf KJUR.asn1.DERAbstractTime#
+ * @function
+ * @param {Integer} year year of date (ex. 2013)
+ * @param {Integer} month month of date between 1 and 12 (ex. 12)
+ * @param {Integer} day day of month
+ * @param {Integer} hour hours of date
+ * @param {Integer} min minutes of date
+ * @param {Integer} sec seconds of date
+ */
+ this.setByDateValue = function(year, month, day, hour, min, sec) {
+ var dateObject = new Date(Date.UTC(year, month - 1, day, hour, min, sec, 0));
+ this.setByDate(dateObject);
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+};
+YAHOO.lang.extend(KJUR.asn1.DERAbstractTime, KJUR.asn1.ASN1Object);
+// == END DERAbstractTime ==================================================
+
+// == BEGIN DERAbstractStructured ============================================
+/**
+ * base class for ASN.1 DER structured class
+ * @name KJUR.asn1.DERAbstractStructured
+ * @class base class for ASN.1 DER structured class
+ * @property {Array} asn1Array internal array of ASN1Object
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ * @see KJUR.asn1.ASN1Object - superclass
+ */
+KJUR.asn1.DERAbstractStructured = function(params) {
+ KJUR.asn1.DERAbstractString.superclass.constructor.call(this);
+ var asn1Array = null;
+
+ /**
+ * set value by array of ASN1Object
+ * @name setByASN1ObjectArray
+ * @memberOf KJUR.asn1.DERAbstractStructured#
+ * @function
+ * @param {array} asn1ObjectArray array of ASN1Object to set
+ */
+ this.setByASN1ObjectArray = function(asn1ObjectArray) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.asn1Array = asn1ObjectArray;
+ };
+
+ /**
+ * append an ASN1Object to internal array
+ * @name appendASN1Object
+ * @memberOf KJUR.asn1.DERAbstractStructured#
+ * @function
+ * @param {ASN1Object} asn1Object to add
+ */
+ this.appendASN1Object = function(asn1Object) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.asn1Array.push(asn1Object);
+ };
+
+ this.asn1Array = new Array();
+ if (typeof params != "undefined") {
+ if (typeof params['array'] != "undefined") {
+ this.asn1Array = params['array'];
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERAbstractStructured, KJUR.asn1.ASN1Object);
+
+
+// ********************************************************************
+// ASN.1 Object Classes
+// ********************************************************************
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Boolean
+ * @name KJUR.asn1.DERBoolean
+ * @class class for ASN.1 DER Boolean
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ * @see KJUR.asn1.ASN1Object - superclass
+ */
+KJUR.asn1.DERBoolean = function() {
+ KJUR.asn1.DERBoolean.superclass.constructor.call(this);
+ this.hT = "01";
+ this.hTLV = "0101ff";
+};
+YAHOO.lang.extend(KJUR.asn1.DERBoolean, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Integer
+ * @name KJUR.asn1.DERInteger
+ * @class class for ASN.1 DER Integer
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - int - specify initial ASN.1 value(V) by integer value
+ * - bigint - specify initial ASN.1 value(V) by BigInteger object
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ *
+ * NOTE: 'params' can be omitted.
+ */
+KJUR.asn1.DERInteger = function(params) {
+ KJUR.asn1.DERInteger.superclass.constructor.call(this);
+ this.hT = "02";
+
+ /**
+ * set value by Tom Wu's BigInteger object
+ * @name setByBigInteger
+ * @memberOf KJUR.asn1.DERInteger#
+ * @function
+ * @param {BigInteger} bigIntegerValue to set
+ */
+ this.setByBigInteger = function(bigIntegerValue) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
+ };
+
+ /**
+ * set value by integer value
+ * @name setByInteger
+ * @memberOf KJUR.asn1.DERInteger
+ * @function
+ * @param {Integer} integer value to set
+ */
+ this.setByInteger = function(intValue) {
+ var bi = new BigInteger(String(intValue), 10);
+ this.setByBigInteger(bi);
+ };
+
+ /**
+ * set value by integer value
+ * @name setValueHex
+ * @memberOf KJUR.asn1.DERInteger#
+ * @function
+ * @param {String} hexadecimal string of integer value
+ * @description
+ *
+ * NOTE: Value shall be represented by minimum octet length of
+ * two's complement representation.
+ * @example
+ * new KJUR.asn1.DERInteger(123);
+ * new KJUR.asn1.DERInteger({'int': 123});
+ * new KJUR.asn1.DERInteger({'hex': '1fad'});
+ */
+ this.setValueHex = function(newHexString) {
+ this.hV = newHexString;
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params['bigint'] != "undefined") {
+ this.setByBigInteger(params['bigint']);
+ } else if (typeof params['int'] != "undefined") {
+ this.setByInteger(params['int']);
+ } else if (typeof params == "number") {
+ this.setByInteger(params);
+ } else if (typeof params['hex'] != "undefined") {
+ this.setValueHex(params['hex']);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERInteger, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER encoded BitString primitive
+ * @name KJUR.asn1.DERBitString
+ * @class class for ASN.1 DER encoded BitString primitive
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - bin - specify binary string (ex. '10111')
+ * - array - specify array of boolean (ex. [true,false,true,true])
+ * - hex - specify hexadecimal string of ASN.1 value(V) including unused bits
+ * - obj - specify {@link KJUR.asn1.ASN1Util.newObject}
+ * argument for "BitString encapsulates" structure.
+ *
+ * NOTE1: 'params' can be omitted.
+ * NOTE2: 'obj' parameter have been supported since
+ * asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25).
+ * @example
+ * // default constructor
+ * o = new KJUR.asn1.DERBitString();
+ * // initialize with binary string
+ * o = new KJUR.asn1.DERBitString({bin: "1011"});
+ * // initialize with boolean array
+ * o = new KJUR.asn1.DERBitString({array: [true,false,true,true]});
+ * // initialize with hexadecimal string (04 is unused bits)
+ * o = new KJUR.asn1.DEROctetString({hex: "04bac0"});
+ * // initialize with ASN1Util.newObject argument for encapsulated
+ * o = new KJUR.asn1.DERBitString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}});
+ * // above generates a ASN.1 data like this:
+ * // BIT STRING, encapsulates {
+ * // SEQUENCE {
+ * // INTEGER 3
+ * // PrintableString 'aaa'
+ * // }
+ * // }
+ */
+KJUR.asn1.DERBitString = function(params) {
+ if (params !== undefined && typeof params.obj !== "undefined") {
+ var o = KJUR.asn1.ASN1Util.newObject(params.obj);
+ params.hex = "00" + o.getEncodedHex();
+ }
+ KJUR.asn1.DERBitString.superclass.constructor.call(this);
+ this.hT = "03";
+
+ /**
+ * set ASN.1 value(V) by a hexadecimal string including unused bits
+ * @name setHexValueIncludingUnusedBits
+ * @memberOf KJUR.asn1.DERBitString#
+ * @function
+ * @param {String} newHexStringIncludingUnusedBits
+ */
+ this.setHexValueIncludingUnusedBits = function(newHexStringIncludingUnusedBits) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.hV = newHexStringIncludingUnusedBits;
+ };
+
+ /**
+ * set ASN.1 value(V) by unused bit and hexadecimal string of value
+ * @name setUnusedBitsAndHexValue
+ * @memberOf KJUR.asn1.DERBitString#
+ * @function
+ * @param {Integer} unusedBits
+ * @param {String} hValue
+ */
+ this.setUnusedBitsAndHexValue = function(unusedBits, hValue) {
+ if (unusedBits < 0 || 7 < unusedBits) {
+ throw "unused bits shall be from 0 to 7: u = " + unusedBits;
+ }
+ var hUnusedBits = "0" + unusedBits;
+ this.hTLV = null;
+ this.isModified = true;
+ this.hV = hUnusedBits + hValue;
+ };
+
+ /**
+ * set ASN.1 DER BitString by binary string
+ * @name setByBinaryString
+ * @memberOf KJUR.asn1.DERBitString#
+ * @function
+ * @param {String} binaryString binary value string (i.e. '10111')
+ * @description
+ * Its unused bits will be calculated automatically by length of
+ * 'binaryValue'.
+ * NOTE: Trailing zeros '0' will be ignored.
+ * @example
+ * o = new KJUR.asn1.DERBitString();
+ * o.setByBooleanArray("01011");
+ */
+ this.setByBinaryString = function(binaryString) {
+ binaryString = binaryString.replace(/0+$/, '');
+ var unusedBits = 8 - binaryString.length % 8;
+ if (unusedBits == 8) unusedBits = 0;
+ for (var i = 0; i <= unusedBits; i++) {
+ binaryString += '0';
+ }
+ var h = '';
+ for (var i = 0; i < binaryString.length - 1; i += 8) {
+ var b = binaryString.substr(i, 8);
+ var x = parseInt(b, 2).toString(16);
+ if (x.length == 1) x = '0' + x;
+ h += x;
+ }
+ this.hTLV = null;
+ this.isModified = true;
+ this.hV = '0' + unusedBits + h;
+ };
+
+ /**
+ * set ASN.1 TLV value(V) by an array of boolean
+ * @name setByBooleanArray
+ * @memberOf KJUR.asn1.DERBitString#
+ * @function
+ * @param {array} booleanArray array of boolean (ex. [true, false, true])
+ * @description
+ * NOTE: Trailing falses will be ignored in the ASN.1 DER Object.
+ * @example
+ * o = new KJUR.asn1.DERBitString();
+ * o.setByBooleanArray([false, true, false, true, true]);
+ */
+ this.setByBooleanArray = function(booleanArray) {
+ var s = '';
+ for (var i = 0; i < booleanArray.length; i++) {
+ if (booleanArray[i] == true) {
+ s += '1';
+ } else {
+ s += '0';
+ }
+ }
+ this.setByBinaryString(s);
+ };
+
+ /**
+ * generate an array of falses with specified length
+ * @name newFalseArray
+ * @memberOf KJUR.asn1.DERBitString
+ * @function
+ * @param {Integer} nLength length of array to generate
+ * @return {array} array of boolean falses
+ * @description
+ * This static method may be useful to initialize boolean array.
+ * @example
+ * o = new KJUR.asn1.DERBitString();
+ * o.newFalseArray(3) → [false, false, false]
+ */
+ this.newFalseArray = function(nLength) {
+ var a = new Array(nLength);
+ for (var i = 0; i < nLength; i++) {
+ a[i] = false;
+ }
+ return a;
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params == "string" && params.toLowerCase().match(/^[0-9a-f]+$/)) {
+ this.setHexValueIncludingUnusedBits(params);
+ } else if (typeof params['hex'] != "undefined") {
+ this.setHexValueIncludingUnusedBits(params['hex']);
+ } else if (typeof params['bin'] != "undefined") {
+ this.setByBinaryString(params['bin']);
+ } else if (typeof params['array'] != "undefined") {
+ this.setByBooleanArray(params['array']);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERBitString, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER OctetString
+ * @name KJUR.asn1.DEROctetString
+ * @class class for ASN.1 DER OctetString
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * This class provides ASN.1 OctetString simple type.
+ * Supported "params" attributes are:
+ *
+ * - str - to set a string as a value
+ * - hex - to set a hexadecimal string as a value
+ * - obj - to set a encapsulated ASN.1 value by JSON object
+ * which is defined in {@link KJUR.asn1.ASN1Util.newObject}
+ *
+ * NOTE: A parameter 'obj' have been supported
+ * for "OCTET STRING, encapsulates" structure.
+ * since asn1 1.0.11, jsrsasign 6.1.1 (2016-Sep-25).
+ * @see KJUR.asn1.DERAbstractString - superclass
+ * @example
+ * // default constructor
+ * o = new KJUR.asn1.DEROctetString();
+ * // initialize with string
+ * o = new KJUR.asn1.DEROctetString({str: "aaa"});
+ * // initialize with hexadecimal string
+ * o = new KJUR.asn1.DEROctetString({hex: "616161"});
+ * // initialize with ASN1Util.newObject argument
+ * o = new KJUR.asn1.DEROctetString({obj: {seq: [{int: 3}, {prnstr: 'aaa'}]}});
+ * // above generates a ASN.1 data like this:
+ * // OCTET STRING, encapsulates {
+ * // SEQUENCE {
+ * // INTEGER 3
+ * // PrintableString 'aaa'
+ * // }
+ * // }
+ */
+KJUR.asn1.DEROctetString = function(params) {
+ if (params !== undefined && typeof params.obj !== "undefined") {
+ var o = KJUR.asn1.ASN1Util.newObject(params.obj);
+ params.hex = o.getEncodedHex();
+ }
+ KJUR.asn1.DEROctetString.superclass.constructor.call(this, params);
+ this.hT = "04";
+};
+YAHOO.lang.extend(KJUR.asn1.DEROctetString, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Null
+ * @name KJUR.asn1.DERNull
+ * @class class for ASN.1 DER Null
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ * @see KJUR.asn1.ASN1Object - superclass
+ */
+KJUR.asn1.DERNull = function() {
+ KJUR.asn1.DERNull.superclass.constructor.call(this);
+ this.hT = "05";
+ this.hTLV = "0500";
+};
+YAHOO.lang.extend(KJUR.asn1.DERNull, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER ObjectIdentifier
+ * @name KJUR.asn1.DERObjectIdentifier
+ * @class class for ASN.1 DER ObjectIdentifier
+ * @param {Array} params associative array of parameters (ex. {'oid': '2.5.4.5'})
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - oid - specify initial ASN.1 value(V) by a oid string (ex. 2.5.4.13)
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ *
+ * NOTE: 'params' can be omitted.
+ */
+KJUR.asn1.DERObjectIdentifier = function(params) {
+ var itox = function(i) {
+ var h = i.toString(16);
+ if (h.length == 1) h = '0' + h;
+ return h;
+ };
+ var roidtox = function(roid) {
+ var h = '';
+ var bi = new BigInteger(roid, 10);
+ var b = bi.toString(2);
+ var padLen = 7 - b.length % 7;
+ if (padLen == 7) padLen = 0;
+ var bPad = '';
+ for (var i = 0; i < padLen; i++) bPad += '0';
+ b = bPad + b;
+ for (var i = 0; i < b.length - 1; i += 7) {
+ var b8 = b.substr(i, 7);
+ if (i != b.length - 7) b8 = '1' + b8;
+ h += itox(parseInt(b8, 2));
+ }
+ return h;
+ }
+
+ KJUR.asn1.DERObjectIdentifier.superclass.constructor.call(this);
+ this.hT = "06";
+
+ /**
+ * set value by a hexadecimal string
+ * @name setValueHex
+ * @memberOf KJUR.asn1.DERObjectIdentifier#
+ * @function
+ * @param {String} newHexString hexadecimal value of OID bytes
+ */
+ this.setValueHex = function(newHexString) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.s = null;
+ this.hV = newHexString;
+ };
+
+ /**
+ * set value by a OID string
+ * @name setValueOidString
+ * @memberOf KJUR.asn1.DERObjectIdentifier#
+ * @function
+ * @param {String} oidString OID string (ex. 2.5.4.13)
+ * @example
+ * o = new KJUR.asn1.DERObjectIdentifier();
+ * o.setValueOidString("2.5.4.13");
+ */
+ this.setValueOidString = function(oidString) {
+ if (! oidString.match(/^[0-9.]+$/)) {
+ throw "malformed oid string: " + oidString;
+ }
+ var h = '';
+ var a = oidString.split('.');
+ var i0 = parseInt(a[0]) * 40 + parseInt(a[1]);
+ h += itox(i0);
+ a.splice(0, 2);
+ for (var i = 0; i < a.length; i++) {
+ h += roidtox(a[i]);
+ }
+ this.hTLV = null;
+ this.isModified = true;
+ this.s = null;
+ this.hV = h;
+ };
+
+ /**
+ * set value by a OID name
+ * @name setValueName
+ * @memberOf KJUR.asn1.DERObjectIdentifier#
+ * @function
+ * @param {String} oidName OID name (ex. 'serverAuth')
+ * @since 1.0.1
+ * @description
+ * OID name shall be defined in 'KJUR.asn1.x509.OID.name2oidList'.
+ * Otherwise raise error.
+ * @example
+ * o = new KJUR.asn1.DERObjectIdentifier();
+ * o.setValueName("serverAuth");
+ */
+ this.setValueName = function(oidName) {
+ var oid = KJUR.asn1.x509.OID.name2oid(oidName);
+ if (oid !== '') {
+ this.setValueOidString(oid);
+ } else {
+ throw "DERObjectIdentifier oidName undefined: " + oidName;
+ }
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (params !== undefined) {
+ if (typeof params === "string") {
+ if (params.match(/^[0-2].[0-9.]+$/)) {
+ this.setValueOidString(params);
+ } else {
+ this.setValueName(params);
+ }
+ } else if (params.oid !== undefined) {
+ this.setValueOidString(params.oid);
+ } else if (params.hex !== undefined) {
+ this.setValueHex(params.hex);
+ } else if (params.name !== undefined) {
+ this.setValueName(params.name);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Enumerated
+ * @name KJUR.asn1.DEREnumerated
+ * @class class for ASN.1 DER Enumerated
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - int - specify initial ASN.1 value(V) by integer value
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ *
+ * NOTE: 'params' can be omitted.
+ * @example
+ * new KJUR.asn1.DEREnumerated(123);
+ * new KJUR.asn1.DEREnumerated({int: 123});
+ * new KJUR.asn1.DEREnumerated({hex: '1fad'});
+ */
+KJUR.asn1.DEREnumerated = function(params) {
+ KJUR.asn1.DEREnumerated.superclass.constructor.call(this);
+ this.hT = "0a";
+
+ /**
+ * set value by Tom Wu's BigInteger object
+ * @name setByBigInteger
+ * @memberOf KJUR.asn1.DEREnumerated#
+ * @function
+ * @param {BigInteger} bigIntegerValue to set
+ */
+ this.setByBigInteger = function(bigIntegerValue) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
+ };
+
+ /**
+ * set value by integer value
+ * @name setByInteger
+ * @memberOf KJUR.asn1.DEREnumerated#
+ * @function
+ * @param {Integer} integer value to set
+ */
+ this.setByInteger = function(intValue) {
+ var bi = new BigInteger(String(intValue), 10);
+ this.setByBigInteger(bi);
+ };
+
+ /**
+ * set value by integer value
+ * @name setValueHex
+ * @memberOf KJUR.asn1.DEREnumerated#
+ * @function
+ * @param {String} hexadecimal string of integer value
+ * @description
+ *
+ * NOTE: Value shall be represented by minimum octet length of
+ * two's complement representation.
+ */
+ this.setValueHex = function(newHexString) {
+ this.hV = newHexString;
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params['int'] != "undefined") {
+ this.setByInteger(params['int']);
+ } else if (typeof params == "number") {
+ this.setByInteger(params);
+ } else if (typeof params['hex'] != "undefined") {
+ this.setValueHex(params['hex']);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER UTF8String
+ * @name KJUR.asn1.DERUTF8String
+ * @class class for ASN.1 DER UTF8String
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * @see KJUR.asn1.DERAbstractString - superclass
+ */
+KJUR.asn1.DERUTF8String = function(params) {
+ KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params);
+ this.hT = "0c";
+};
+YAHOO.lang.extend(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER NumericString
+ * @name KJUR.asn1.DERNumericString
+ * @class class for ASN.1 DER NumericString
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * @see KJUR.asn1.DERAbstractString - superclass
+ */
+KJUR.asn1.DERNumericString = function(params) {
+ KJUR.asn1.DERNumericString.superclass.constructor.call(this, params);
+ this.hT = "12";
+};
+YAHOO.lang.extend(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER PrintableString
+ * @name KJUR.asn1.DERPrintableString
+ * @class class for ASN.1 DER PrintableString
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * @see KJUR.asn1.DERAbstractString - superclass
+ */
+KJUR.asn1.DERPrintableString = function(params) {
+ KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params);
+ this.hT = "13";
+};
+YAHOO.lang.extend(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER TeletexString
+ * @name KJUR.asn1.DERTeletexString
+ * @class class for ASN.1 DER TeletexString
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * @see KJUR.asn1.DERAbstractString - superclass
+ */
+KJUR.asn1.DERTeletexString = function(params) {
+ KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params);
+ this.hT = "14";
+};
+YAHOO.lang.extend(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER IA5String
+ * @name KJUR.asn1.DERIA5String
+ * @class class for ASN.1 DER IA5String
+ * @param {Array} params associative array of parameters (ex. {'str': 'aaa'})
+ * @extends KJUR.asn1.DERAbstractString
+ * @description
+ * @see KJUR.asn1.DERAbstractString - superclass
+ */
+KJUR.asn1.DERIA5String = function(params) {
+ KJUR.asn1.DERIA5String.superclass.constructor.call(this, params);
+ this.hT = "16";
+};
+YAHOO.lang.extend(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER UTCTime
+ * @name KJUR.asn1.DERUTCTime
+ * @class class for ASN.1 DER UTCTime
+ * @param {Array} params associative array of parameters (ex. {'str': '130430235959Z'})
+ * @extends KJUR.asn1.DERAbstractTime
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - str - specify initial ASN.1 value(V) by a string (ex.'130430235959Z')
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ * - date - specify Date object.
+ *
+ * NOTE: 'params' can be omitted.
+ * EXAMPLES
+ * @example
+ * d1 = new KJUR.asn1.DERUTCTime();
+ * d1.setString('130430125959Z');
+ *
+ * d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'});
+ * d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))});
+ * d4 = new KJUR.asn1.DERUTCTime('130430125959Z');
+ */
+KJUR.asn1.DERUTCTime = function(params) {
+ KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params);
+ this.hT = "17";
+
+ /**
+ * set value by a Date object
+ * @name setByDate
+ * @memberOf KJUR.asn1.DERUTCTime#
+ * @function
+ * @param {Date} dateObject Date object to set ASN.1 value(V)
+ * @example
+ * o = new KJUR.asn1.DERUTCTime();
+ * o.setByDate(new Date("2016/12/31"));
+ */
+ this.setByDate = function(dateObject) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.date = dateObject;
+ this.s = this.formatDate(this.date, 'utc');
+ this.hV = stohex(this.s);
+ };
+
+ this.getFreshValueHex = function() {
+ if (typeof this.date == "undefined" && typeof this.s == "undefined") {
+ this.date = new Date();
+ this.s = this.formatDate(this.date, 'utc');
+ this.hV = stohex(this.s);
+ }
+ return this.hV;
+ };
+
+ if (params !== undefined) {
+ if (params.str !== undefined) {
+ this.setString(params.str);
+ } else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
+ this.setString(params);
+ } else if (params.hex !== undefined) {
+ this.setStringHex(params.hex);
+ } else if (params.date !== undefined) {
+ this.setByDate(params.date);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER GeneralizedTime
+ * @name KJUR.asn1.DERGeneralizedTime
+ * @class class for ASN.1 DER GeneralizedTime
+ * @param {Array} params associative array of parameters (ex. {'str': '20130430235959Z'})
+ * @property {Boolean} withMillis flag to show milliseconds or not
+ * @extends KJUR.asn1.DERAbstractTime
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - str - specify initial ASN.1 value(V) by a string (ex.'20130430235959Z')
+ * - hex - specify initial ASN.1 value(V) by a hexadecimal string
+ * - date - specify Date object.
+ * - millis - specify flag to show milliseconds (from 1.0.6)
+ *
+ * NOTE1: 'params' can be omitted.
+ * NOTE2: 'withMillis' property is supported from asn1 1.0.6.
+ */
+KJUR.asn1.DERGeneralizedTime = function(params) {
+ KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
+ this.hT = "18";
+ this.withMillis = false;
+
+ /**
+ * set value by a Date object
+ * @name setByDate
+ * @memberOf KJUR.asn1.DERGeneralizedTime#
+ * @function
+ * @param {Date} dateObject Date object to set ASN.1 value(V)
+ * @example
+ * When you specify UTC time, use 'Date.UTC' method like this:
+ * o1 = new DERUTCTime();
+ * o1.setByDate(date);
+ *
+ * date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59
+ */
+ this.setByDate = function(dateObject) {
+ this.hTLV = null;
+ this.isModified = true;
+ this.date = dateObject;
+ this.s = this.formatDate(this.date, 'gen', this.withMillis);
+ this.hV = stohex(this.s);
+ };
+
+ this.getFreshValueHex = function() {
+ if (this.date === undefined && this.s === undefined) {
+ this.date = new Date();
+ this.s = this.formatDate(this.date, 'gen', this.withMillis);
+ this.hV = stohex(this.s);
+ }
+ return this.hV;
+ };
+
+ if (params !== undefined) {
+ if (params.str !== undefined) {
+ this.setString(params.str);
+ } else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
+ this.setString(params);
+ } else if (params.hex !== undefined) {
+ this.setStringHex(params.hex);
+ } else if (params.date !== undefined) {
+ this.setByDate(params.date);
+ }
+ if (params.millis === true) {
+ this.withMillis = true;
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Sequence
+ * @name KJUR.asn1.DERSequence
+ * @class class for ASN.1 DER Sequence
+ * @extends KJUR.asn1.DERAbstractStructured
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - array - specify array of ASN1Object to set elements of content
+ *
+ * NOTE: 'params' can be omitted.
+ */
+KJUR.asn1.DERSequence = function(params) {
+ KJUR.asn1.DERSequence.superclass.constructor.call(this, params);
+ this.hT = "30";
+ this.getFreshValueHex = function() {
+ var h = '';
+ for (var i = 0; i < this.asn1Array.length; i++) {
+ var asn1Obj = this.asn1Array[i];
+ h += asn1Obj.getEncodedHex();
+ }
+ this.hV = h;
+ return this.hV;
+ };
+};
+YAHOO.lang.extend(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER Set
+ * @name KJUR.asn1.DERSet
+ * @class class for ASN.1 DER Set
+ * @extends KJUR.asn1.DERAbstractStructured
+ * @description
+ *
+ * As for argument 'params' for constructor, you can specify one of
+ * following properties:
+ *
+ * - array - specify array of ASN1Object to set elements of content
+ * - sortflag - flag for sort (default: true). ASN.1 BER is not sorted in 'SET OF'.
+ *
+ * NOTE1: 'params' can be omitted.
+ * NOTE2: sortflag is supported since 1.0.5.
+ */
+KJUR.asn1.DERSet = function(params) {
+ KJUR.asn1.DERSet.superclass.constructor.call(this, params);
+ this.hT = "31";
+ this.sortFlag = true; // item shall be sorted only in ASN.1 DER
+ this.getFreshValueHex = function() {
+ var a = new Array();
+ for (var i = 0; i < this.asn1Array.length; i++) {
+ var asn1Obj = this.asn1Array[i];
+ a.push(asn1Obj.getEncodedHex());
+ }
+ if (this.sortFlag == true) a.sort();
+ this.hV = a.join('');
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params.sortflag != "undefined" &&
+ params.sortflag == false)
+ this.sortFlag = false;
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured);
+
+// ********************************************************************
+/**
+ * class for ASN.1 DER TaggedObject
+ * @name KJUR.asn1.DERTaggedObject
+ * @class class for ASN.1 DER TaggedObject
+ * @extends KJUR.asn1.ASN1Object
+ * @description
+ *
+ * Parameter 'tagNoNex' is ASN.1 tag(T) value for this object.
+ * For example, if you find '[1]' tag in a ASN.1 dump,
+ * 'tagNoHex' will be 'a1'.
+ *
+ * As for optional argument 'params' for constructor, you can specify *ANY* of
+ * following properties:
+ *
+ * - explicit - specify true if this is explicit tag otherwise false
+ * (default is 'true').
+ * - tag - specify tag (default is 'a0' which means [0])
+ * - obj - specify ASN1Object which is tagged
+ *
+ * @example
+ * d1 = new KJUR.asn1.DERUTF8String({'str':'a'});
+ * d2 = new KJUR.asn1.DERTaggedObject({'obj': d1});
+ * hex = d2.getEncodedHex();
+ */
+KJUR.asn1.DERTaggedObject = function(params) {
+ KJUR.asn1.DERTaggedObject.superclass.constructor.call(this);
+ this.hT = "a0";
+ this.hV = '';
+ this.isExplicit = true;
+ this.asn1Object = null;
+
+ /**
+ * set value by an ASN1Object
+ * @name setString
+ * @memberOf KJUR.asn1.DERTaggedObject#
+ * @function
+ * @param {Boolean} isExplicitFlag flag for explicit/implicit tag
+ * @param {Integer} tagNoHex hexadecimal string of ASN.1 tag
+ * @param {ASN1Object} asn1Object ASN.1 to encapsulate
+ */
+ this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) {
+ this.hT = tagNoHex;
+ this.isExplicit = isExplicitFlag;
+ this.asn1Object = asn1Object;
+ if (this.isExplicit) {
+ this.hV = this.asn1Object.getEncodedHex();
+ this.hTLV = null;
+ this.isModified = true;
+ } else {
+ this.hV = null;
+ this.hTLV = asn1Object.getEncodedHex();
+ this.hTLV = this.hTLV.replace(/^../, tagNoHex);
+ this.isModified = false;
+ }
+ };
+
+ this.getFreshValueHex = function() {
+ return this.hV;
+ };
+
+ if (typeof params != "undefined") {
+ if (typeof params['tag'] != "undefined") {
+ this.hT = params['tag'];
+ }
+ if (typeof params['explicit'] != "undefined") {
+ this.isExplicit = params['explicit'];
+ }
+ if (typeof params['obj'] != "undefined") {
+ this.asn1Object = params['obj'];
+ this.setASN1Object(this.isExplicit, this.hT, this.asn1Object);
+ }
+ }
+};
+YAHOO.lang.extend(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);
diff --git a/source/asn1hex-1.1.js b/source/asn1hex-1.1.js
new file mode 100644
index 0000000..a2f669c
--- /dev/null
+++ b/source/asn1hex-1.1.js
@@ -0,0 +1,709 @@
+/* asn1hex-1.2.0.js (c) 2012-2017 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * asn1hex.js - Hexadecimal represented ASN.1 string library
+ *
+ * Copyright (c) 2010-2017 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * https://kjur.github.io/jsrsasign/license/
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name asn1hex-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version asn1hex 1.2.0 (2017-Jun-24)
+ * @license MIT License
+ */
+
+/*
+ * MEMO:
+ * f('3082025b02...', 2) ... 82025b ... 3bytes
+ * f('020100', 2) ... 01 ... 1byte
+ * f('0203001...', 2) ... 03 ... 1byte
+ * f('02818003...', 2) ... 8180 ... 2bytes
+ * f('3080....0000', 2) ... 80 ... -1
+ *
+ * Requirements:
+ * - ASN.1 type octet length MUST be 1.
+ * (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
+ */
+
+/**
+ * ASN.1 DER encoded hexadecimal string utility class
+ * @name ASN1HEX
+ * @class ASN.1 DER encoded hexadecimal string utility class
+ * @since jsrsasign 1.1
+ * @description
+ * This class provides a parser for hexadecimal string of
+ * DER encoded ASN.1 binary data.
+ * Here are major methods of this class.
+ *
+ * - ACCESS BY POSITION
+ *
+ * - {@link ASN1HEX.getTLV} - get ASN.1 TLV at specified position
+ * - {@link ASN1HEX.getV} - get ASN.1 V at specified position
+ * - {@link ASN1HEX.getVlen} - get integer ASN.1 L at specified position
+ * - {@link ASN1HEX.getVidx} - get ASN.1 V position from its ASN.1 TLV position
+ * - {@link ASN1HEX.getL} - get hexadecimal ASN.1 L at specified position
+ * - {@link ASN1HEX.getLblen} - get byte length for ASN.1 L(length) bytes
+ *
+ *
+ * - ACCESS FOR CHILD ITEM
+ *
+ * - {@link ASN1HEX.getNthChildIndex_AtObj} - get nth child index at specified position
+ * - {@link ASN1HEX.getPosArrayOfChildren_AtObj} - get indexes of children
+ * - {@link ASN1HEX.getPosOfNextSibling_AtObj} - get position of next sibling
+ *
+ *
+ * - ACCESS NESTED ASN.1 STRUCTURE
+ *
+ * - {@link ASN1HEX.getTLVbyList} - get ASN.1 TLV at specified list index
+ * - {@link ASN1HEX.getVbyList} - get ASN.1 V at specified nth list index with checking expected tag
+ * - {@link ASN1HEX.getIdxbyList} - get index at specified list index
+ *
+ *
+ * - UTILITIES
+ *
+ * - {@link ASN1HEX.dump} - dump ASN.1 structure
+ * - {@link ASN1HEX.isASN1HEX} - check whether ASN.1 hexadecimal string or not
+ * - {@link ASN1HEX.hextooidstr} - convert hexadecimal string of OID to dotted integer list
+ *
+ *
+ *
+ */
+var ASN1HEX = new function() {
+};
+
+/**
+ * get byte length for ASN.1 L(length) bytes
+ * @name getLblen
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @return byte length for ASN.1 L(length) bytes
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ * @example
+ * ASN1HEX.getLblen('020100', 0) → 1 for '01'
+ * ASN1HEX.getLblen('020200', 0) → 1 for '02'
+ * ASN1HEX.getLblen('02818003...', 0) → 2 for '8180'
+ * ASN1HEX.getLblen('0282025b03...', 0) → 3 for '82025b'
+ * ASN1HEX.getLblen('0280020100...', 0) → -1 for '80' BER indefinite length
+ * ASN1HEX.getLblen('02ffab...', 0) → -2 for malformed ASN.1 length
+ */
+ASN1HEX.getLblen = function(s, idx) {
+ if (s.substr(idx + 2, 1) != '8') return 1;
+ var i = parseInt(s.substr(idx + 3, 1));
+ if (i == 0) return -1; // length octet '80' indefinite length
+ if (0 < i && i < 10) return i + 1; // including '8?' octet;
+ return -2; // malformed format
+};
+
+/**
+ * get hexadecimal string for ASN.1 L(length) bytes
+ * @name getL
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index to get L of ASN.1 object
+ * @return {String} hexadecimal string for ASN.1 L(length) bytes
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+ASN1HEX.getL = function(s, idx) {
+ var len = ASN1HEX.getLblen(s, idx);
+ if (len < 1) return '';
+ return s.substr(idx + 2, len * 2);
+};
+
+/**
+ * get integer value of ASN.1 length for ASN.1 data
+ * @name getVblen
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @return ASN.1 L(length) integer value
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+/*
+ getting ASN.1 length value at the position 'idx' of
+ hexa decimal string 's'.
+ f('3082025b02...', 0) ... 82025b ... ???
+ f('020100', 0) ... 01 ... 1
+ f('0203001...', 0) ... 03 ... 3
+ f('02818003...', 0) ... 8180 ... 128
+ */
+ASN1HEX.getVblen = function(s, idx) {
+ var hLen, bi;
+ hLen = ASN1HEX.getL(s, idx);
+ if (hLen == '') return -1;
+ if (hLen.substr(0, 1) === '8') {
+ bi = new BigInteger(hLen.substr(2), 16);
+ } else {
+ bi = new BigInteger(hLen, 16);
+ }
+ return bi.intValue();
+};
+
+/**
+ * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
+ * @name getVidx
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+ASN1HEX.getVidx = function(s, idx) {
+ var l_len = ASN1HEX.getLblen(s, idx);
+ if (l_len < 0) return l_len;
+ return idx + (l_len + 1) * 2;
+};
+
+/**
+ * get hexadecimal string of ASN.1 V(value)
+ * @name getV
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @return {String} hexadecimal string of ASN.1 value.
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+ASN1HEX.getV = function(s, idx) {
+ var idx1 = ASN1HEX.getVidx(s, idx);
+ var blen = ASN1HEX.getVblen(s, idx);
+ return s.substr(idx1, blen * 2);
+};
+
+/**
+ * get hexadecimal string of ASN.1 TLV at
+ * @name getTLV
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @return {String} hexadecimal string of ASN.1 TLV.
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+ASN1HEX.getTLV = function(s, idx) {
+ return s.substr(idx, 2) + ASN1HEX.getL(s, idx) + ASN1HEX.getV(s, idx);
+};
+
+// ========== sibling methods ================================
+
+/**
+ * get next sibling starting index for ASN.1 object string
+ * @name getNextSiblingIdx
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} s hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx string index
+ * @return next sibling starting index for ASN.1 object string
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ * @example
+ * SEQUENCE { INTEGER 3, INTEGER 4 }
+ * 3006
+ * 020103 :idx=4
+ * 020104 :next sibling idx=10
+ * getNextSiblingIdx("3006020103020104", 4) & rarr 10
+ */
+ASN1HEX.getNextSiblingIdx = function(s, idx) {
+ var idx1 = ASN1HEX.getVidx(s, idx);
+ var blen = ASN1HEX.getVblen(s, idx);
+ return idx1 + blen * 2;
+};
+
+// ========== children methods ===============================
+/**
+ * get array of string indexes of child ASN.1 objects
+ * @name getChildIdx
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} h hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} pos start string index of ASN.1 object
+ * @return {Array of Number} array of indexes for childen of ASN.1 objects
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ * @description
+ * This method returns array of integers for a concatination of ASN.1 objects
+ * in a ASN.1 value. As for BITSTRING, one byte of unusedbits is skipped.
+ * As for other ASN.1 simple types such as INTEGER, OCTET STRING or PRINTABLE STRING,
+ * it returns a array of a string index of its ASN.1 value.
+ * NOTE: Since asn1hex 1.1.7 of jsrsasign 6.1.2, Encapsulated BitString is supported.
+ * @example
+ * ASN1HEX.getChildIdx("0203012345", 0) ⇒ [4] // INTEGER 012345
+ * ASN1HEX.getChildIdx("1303616161", 0) ⇒ [4] // PrintableString aaa
+ * ASN1HEX.getChildIdx("030300ffff", 0) ⇒ [6] // BITSTRING ffff (unusedbits=00a)
+ * ASN1HEX.getChildIdx("3006020104020105", 0) ⇒ [4, 10] // SEQUENCE(INT4,INT5)
+ */
+ASN1HEX.getChildIdx = function(h, pos) {
+ var _ASN1HEX = ASN1HEX;
+ var a = new Array();
+ var p0 = _ASN1HEX.getVidx(h, pos);
+ if (h.substr(pos, 2) == "03") {
+ a.push(p0 + 2); // BITSTRING value without unusedbits
+ } else {
+ a.push(p0);
+ }
+
+ var blen = _ASN1HEX.getVblen(h, pos);
+ var p = p0;
+ var k = 0;
+ while (1) {
+ var pNext = _ASN1HEX.getNextSiblingIdx(h, p);
+ if (pNext == null || (pNext - p0 >= (blen * 2))) break;
+ if (k >= 200) break;
+
+ a.push(pNext);
+ p = pNext;
+
+ k++;
+ }
+
+ return a;
+};
+
+/**
+ * get string index of nth child object of ASN.1 object refered by h, idx
+ * @name getNthChildIdx
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} h hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} idx start string index of ASN.1 object
+ * @param {Number} nth for child
+ * @return {Number} string index of nth child.
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ */
+ASN1HEX.getNthChildIdx = function(h, idx, nth) {
+ var a = ASN1HEX.getChildIdx(h, idx);
+ return a[nth];
+};
+
+// ========== decendant methods ==============================
+/**
+ * get string index of nth child object of ASN.1 object refered by h, idx
+ * @name getIdxbyList
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} h hexadecimal string of ASN.1 DER encoded data
+ * @param {Number} currentIndex start string index of ASN.1 object
+ * @param {Array of Number} nthList array list of nth
+ * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList
+ * @return {Number} string index refered by nthList
+ * @since jsrsasign 7.1.4 asn1hex 1.1.10.
+ * @description
+ * @example
+ * The "nthList" is a index list of structured ASN.1 object
+ * reference. Here is a sample structure and "nthList"s which
+ * refers each objects.
+ *
+ * SQUENCE -
+ * SEQUENCE - [0]
+ * IA5STRING 000 - [0, 0]
+ * UTF8STRING 001 - [0, 1]
+ * SET - [1]
+ * IA5STRING 010 - [1, 0]
+ * UTF8STRING 011 - [1, 1]
+ */
+ASN1HEX.getIdxbyList = function(h, currentIndex, nthList, checkingTag) {
+ var _ASN1HEX = ASN1HEX;
+ var firstNth, a;
+ if (nthList.length == 0) {
+ if (checkingTag !== undefined) {
+ if (h.substr(currentIndex, 2) !== checkingTag) {
+ throw "checking tag doesn't match: " +
+ h.substr(currentIndex, 2) + "!=" + checkingTag;
+ }
+ }
+ return currentIndex;
+ }
+ firstNth = nthList.shift();
+ a = _ASN1HEX.getChildIdx(h, currentIndex);
+ return _ASN1HEX.getIdxbyList(h, a[firstNth], nthList, checkingTag);
+};
+
+/**
+ * get ASN.1 TLV by nthList
+ * @name getTLVbyList
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} h hexadecimal string of ASN.1 structure
+ * @param {Integer} currentIndex string index to start searching in hexadecimal string "h"
+ * @param {Array} nthList array of nth list index
+ * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList
+ * @since jsrsasign 7.1.4 asn1hex 1.1.10
+ * @description
+ * This static method is to get a ASN.1 value which specified "nthList" position
+ * with checking expected tag "checkingTag".
+ */
+ASN1HEX.getTLVbyList = function(h, currentIndex, nthList, checkingTag) {
+ var _ASN1HEX = ASN1HEX;
+ var idx = _ASN1HEX.getIdxbyList(h, currentIndex, nthList);
+ if (idx === undefined) {
+ throw "can't find nthList object";
+ }
+ if (checkingTag !== undefined) {
+ if (h.substr(idx, 2) != checkingTag) {
+ throw "checking tag doesn't match: " +
+ h.substr(idx,2) + "!=" + checkingTag;
+ }
+ }
+ return _ASN1HEX.getTLV(h, idx);
+};
+
+/**
+ * get ASN.1 value by nthList
+ * @name getVbyList
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} h hexadecimal string of ASN.1 structure
+ * @param {Integer} currentIndex string index to start searching in hexadecimal string "h"
+ * @param {Array} nthList array of nth list index
+ * @param {String} checkingTag (OPTIONAL) string of expected ASN.1 tag for nthList
+ * @param {Boolean} removeUnusedbits (OPTIONAL) flag for remove first byte for value (DEFAULT false)
+ * @since asn1hex 1.1.4
+ * @description
+ * This static method is to get a ASN.1 value which specified "nthList" position
+ * with checking expected tag "checkingTag".
+ * NOTE: 'removeUnusedbits' flag has been supported since
+ * jsrsasign 7.1.14 asn1hex 1.1.10.
+ */
+ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag, removeUnusedbits) {
+ var _ASN1HEX = ASN1HEX;
+ var idx, v;
+ idx = _ASN1HEX.getIdxbyList(h, currentIndex, nthList, checkingTag);
+
+ if (idx === undefined) {
+ throw "can't find nthList object";
+ }
+
+ v = _ASN1HEX.getV(h, idx);
+ if (removeUnusedbits === true) v = v.substr(2);
+ return v;
+};
+
+/**
+ * get OID string from hexadecimal encoded value
+ * @name hextooidstr
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
+ * @return {String} OID string (ex. '1.2.3.4.567')
+ * @since asn1hex 1.1.5
+ */
+ASN1HEX.hextooidstr = function(hex) {
+ var zeroPadding = function(s, len) {
+ if (s.length >= len) return s;
+ return new Array(len - s.length + 1).join('0') + s;
+ };
+
+ var a = [];
+
+ // a[0], a[1]
+ var hex0 = hex.substr(0, 2);
+ var i0 = parseInt(hex0, 16);
+ a[0] = new String(Math.floor(i0 / 40));
+ a[1] = new String(i0 % 40);
+
+ // a[2]..a[n]
+ var hex1 = hex.substr(2);
+ var b = [];
+ for (var i = 0; i < hex1.length / 2; i++) {
+ b.push(parseInt(hex1.substr(i * 2, 2), 16));
+ }
+ var c = [];
+ var cbin = "";
+ for (var i = 0; i < b.length; i++) {
+ if (b[i] & 0x80) {
+ cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+ } else {
+ cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
+ c.push(new String(parseInt(cbin, 2)));
+ cbin = "";
+ }
+ }
+
+ var s = a.join(".");
+ if (c.length > 0) s = s + "." + c.join(".");
+ return s;
+};
+
+/**
+ * get string of simple ASN.1 dump from hexadecimal ASN.1 data
+ * @name dump
+ * @memberOf ASN1HEX
+ * @function
+ * @param {Object} hexOrObj hexadecmal string of ASN.1 data or ASN1Object object
+ * @param {Array} flags associative array of flags for dump (OPTION)
+ * @param {Number} idx string index for starting dump (OPTION)
+ * @param {String} indent indent string (OPTION)
+ * @return {String} string of simple ASN.1 dump
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method will get an ASN.1 dump from
+ * hexadecmal string of ASN.1 DER encoded data.
+ * Here are features:
+ *
+ * - ommit long hexadecimal string
+ * - dump encapsulated OCTET STRING (good for X.509v3 extensions)
+ * - structured/primitive context specific tag support (i.e. [0], [3] ...)
+ * - automatic decode for implicit primitive context specific tag
+ * (good for X.509v3 extension value)
+ *
+ * - if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.
+ * - if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
+ * value will be encoded as utf8 string
+ * - otherwise it shows as hexadecimal string
+ *
+ *
+ *
+ * NOTE1: Argument {@link KJUR.asn1.ASN1Object} object is supported since
+ * jsrsasign 6.2.4 asn1hex 1.0.8
+ * @example
+ * // 1) ASN.1 INTEGER
+ * ASN1HEX.dump('0203012345')
+ * ↓
+ * INTEGER 012345
+ *
+ * // 2) ASN.1 Object Identifier
+ * ASN1HEX.dump('06052b0e03021a')
+ * ↓
+ * ObjectIdentifier sha1 (1 3 14 3 2 26)
+ *
+ * // 3) ASN.1 SEQUENCE
+ * ASN1HEX.dump('3006020101020102')
+ * ↓
+ * SEQUENCE
+ * INTEGER 01
+ * INTEGER 02
+ *
+ * // 4) ASN.1 SEQUENCE since jsrsasign 6.2.4
+ * o = KJUR.asn1.ASN1Util.newObject({seq: [{int: 1}, {int: 2}]});
+ * ASN1HEX.dump(o)
+ * ↓
+ * SEQUENCE
+ * INTEGER 01
+ * INTEGER 02
+ * // 5) ASN.1 DUMP FOR X.509 CERTIFICATE
+ * ASN1HEX.dump(pemtohex(certPEM))
+ * ↓
+ * SEQUENCE
+ * SEQUENCE
+ * [0]
+ * INTEGER 02
+ * INTEGER 0c009310d206dbe337553580118ddc87
+ * SEQUENCE
+ * ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
+ * NULL
+ * SEQUENCE
+ * SET
+ * SEQUENCE
+ * ObjectIdentifier countryName (2 5 4 6)
+ * PrintableString 'US'
+ * :
+ */
+ASN1HEX.dump = function(hexOrObj, flags, idx, indent) {
+ var _ASN1HEX = ASN1HEX;
+ var _getV = _ASN1HEX.getV;
+ var _dump = _ASN1HEX.dump;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+
+ var hex = hexOrObj;
+ if (hexOrObj instanceof KJUR.asn1.ASN1Object)
+ hex = hexOrObj.getEncodedHex();
+
+ var _skipLongHex = function(hex, limitNumOctet) {
+ if (hex.length <= limitNumOctet * 2) {
+ return hex;
+ } else {
+ var s = hex.substr(0, limitNumOctet) +
+ "..(total " + hex.length / 2 + "bytes).." +
+ hex.substr(hex.length - limitNumOctet, limitNumOctet);
+ return s;
+ };
+ };
+
+ if (flags === undefined) flags = { "ommit_long_octet": 32 };
+ if (idx === undefined) idx = 0;
+ if (indent === undefined) indent = "";
+ var skipLongHex = flags.ommit_long_octet;
+
+ if (hex.substr(idx, 2) == "01") {
+ var v = _getV(hex, idx);
+ if (v == "00") {
+ return indent + "BOOLEAN FALSE\n";
+ } else {
+ return indent + "BOOLEAN TRUE\n";
+ }
+ }
+ if (hex.substr(idx, 2) == "02") {
+ var v = _getV(hex, idx);
+ return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
+ }
+ if (hex.substr(idx, 2) == "03") {
+ var v = _getV(hex, idx);
+ return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+ }
+ if (hex.substr(idx, 2) == "04") {
+ var v = _getV(hex, idx);
+ if (_ASN1HEX.isASN1HEX(v)) {
+ var s = indent + "OCTETSTRING, encapsulates\n";
+ s = s + _dump(v, flags, 0, indent + " ");
+ return s;
+ } else {
+ return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
+ }
+ }
+ if (hex.substr(idx, 2) == "05") {
+ return indent + "NULL\n";
+ }
+ if (hex.substr(idx, 2) == "06") {
+ var hV = _getV(hex, idx);
+ var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
+ var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
+ var oidSpc = oidDot.replace(/\./g, ' ');
+ if (oidName != '') {
+ return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
+ } else {
+ return indent + "ObjectIdentifier (" + oidSpc + ")\n";
+ }
+ }
+ if (hex.substr(idx, 2) == "0c") {
+ return indent + "UTF8String '" + hextoutf8(_getV(hex, idx)) + "'\n";
+ }
+ if (hex.substr(idx, 2) == "13") {
+ return indent + "PrintableString '" + hextoutf8(_getV(hex, idx)) + "'\n";
+ }
+ if (hex.substr(idx, 2) == "14") {
+ return indent + "TeletexString '" + hextoutf8(_getV(hex, idx)) + "'\n";
+ }
+ if (hex.substr(idx, 2) == "16") {
+ return indent + "IA5String '" + hextoutf8(_getV(hex, idx)) + "'\n";
+ }
+ if (hex.substr(idx, 2) == "17") {
+ return indent + "UTCTime " + hextoutf8(_getV(hex, idx)) + "\n";
+ }
+ if (hex.substr(idx, 2) == "18") {
+ return indent + "GeneralizedTime " + hextoutf8(_getV(hex, idx)) + "\n";
+ }
+ if (hex.substr(idx, 2) == "30") {
+ if (hex.substr(idx, 4) == "3000") {
+ return indent + "SEQUENCE {}\n";
+ }
+
+ var s = indent + "SEQUENCE\n";
+ var aIdx = _getChildIdx(hex, idx);
+
+ var flagsTemp = flags;
+
+ if ((aIdx.length == 2 || aIdx.length == 3) &&
+ hex.substr(aIdx[0], 2) == "06" &&
+ hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
+ var oidName = _ASN1HEX.oidname(_getV(hex, aIdx[0]));
+ var flagsClone = JSON.parse(JSON.stringify(flags));
+ flagsClone.x509ExtName = oidName;
+ flagsTemp = flagsClone;
+ }
+
+ for (var i = 0; i < aIdx.length; i++) {
+ s = s + _dump(hex, flagsTemp, aIdx[i], indent + " ");
+ }
+ return s;
+ }
+ if (hex.substr(idx, 2) == "31") {
+ var s = indent + "SET\n";
+ var aIdx = _getChildIdx(hex, idx);
+ for (var i = 0; i < aIdx.length; i++) {
+ s = s + _dump(hex, flags, aIdx[i], indent + " ");
+ }
+ return s;
+ }
+ var tag = parseInt(hex.substr(idx, 2), 16);
+ if ((tag & 128) != 0) { // context specific
+ var tagNumber = tag & 31;
+ if ((tag & 32) != 0) { // structured tag
+ var s = indent + "[" + tagNumber + "]\n";
+ var aIdx = _getChildIdx(hex, idx);
+ for (var i = 0; i < aIdx.length; i++) {
+ s = s + _dump(hex, flags, aIdx[i], indent + " ");
+ }
+ return s;
+ } else { // primitive tag
+ var v = _getV(hex, idx);
+ if (v.substr(0, 8) == "68747470") { // http
+ v = hextoutf8(v);
+ }
+ if (flags.x509ExtName === "subjectAltName" &&
+ tagNumber == 2) {
+ v = hextoutf8(v);
+ }
+
+ var s = indent + "[" + tagNumber + "] " + v + "\n";
+ return s;
+ }
+ }
+ return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " +
+ _getV(hex, idx) + "\n";
+};
+
+/**
+ * check wheather the string is ASN.1 hexadecimal string or not
+ * @name isASN1HEX
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
+ * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
+ * @since jsrsasign 4.8.3 asn1hex 1.1.6
+ * @description
+ * This method checks wheather the argument 'hex' is a hexadecimal string of
+ * ASN.1 data or not.
+ * @example
+ * ASN1HEX.isASN1HEX('0203012345') → true // PROPER ASN.1 INTEGER
+ * ASN1HEX.isASN1HEX('0203012345ff') → false // TOO LONG VALUE
+ * ASN1HEX.isASN1HEX('02030123') → false // TOO SHORT VALUE
+ * ASN1HEX.isASN1HEX('fa3bcd') → false // WRONG FOR ASN.1
+ */
+ASN1HEX.isASN1HEX = function(hex) {
+ var _ASN1HEX = ASN1HEX;
+ if (hex.length % 2 == 1) return false;
+
+ var intL = _ASN1HEX.getVblen(hex, 0);
+ var tV = hex.substr(0, 2);
+ var lV = _ASN1HEX.getL(hex, 0);
+ var hVLength = hex.length - tV.length - lV.length;
+ if (hVLength == intL * 2) return true;
+
+ return false;
+};
+
+/**
+ * get hexacedimal string from PEM format data
+ * @name oidname
+ * @memberOf ASN1HEX
+ * @function
+ * @param {String} oidDotOrHex number dot notation(i.e. 1.2.3) or hexadecimal string for OID
+ * @return {String} name for OID
+ * @since jsrsasign 7.2.0 asn1hex 1.1.11
+ * @description
+ * This static method gets a OID name for
+ * a specified string of number dot notation (i.e. 1.2.3) or
+ * hexadecimal string.
+ * @example
+ * ASN1HEX.oidname("2.5.29.37") → extKeyUsage
+ * ASN1HEX.oidname("551d25") → extKeyUsage
+ * ASN1HEX.oidname("0.1.2.3") → 0.1.2.3 // unknown
+ */
+ASN1HEX.oidname = function(oidDotOrHex) {
+ var _KJUR_asn1 = KJUR.asn1;
+ if (KJUR.lang.String.isHex(oidDotOrHex))
+ oidDotOrHex = _KJUR_asn1.ASN1Util.oidHexToInt(oidDotOrHex);
+ var name = _KJUR_asn1.x509.OID.oid2name(oidDotOrHex);
+ if (name === "") name = oidDotOrHex;
+ return name;
+};
+
diff --git a/source/base64x-1.1.js b/source/base64x-1.1.js
new file mode 100644
index 0000000..2770cbc
--- /dev/null
+++ b/source/base64x-1.1.js
@@ -0,0 +1,1173 @@
+/* base64x-1.1.14 (c) 2012-2018 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * base64x.js - Base64url and supplementary functions for Tom Wu's base64.js library
+ *
+ * version: 1.1.14 (2018-Apr-21)
+ *
+ * Copyright (c) 2012-2018 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * https://kjur.github.io/jsrsasign/license
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name base64x-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version jsrsasign 8.0.12 base64x 1.1.14 (2018-Apr-22)
+ * @since jsrsasign 2.1
+ * @license MIT License
+ */
+
+var KJUR;
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+if (typeof KJUR.lang == "undefined" || !KJUR.lang) KJUR.lang = {};
+
+/**
+ * String and its utility class
+ * This class provides some static utility methods for string.
+ * @class String and its utility class
+ * @author Kenji Urushima
+ * @version 1.0 (2016-Aug-05)
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @description
+ *
+ * This class provides static methods for string utility.
+ *
+ * - STRING TYPE CHECKERS
+ *
-
+ *
+ * - {@link KJUR.lang.String.isInteger} - check whether argument is an integer
+ * - {@link KJUR.lang.String.isHex} - check whether argument is a hexadecimal string
+ * - {@link KJUR.lang.String.isBase64} - check whether argument is a Base64 encoded string
+ * - {@link KJUR.lang.String.isBase64URL} - check whether argument is a Base64URL encoded string
+ * - {@link KJUR.lang.String.isIntegerArray} - check whether argument is an array of integers
+ *
+ *
+ */
+KJUR.lang.String = function() {};
+
+/**
+ * Base64URL and supplementary functions for Tom Wu's base64.js library.
+ * This class is just provide information about global functions
+ * defined in 'base64x.js'. The 'base64x.js' script file provides
+ * global functions for converting following data each other.
+ *
+ * - (ASCII) String
+ * - UTF8 String including CJK, Latin and other characters
+ * - byte array
+ * - hexadecimal encoded String
+ * - Full URIComponent encoded String (such like "%69%94")
+ * - Base64 encoded String
+ * - Base64URL encoded String
+ *
+ * All functions in 'base64x.js' are defined in {@link _global_} and not
+ * in this class.
+ *
+ * @class Base64URL and supplementary functions for Tom Wu's base64.js library
+ * @author Kenji Urushima
+ * @version 1.1 (07 May 2012)
+ * @requires base64.js
+ * @see 'jwjws'(JWS JavaScript Library) home page https://kjur.github.io/jsjws/
+ * @see 'jwrsasign'(RSA Sign JavaScript Library) home page https://kjur.github.io/jsrsasign/
+ */
+function Base64x() {
+}
+
+// ==== string / byte array ================================
+/**
+ * convert a string to an array of character codes
+ * @name stoBA
+ * @function
+ * @param {String} s
+ * @return {Array of Numbers}
+ */
+function stoBA(s) {
+ var a = new Array();
+ for (var i = 0; i < s.length; i++) {
+ a[i] = s.charCodeAt(i);
+ }
+ return a;
+}
+
+/**
+ * convert an array of character codes to a string
+ * @name BAtos
+ * @function
+ * @param {Array of Numbers} a array of character codes
+ * @return {String} s
+ */
+function BAtos(a) {
+ var s = "";
+ for (var i = 0; i < a.length; i++) {
+ s = s + String.fromCharCode(a[i]);
+ }
+ return s;
+}
+
+// ==== byte array / hex ================================
+/**
+ * convert an array of bytes(Number) to hexadecimal string.
+ * @name BAtohex
+ * @function
+ * @param {Array of Numbers} a array of bytes
+ * @return {String} hexadecimal string
+ */
+function BAtohex(a) {
+ var s = "";
+ for (var i = 0; i < a.length; i++) {
+ var hex1 = a[i].toString(16);
+ if (hex1.length == 1) hex1 = "0" + hex1;
+ s = s + hex1;
+ }
+ return s;
+}
+
+// ==== string / hex ================================
+/**
+ * convert a ASCII string to a hexadecimal string of ASCII codes.
+ * NOTE: This can't be used for non ASCII characters.
+ * @name stohex
+ * @function
+ * @param {s} s ASCII string
+ * @return {String} hexadecimal string
+ */
+function stohex(s) {
+ return BAtohex(stoBA(s));
+}
+
+// ==== string / base64 ================================
+/**
+ * convert a ASCII string to a Base64 encoded string.
+ * NOTE: This can't be used for non ASCII characters.
+ * @name stob64
+ * @function
+ * @param {s} s ASCII string
+ * @return {String} Base64 encoded string
+ */
+function stob64(s) {
+ return hex2b64(stohex(s));
+}
+
+// ==== string / base64url ================================
+/**
+ * convert a ASCII string to a Base64URL encoded string.
+ * NOTE: This can't be used for non ASCII characters.
+ * @name stob64u
+ * @function
+ * @param {s} s ASCII string
+ * @return {String} Base64URL encoded string
+ */
+function stob64u(s) {
+ return b64tob64u(hex2b64(stohex(s)));
+}
+
+/**
+ * convert a Base64URL encoded string to a ASCII string.
+ * NOTE: This can't be used for Base64URL encoded non ASCII characters.
+ * @name b64utos
+ * @function
+ * @param {s} s Base64URL encoded string
+ * @return {String} ASCII string
+ */
+function b64utos(s) {
+ return BAtos(b64toBA(b64utob64(s)));
+}
+
+// ==== base64 / base64url ================================
+/**
+ * convert a Base64 encoded string to a Base64URL encoded string.
+ * @name b64tob64u
+ * @function
+ * @param {String} s Base64 encoded string
+ * @return {String} Base64URL encoded string
+ * @example
+ * b64tob64u("ab+c3f/==") → "ab-c3f_"
+ */
+function b64tob64u(s) {
+ s = s.replace(/\=/g, "");
+ s = s.replace(/\+/g, "-");
+ s = s.replace(/\//g, "_");
+ return s;
+}
+
+/**
+ * convert a Base64URL encoded string to a Base64 encoded string.
+ * @name b64utob64
+ * @function
+ * @param {String} s Base64URL encoded string
+ * @return {String} Base64 encoded string
+ * @example
+ * b64utob64("ab-c3f_") → "ab+c3f/=="
+ */
+function b64utob64(s) {
+ if (s.length % 4 == 2) s = s + "==";
+ else if (s.length % 4 == 3) s = s + "=";
+ s = s.replace(/-/g, "+");
+ s = s.replace(/_/g, "/");
+ return s;
+}
+
+// ==== hex / base64url ================================
+/**
+ * convert a hexadecimal string to a Base64URL encoded string.
+ * @name hextob64u
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} Base64URL encoded string
+ * @description
+ * convert a hexadecimal string to a Base64URL encoded string.
+ * NOTE: If leading "0" is omitted and odd number length for
+ * hexadecimal leading "0" is automatically added.
+ */
+function hextob64u(s) {
+ if (s.length % 2 == 1) s = "0" + s;
+ return b64tob64u(hex2b64(s));
+}
+
+/**
+ * convert a Base64URL encoded string to a hexadecimal string.
+ * @name b64utohex
+ * @function
+ * @param {String} s Base64URL encoded string
+ * @return {String} hexadecimal string
+ */
+function b64utohex(s) {
+ return b64tohex(b64utob64(s));
+}
+
+// ==== utf8 / base64url ================================
+
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a Base64URL encoded string.
+ * @name utf8tob64u
+ * @function
+ * @param {String} s UTF-8 encoded string
+ * @return {String} Base64URL encoded string
+ * @since 1.1
+ */
+
+/**
+ * convert a Base64URL encoded string to a UTF-8 encoded string including CJK or Latin.
+ * @name b64utoutf8
+ * @function
+ * @param {String} s Base64URL encoded string
+ * @return {String} UTF-8 encoded string
+ * @since 1.1
+ */
+
+var utf8tob64u, b64utoutf8;
+
+if (typeof Buffer === 'function') {
+ utf8tob64u = function (s) {
+ return b64tob64u(new Buffer(s, 'utf8').toString('base64'));
+ };
+
+ b64utoutf8 = function (s) {
+ return new Buffer(b64utob64(s), 'base64').toString('utf8');
+ };
+} else {
+ utf8tob64u = function (s) {
+ return hextob64u(uricmptohex(encodeURIComponentAll(s)));
+ };
+
+ b64utoutf8 = function (s) {
+ return decodeURIComponent(hextouricmp(b64utohex(s)));
+ };
+}
+
+// ==== utf8 / base64url ================================
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a Base64 encoded string.
+ * @name utf8tob64
+ * @function
+ * @param {String} s UTF-8 encoded string
+ * @return {String} Base64 encoded string
+ * @since 1.1.1
+ */
+function utf8tob64(s) {
+ return hex2b64(uricmptohex(encodeURIComponentAll(s)));
+}
+
+/**
+ * convert a Base64 encoded string to a UTF-8 encoded string including CJK or Latin.
+ * @name b64toutf8
+ * @function
+ * @param {String} s Base64 encoded string
+ * @return {String} UTF-8 encoded string
+ * @since 1.1.1
+ */
+function b64toutf8(s) {
+ return decodeURIComponent(hextouricmp(b64tohex(s)));
+}
+
+// ==== utf8 / hex ================================
+/**
+ * convert a UTF-8 encoded string including CJK or Latin to a hexadecimal encoded string.
+ * @name utf8tohex
+ * @function
+ * @param {String} s UTF-8 encoded string
+ * @return {String} hexadecimal encoded string
+ * @since 1.1.1
+ */
+function utf8tohex(s) {
+ return uricmptohex(encodeURIComponentAll(s));
+}
+
+/**
+ * convert a hexadecimal encoded string to a UTF-8 encoded string including CJK or Latin.
+ * Note that when input is improper hexadecimal string as UTF-8 string, this function returns
+ * 'null'.
+ * @name hextoutf8
+ * @function
+ * @param {String} s hexadecimal encoded string
+ * @return {String} UTF-8 encoded string or null
+ * @since 1.1.1
+ */
+function hextoutf8(s) {
+ return decodeURIComponent(hextouricmp(s));
+}
+
+/**
+ * convert a hexadecimal encoded string to raw string including non printable characters.
+ * @name hextorstr
+ * @function
+ * @param {String} s hexadecimal encoded string
+ * @return {String} raw string
+ * @since 1.1.2
+ * @example
+ * hextorstr("610061") → "a\x00a"
+ */
+function hextorstr(sHex) {
+ var s = "";
+ for (var i = 0; i < sHex.length - 1; i += 2) {
+ s += String.fromCharCode(parseInt(sHex.substr(i, 2), 16));
+ }
+ return s;
+}
+
+/**
+ * convert a raw string including non printable characters to hexadecimal encoded string.
+ * @name rstrtohex
+ * @function
+ * @param {String} s raw string
+ * @return {String} hexadecimal encoded string
+ * @since 1.1.2
+ * @example
+ * rstrtohex("a\x00a") → "610061"
+ */
+function rstrtohex(s) {
+ var result = "";
+ for (var i = 0; i < s.length; i++) {
+ result += ("0" + s.charCodeAt(i).toString(16)).slice(-2);
+ }
+ return result;
+}
+
+// ==== hex / b64nl =======================================
+
+/**
+ * convert a hexadecimal string to Base64 encoded string
+ * @name hextob64
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} resulted Base64 encoded string
+ * @since base64x 1.1.3
+ * @description
+ * This function converts from a hexadecimal string to Base64 encoded
+ * string without new lines.
+ * @example
+ * hextob64("616161") → "YWFh"
+ */
+function hextob64(s) {
+ return hex2b64(s);
+}
+
+/**
+ * convert a hexadecimal string to Base64 encoded string with new lines
+ * @name hextob64nl
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} resulted Base64 encoded string with new lines
+ * @since base64x 1.1.3
+ * @description
+ * This function converts from a hexadecimal string to Base64 encoded
+ * string with new lines for each 64 characters. This is useful for
+ * PEM encoded file.
+ * @example
+ * hextob64nl("123456789012345678901234567890123456789012345678901234567890")
+ * →
+ * MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 // new line
+ * OTAxMjM0NTY3ODkwCg==
+ */
+function hextob64nl(s) {
+ var b64 = hextob64(s);
+ var b64nl = b64.replace(/(.{64})/g, "$1\r\n");
+ b64nl = b64nl.replace(/\r\n$/, '');
+ return b64nl;
+}
+
+/**
+ * convert a Base64 encoded string with new lines to a hexadecimal string
+ * @name b64nltohex
+ * @function
+ * @param {String} s Base64 encoded string with new lines
+ * @return {String} hexadecimal string
+ * @since base64x 1.1.3
+ * @description
+ * This function converts from a Base64 encoded
+ * string with new lines to a hexadecimal string.
+ * This is useful to handle PEM encoded file.
+ * This function removes any non-Base64 characters (i.e. not 0-9,A-Z,a-z,\,+,=)
+ * including new line.
+ * @example
+ * hextob64nl(
+ * "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4\r\n" +
+ * "OTAxMjM0NTY3ODkwCg==\r\n")
+ * →
+ * "123456789012345678901234567890123456789012345678901234567890"
+ */
+function b64nltohex(s) {
+ var b64 = s.replace(/[^0-9A-Za-z\/+=]*/g, '');
+ var hex = b64tohex(b64);
+ return hex;
+}
+
+// ==== hex / pem =========================================
+
+/**
+ * get PEM string from hexadecimal data and header string
+ * @name hextopem
+ * @function
+ * @param {String} dataHex hexadecimal string of PEM body
+ * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY')
+ * @return {String} PEM formatted string of input data
+ * @since jsrasign 7.2.1 base64x 1.1.12
+ * @description
+ * This function converts a hexadecimal string to a PEM string with
+ * a specified header. Its line break will be CRLF("\r\n").
+ * @example
+ * hextopem('616161', 'RSA PRIVATE KEY') →
+ * -----BEGIN PRIVATE KEY-----
+ * YWFh
+ * -----END PRIVATE KEY-----
+ */
+function hextopem(dataHex, pemHeader) {
+ var pemBody = hextob64nl(dataHex);
+ return "-----BEGIN " + pemHeader + "-----\r\n" +
+ pemBody +
+ "\r\n-----END " + pemHeader + "-----\r\n";
+}
+
+/**
+ * get hexacedimal string from PEM format data
+ * @name pemtohex
+ * @function
+ * @param {String} s PEM formatted string
+ * @param {String} sHead PEM header string without BEGIN/END(OPTION)
+ * @return {String} hexadecimal string data of PEM contents
+ * @since jsrsasign 7.2.1 base64x 1.1.12
+ * @description
+ * This static method gets a hexacedimal string of contents
+ * from PEM format data. You can explicitly specify PEM header
+ * by sHead argument.
+ * Any space characters such as white space or new line
+ * will be omitted.
+ * NOTE: Now {@link KEYUTIL.getHexFromPEM} and {@link X509.pemToHex}
+ * have been deprecated since jsrsasign 7.2.1.
+ * Please use this method instead.
+ * @example
+ * pemtohex("-----BEGIN PUBLIC KEY...") → "3082..."
+ * pemtohex("-----BEGIN CERTIFICATE...", "CERTIFICATE") → "3082..."
+ * pemtohex(" \r\n-----BEGIN DSA PRIVATE KEY...") → "3082..."
+ */
+function pemtohex(s, sHead) {
+ if (s.indexOf("-----BEGIN ") == -1)
+ throw "can't find PEM header: " + sHead;
+
+ if (sHead !== undefined) {
+ s = s.replace("-----BEGIN " + sHead + "-----", "");
+ s = s.replace("-----END " + sHead + "-----", "");
+ } else {
+ s = s.replace(/-----BEGIN [^-]+-----/, '');
+ s = s.replace(/-----END [^-]+-----/, '');
+ }
+ return b64nltohex(s);
+}
+
+// ==== hex / ArrayBuffer =================================
+
+/**
+ * convert a hexadecimal string to an ArrayBuffer
+ * @name hextoArrayBuffer
+ * @function
+ * @param {String} hex hexadecimal string
+ * @return {ArrayBuffer} ArrayBuffer
+ * @since jsrsasign 6.1.4 base64x 1.1.8
+ * @description
+ * This function converts from a hexadecimal string to an ArrayBuffer.
+ * @example
+ * hextoArrayBuffer("fffa01") → ArrayBuffer of [255, 250, 1]
+ */
+function hextoArrayBuffer(hex) {
+ if (hex.length % 2 != 0) throw "input is not even length";
+ if (hex.match(/^[0-9A-Fa-f]+$/) == null) throw "input is not hexadecimal";
+
+ var buffer = new ArrayBuffer(hex.length / 2);
+ var view = new DataView(buffer);
+
+ for (var i = 0; i < hex.length / 2; i++) {
+ view.setUint8(i, parseInt(hex.substr(i * 2, 2), 16));
+ }
+
+ return buffer;
+}
+
+// ==== ArrayBuffer / hex =================================
+
+/**
+ * convert an ArrayBuffer to a hexadecimal string
+ * @name ArrayBuffertohex
+ * @function
+ * @param {ArrayBuffer} buffer ArrayBuffer
+ * @return {String} hexadecimal string
+ * @since jsrsasign 6.1.4 base64x 1.1.8
+ * @description
+ * This function converts from an ArrayBuffer to a hexadecimal string.
+ * @example
+ * var buffer = new ArrayBuffer(3);
+ * var view = new DataView(buffer);
+ * view.setUint8(0, 0xfa);
+ * view.setUint8(1, 0xfb);
+ * view.setUint8(2, 0x01);
+ * ArrayBuffertohex(buffer) → "fafb01"
+ */
+function ArrayBuffertohex(buffer) {
+ var hex = "";
+ var view = new DataView(buffer);
+
+ for (var i = 0; i < buffer.byteLength; i++) {
+ hex += ("00" + view.getUint8(i).toString(16)).slice(-2);
+ }
+
+ return hex;
+}
+
+// ==== zulu / int =================================
+/**
+ * GeneralizedTime or UTCTime string to milliseconds from Unix origin
+ * @name zulutomsec
+ * @function
+ * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z)
+ * @return {Number} milliseconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC)
+ * @since jsrsasign 7.1.3 base64x 1.1.9
+ * @description
+ * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or
+ * UTCTime string (i.e. YYMMDDHHmmSSZ) to milliseconds from Unix origin time
+ * (i.e. Jan 1 1970 0:00:00 UTC).
+ * Argument string may have fraction of seconds and
+ * its length is one or more digits such as "20170410235959.1234567Z".
+ * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY.
+ * If year "YY" is equal or greater than 50 then it is 19YY.
+ * @example
+ * zulutomsec( "071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutomsec( "071231235959.1Z") → 1199145599100 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutomsec( "071231235959.12345Z") → 1199145599123 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutomsec("20071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutomsec( "931231235959Z") → -410227201000 #Mon, 31 Dec 1956 23:59:59 GMT
+ */
+function zulutomsec(s) {
+ var year, month, day, hour, min, sec, msec, d;
+ var sYear, sFrac, sMsec, matchResult;
+
+ matchResult = s.match(/^(\d{2}|\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(|\.\d+)Z$/);
+
+ if (matchResult) {
+ sYear = matchResult[1];
+ year = parseInt(sYear);
+ if (sYear.length === 2) {
+ if (50 <= year && year < 100) {
+ year = 1900 + year;
+ } else if (0 <= year && year < 50) {
+ year = 2000 + year;
+ }
+ }
+ month = parseInt(matchResult[2]) - 1;
+ day = parseInt(matchResult[3]);
+ hour = parseInt(matchResult[4]);
+ min = parseInt(matchResult[5]);
+ sec = parseInt(matchResult[6]);
+ msec = 0;
+
+ sFrac = matchResult[7];
+ if (sFrac !== "") {
+ sMsec = (sFrac.substr(1) + "00").substr(0, 3); // .12 -> 012
+ msec = parseInt(sMsec);
+ }
+ return Date.UTC(year, month, day, hour, min, sec, msec);
+ }
+ throw "unsupported zulu format: " + s;
+}
+
+/**
+ * GeneralizedTime or UTCTime string to seconds from Unix origin
+ * @name zulutosec
+ * @function
+ * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z)
+ * @return {Number} seconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC)
+ * @since jsrsasign 7.1.3 base64x 1.1.9
+ * @description
+ * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or
+ * UTCTime string (i.e. YYMMDDHHmmSSZ) to seconds from Unix origin time
+ * (i.e. Jan 1 1970 0:00:00 UTC). Argument string may have fraction of seconds
+ * however result value will be omitted.
+ * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY.
+ * If year "YY" is equal or greater than 50 then it is 19YY.
+ * @example
+ * zulutosec( "071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutosec( "071231235959.1Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT
+ * zulutosec("20071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT
+ */
+function zulutosec(s) {
+ var msec = zulutomsec(s);
+ return ~~(msec / 1000);
+}
+
+// ==== zulu / Date =================================
+
+/**
+ * GeneralizedTime or UTCTime string to Date object
+ * @name zulutodate
+ * @function
+ * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z)
+ * @return {Date} Date object for specified time
+ * @since jsrsasign 7.1.3 base64x 1.1.9
+ * @description
+ * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or
+ * UTCTime string (i.e. YYMMDDHHmmSSZ) to Date object.
+ * Argument string may have fraction of seconds and
+ * its length is one or more digits such as "20170410235959.1234567Z".
+ * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY.
+ * If year "YY" is equal or greater than 50 then it is 19YY.
+ * @example
+ * zulutodate( "071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT"
+ * zulutodate( "071231235959.1Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT"
+ * zulutodate("20071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT"
+ * zulutodate( "071231235959.34").getMilliseconds() → 340
+ */
+function zulutodate(s) {
+ return new Date(zulutomsec(s));
+}
+
+// ==== Date / zulu =================================
+
+/**
+ * Date object to zulu time string
+ * @name datetozulu
+ * @function
+ * @param {Date} d Date object for specified time
+ * @param {Boolean} flagUTCTime if this is true year will be YY otherwise YYYY
+ * @param {Boolean} flagMilli if this is true result concludes milliseconds
+ * @return {String} GeneralizedTime or UTCTime string (ex. 20170412235959.384Z)
+ * @since jsrsasign 7.2.0 base64x 1.1.11
+ * @description
+ * This function converts from Date object to GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or
+ * UTCTime string (i.e. YYMMDDHHmmSSZ).
+ * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY.
+ * If year "YY" is equal or greater than 50 then it is 19YY.
+ * If flagMilli is true its result concludes milliseconds such like
+ * "20170520235959.42Z".
+ * @example
+ * d = new Date(Date.UTC(2017,4,20,23,59,59,670));
+ * datetozulu(d) → "20170520235959Z"
+ * datetozulu(d, true) → "170520235959Z"
+ * datetozulu(d, false, true) → "20170520235959.67Z"
+ */
+function datetozulu(d, flagUTCTime, flagMilli) {
+ var s;
+ var year = d.getUTCFullYear();
+ if (flagUTCTime) {
+ if (year < 1950 || 2049 < year)
+ throw "not proper year for UTCTime: " + year;
+ s = ("" + year).slice(-2);
+ } else {
+ s = ("000" + year).slice(-4);
+ }
+ s += ("0" + (d.getUTCMonth() + 1)).slice(-2);
+ s += ("0" + d.getUTCDate()).slice(-2);
+ s += ("0" + d.getUTCHours()).slice(-2);
+ s += ("0" + d.getUTCMinutes()).slice(-2);
+ s += ("0" + d.getUTCSeconds()).slice(-2);
+ if (flagMilli) {
+ var milli = d.getUTCMilliseconds();
+ if (milli !== 0) {
+ milli = ("00" + milli).slice(-3);
+ milli = milli.replace(/0+$/g, "");
+ s += "." + milli;
+ }
+ }
+ s += "Z";
+ return s;
+}
+
+// ==== URIComponent / hex ================================
+/**
+ * convert a URLComponent string such like "%67%68" to a hexadecimal string.
+ * @name uricmptohex
+ * @function
+ * @param {String} s URIComponent string such like "%67%68"
+ * @return {String} hexadecimal string
+ * @since 1.1
+ */
+function uricmptohex(s) {
+ return s.replace(/%/g, "");
+}
+
+/**
+ * convert a hexadecimal string to a URLComponent string such like "%67%68".
+ * @name hextouricmp
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} URIComponent string such like "%67%68"
+ * @since 1.1
+ */
+function hextouricmp(s) {
+ return s.replace(/(..)/g, "%$1");
+}
+
+// ==== hex / ipv6 =================================
+
+/**
+ * convert any IPv6 address to a 16 byte hexadecimal string
+ * @function
+ * @param s string of IPv6 address
+ * @return {String} 16 byte hexadecimal string of IPv6 address
+ * @description
+ * This function converts any IPv6 address representation string
+ * to a 16 byte hexadecimal string of address.
+ * @example
+ *
+ */
+function ipv6tohex(s) {
+ var msgMalformedAddress = "malformed IPv6 address";
+ if (! s.match(/^[0-9A-Fa-f:]+$/))
+ throw msgMalformedAddress;
+
+ // 1. downcase
+ s = s.toLowerCase();
+
+ // 2. expand ::
+ var num_colon = s.split(':').length - 1;
+ if (num_colon < 2) throw msgMalformedAddress;
+ var colon_replacer = ':'.repeat(7 - num_colon + 2);
+ s = s.replace('::', colon_replacer);
+
+ // 3. fill zero
+ var a = s.split(':');
+ if (a.length != 8) throw msgMalformedAddress;
+ for (var i = 0; i < 8; i++) {
+ a[i] = ("0000" + a[i]).slice(-4);
+ }
+ return a.join('');
+}
+
+/**
+ * convert a 16 byte hexadecimal string to RFC 5952 canonicalized IPv6 address
+ * @name hextoipv6
+ * @function
+ * @param {String} s hexadecimal string of 16 byte IPv6 address
+ * @return {String} IPv6 address string canonicalized by RFC 5952
+ * @since jsrsasign 8.0.10 base64x 1.1.13
+ * @description
+ * This function converts a 16 byte hexadecimal string to
+ * RFC 5952
+ * canonicalized IPv6 address string.
+ * @example
+ * hextoip("871020010db8000000000000000000000004") &rarr "2001:db8::4"
+ * hextoip("871020010db8000000000000000000") &rarr raise exception
+ * hextoip("xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyz") &rarr raise exception
+ */
+function hextoipv6(s) {
+ if (! s.match(/^[0-9A-Fa-f]{32}$/))
+ throw "malformed IPv6 address octet";
+
+ // 1. downcase
+ s = s.toLowerCase();
+
+ // 2. split 4
+ var a = s.match(/.{1,4}/g);
+
+ // 3. trim leading 0
+ for (var i = 0; i < 8; i++) {
+ a[i] = a[i].replace(/^0+/, "");
+ if (a[i] == '') a[i] = '0';
+ }
+ s = ":" + a.join(":") + ":";
+
+ // 4. find shrinkables :0:0:...
+ var aZero = s.match(/:(0:){2,}/g);
+
+ // 5. no shrinkable
+ if (aZero === null) return s.slice(1, -1);
+
+ // 6. find max length :0:0:...
+ var item = '';
+ for (var i = 0; i < aZero.length; i++) {
+ if (aZero[i].length > item.length) item = aZero[i];
+ }
+
+ // 7. shrink
+ s = s.replace(item, '::');
+ return s.slice(1, -1);
+}
+
+// ==== hex / ip =================================
+
+/**
+ * convert a hexadecimal string to IP addresss
+ * @name hextoip
+ * @function
+ * @param {String} s hexadecimal string of IP address
+ * @return {String} IP address string
+ * @since jsrsasign 8.0.10 base64x 1.1.13
+ * @description
+ * This function converts a hexadecimal string of IPv4 or
+ * IPv6 address to IPv4 or IPv6 address string.
+ * If byte length is not 4 nor 16, this returns a
+ * hexadecimal string without conversion.
+ * @see {@link hextoipv6}
+ * @example
+ * hextoip("c0a80101") &rarr "192.168.1.1"
+ * hextoip("871020010db8000000000000000000000004") &rarr "2001:db8::4"
+ * hextoip("c0a801010203") &rarr "c0a801010203" // 6 bytes
+ * hextoip("zzz")) &rarr raise exception because of not hexadecimal
+ */
+function hextoip(s) {
+ var malformedMsg = "malformed hex value";
+ if (! s.match(/^([0-9A-Fa-f][0-9A-Fa-f]){1,}$/))
+ throw malformedMsg;
+ if (s.length == 8) { // ipv4
+ var ip;
+ try {
+ ip = parseInt(s.substr(0, 2), 16) + "." +
+ parseInt(s.substr(2, 2), 16) + "." +
+ parseInt(s.substr(4, 2), 16) + "." +
+ parseInt(s.substr(6, 2), 16);
+ return ip;
+ } catch (ex) {
+ throw malformedMsg;
+ }
+ } else if (s.length == 32) {
+ return hextoipv6(s);
+ } else {
+ return s;
+ }
+}
+
+/**
+ * convert IPv4/v6 addresss to a hexadecimal string
+ * @name iptohex
+ * @function
+ * @param {String} s IPv4/v6 address string
+ * @return {String} hexadecimal string of IP address
+ * @since jsrsasign 8.0.12 base64x 1.1.14
+ * @description
+ * This function converts IPv4 or IPv6 address string to
+ * a hexadecimal string of IPv4 or IPv6 address.
+ * @example
+ * iptohex("192.168.1.1") &rarr "c0a80101"
+ * iptohex("2001:db8::4") &rarr "871020010db8000000000000000000000004"
+ * iptohex("zzz")) &rarr raise exception
+ */
+function iptohex(s) {
+ var malformedMsg = "malformed IP address";
+ s = s.toLowerCase(s);
+
+ if (s.match(/^[0-9.]+$/)) {
+ var a = s.split(".");
+ if (a.length !== 4) throw malformedMsg;
+ var hex = "";
+ try {
+ for (var i = 0; i < 4; i++) {
+ var d = parseInt(a[i]);
+ hex += ("0" + d.toString(16)).slice(-2);
+ }
+ return hex;
+ } catch(ex) {
+ throw malformedMsg;
+ }
+ } else if (s.match(/^[0-9a-f:]+$/) && s.indexOf(":") !== -1) {
+ return ipv6tohex(s);
+ } else {
+ throw malformedMsg;
+ }
+}
+
+// ==== URIComponent ================================
+/**
+ * convert UTFa hexadecimal string to a URLComponent string such like "%67%68".
+ * Note that these "0-9A-Za-z!'()*-._~
" characters will not
+ * converted to "%xx" format by builtin 'encodeURIComponent()' function.
+ * However this 'encodeURIComponentAll()' function will convert
+ * all of characters into "%xx" format.
+ * @name encodeURIComponentAll
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} URIComponent string such like "%67%68"
+ * @since 1.1
+ */
+function encodeURIComponentAll(u8) {
+ var s = encodeURIComponent(u8);
+ var s2 = "";
+ for (var i = 0; i < s.length; i++) {
+ if (s[i] == "%") {
+ s2 = s2 + s.substr(i, 3);
+ i = i + 2;
+ } else {
+ s2 = s2 + "%" + stohex(s[i]);
+ }
+ }
+ return s2;
+}
+
+// ==== new lines ================================
+/**
+ * convert all DOS new line("\r\n") to UNIX new line("\n") in
+ * a String "s".
+ * @name newline_toUnix
+ * @function
+ * @param {String} s string
+ * @return {String} converted string
+ */
+function newline_toUnix(s) {
+ s = s.replace(/\r\n/mg, "\n");
+ return s;
+}
+
+/**
+ * convert all UNIX new line("\r\n") to DOS new line("\n") in
+ * a String "s".
+ * @name newline_toDos
+ * @function
+ * @param {String} s string
+ * @return {String} converted string
+ */
+function newline_toDos(s) {
+ s = s.replace(/\r\n/mg, "\n");
+ s = s.replace(/\n/mg, "\r\n");
+ return s;
+}
+
+// ==== string type checker ===================
+
+/**
+ * check whether a string is an integer string or not
+ * @name isInteger
+ * @memberOf KJUR.lang.String
+ * @function
+ * @static
+ * @param {String} s input string
+ * @return {Boolean} true if a string "s" is an integer string otherwise false
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @example
+ * KJUR.lang.String.isInteger("12345") → true
+ * KJUR.lang.String.isInteger("123ab") → false
+ */
+KJUR.lang.String.isInteger = function(s) {
+ if (s.match(/^[0-9]+$/)) {
+ return true;
+ } else if (s.match(/^-[0-9]+$/)) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * check whether a string is an hexadecimal string or not
+ * @name isHex
+ * @memberOf KJUR.lang.String
+ * @function
+ * @static
+ * @param {String} s input string
+ * @return {Boolean} true if a string "s" is an hexadecimal string otherwise false
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @example
+ * KJUR.lang.String.isHex("1234") → true
+ * KJUR.lang.String.isHex("12ab") → true
+ * KJUR.lang.String.isHex("12AB") → true
+ * KJUR.lang.String.isHex("12ZY") → false
+ * KJUR.lang.String.isHex("121") → false -- odd length
+ */
+KJUR.lang.String.isHex = function(s) {
+ if (s.length % 2 == 0 &&
+ (s.match(/^[0-9a-f]+$/) || s.match(/^[0-9A-F]+$/))) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * check whether a string is a base64 encoded string or not
+ * Input string can conclude new lines or space characters.
+ * @name isBase64
+ * @memberOf KJUR.lang.String
+ * @function
+ * @static
+ * @param {String} s input string
+ * @return {Boolean} true if a string "s" is a base64 encoded string otherwise false
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @example
+ * KJUR.lang.String.isBase64("YWE=") → true
+ * KJUR.lang.String.isBase64("YW_=") → false
+ * KJUR.lang.String.isBase64("YWE") → false -- length shall be multiples of 4
+ */
+KJUR.lang.String.isBase64 = function(s) {
+ s = s.replace(/\s+/g, "");
+ if (s.match(/^[0-9A-Za-z+\/]+={0,3}$/) && s.length % 4 == 0) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * check whether a string is a base64url encoded string or not
+ * Input string can conclude new lines or space characters.
+ * @name isBase64URL
+ * @memberOf KJUR.lang.String
+ * @function
+ * @static
+ * @param {String} s input string
+ * @return {Boolean} true if a string "s" is a base64url encoded string otherwise false
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @example
+ * KJUR.lang.String.isBase64URL("YWE") → true
+ * KJUR.lang.String.isBase64URL("YW-") → true
+ * KJUR.lang.String.isBase64URL("YW+") → false
+ */
+KJUR.lang.String.isBase64URL = function(s) {
+ if (s.match(/[+/=]/)) return false;
+ s = b64utob64(s);
+ return KJUR.lang.String.isBase64(s);
+};
+
+/**
+ * check whether a string is a string of integer array or not
+ * Input string can conclude new lines or space characters.
+ * @name isIntegerArray
+ * @memberOf KJUR.lang.String
+ * @function
+ * @static
+ * @param {String} s input string
+ * @return {Boolean} true if a string "s" is a string of integer array otherwise false
+ * @since base64x 1.1.7 jsrsasign 5.0.13
+ * @example
+ * KJUR.lang.String.isIntegerArray("[1,2,3]") → true
+ * KJUR.lang.String.isIntegerArray(" [1, 2, 3 ] ") → true
+ * KJUR.lang.String.isIntegerArray("[a,2]") → false
+ */
+KJUR.lang.String.isIntegerArray = function(s) {
+ s = s.replace(/\s+/g, "");
+ if (s.match(/^\[[0-9,]+\]$/)) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+// ==== others ================================
+
+/**
+ * canonicalize hexadecimal string of positive integer
+ * @name hextoposhex
+ * @function
+ * @param {String} s hexadecimal string
+ * @return {String} canonicalized hexadecimal string of positive integer
+ * @since base64x 1.1.10 jsrsasign 7.1.4
+ * @description
+ * This method canonicalize a hexadecimal string of positive integer
+ * for two's complement representation.
+ * Canonicalized hexadecimal string of positive integer will be:
+ *
+ * - Its length is always even.
+ * - If odd length it will be padded with leading zero.
-
+ *
- If it is even length and its first character is "8" or greater,
+ * it will be padded with "00" to make it positive integer.
+ *
+ * @example
+ * hextoposhex("abcd") → "00abcd"
+ * hextoposhex("1234") → "1234"
+ * hextoposhex("12345") → "012345"
+ */
+function hextoposhex(s) {
+ if (s.length % 2 == 1) return "0" + s;
+ if (s.substr(0, 1) > "7") return "00" + s;
+ return s;
+}
+
+/**
+ * convert string of integer array to hexadecimal string.
+ * @name intarystrtohex
+ * @function
+ * @param {String} s string of integer array
+ * @return {String} hexadecimal string
+ * @since base64x 1.1.6 jsrsasign 5.0.2
+ * @throws "malformed integer array string: *" for wrong input
+ * @description
+ * This function converts a string of JavaScript integer array to
+ * a hexadecimal string. Each integer value shall be in a range
+ * from 0 to 255 otherwise it raise exception. Input string can
+ * have extra space or newline string so that they will be ignored.
+ *
+ * @example
+ * intarystrtohex(" [123, 34, 101, 34, 58] ")
+ * → 7b2265223a (i.e. '{"e":' as string)
+ */
+function intarystrtohex(s) {
+ s = s.replace(/^\s*\[\s*/, '');
+ s = s.replace(/\s*\]\s*$/, '');
+ s = s.replace(/\s*/g, '');
+ try {
+ var hex = s.split(/,/).map(function(element, index, array) {
+ var i = parseInt(element);
+ if (i < 0 || 255 < i) throw "integer not in range 0-255";
+ var hI = ("00" + i.toString(16)).slice(-2);
+ return hI;
+ }).join('');
+ return hex;
+ } catch(ex) {
+ throw "malformed integer array string: " + ex;
+ }
+}
+
+/**
+ * find index of string where two string differs
+ * @name strdiffidx
+ * @function
+ * @param {String} s1 string to compare
+ * @param {String} s2 string to compare
+ * @return {Number} string index of where character differs. Return -1 if same.
+ * @since jsrsasign 4.9.0 base64x 1.1.5
+ * @example
+ * strdiffidx("abcdefg", "abcd4fg") -> 4
+ * strdiffidx("abcdefg", "abcdefg") -> -1
+ * strdiffidx("abcdefg", "abcdef") -> 6
+ * strdiffidx("abcdefgh", "abcdef") -> 6
+ */
+var strdiffidx = function(s1, s2) {
+ var n = s1.length;
+ if (s1.length > s2.length) n = s2.length;
+ for (var i = 0; i < n; i++) {
+ if (s1.charCodeAt(i) != s2.charCodeAt(i)) return i;
+ }
+ if (s1.length != s2.length) return n;
+ return -1; // same
+};
+
+
diff --git a/source/build.md b/source/build.md
new file mode 100644
index 0000000..91ae12a
--- /dev/null
+++ b/source/build.md
@@ -0,0 +1,17 @@
+yahoo.js
+cryptojs-312-core-fix.js
+jsbn.js
+jsbn2.js
+ec.js
+prng4.js
+rng.js
+rsa.js
+sha256.js
+asn1-1.0.js
+asn1hex-1.1.js
+base64x-1.1.js
+crypto-1.1.js
+ecdsa-modified-1.0.js
+ecparam-1.0.js
+keyutil-1.0.js
+pack.js
\ No newline at end of file
diff --git a/source/crypto-1.1.js b/source/crypto-1.1.js
new file mode 100644
index 0000000..ffc3f2e
--- /dev/null
+++ b/source/crypto-1.1.js
@@ -0,0 +1,1466 @@
+/* crypto-1.2.1.js (c) 2013-2017 Kenji Urushima | kjur.github.io/jsrsasign/license
+ */
+/*
+ * crypto.js - Cryptographic Algorithm Provider class
+ *
+ * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * https://kjur.github.io/jsrsasign/license
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name crypto-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.2.1 (2017-Sep-15)
+ * @since jsrsasign 2.2
+ * @license MIT License
+ */
+
+/**
+ * kjur's class library name space
+ * @name KJUR
+ * @namespace kjur's class library name space
+ */
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+/**
+ * kjur's cryptographic algorithm provider library name space
+ *
+ * This namespace privides following crytpgrahic classes.
+ *
+ * - {@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class
+ * - {@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class
+ * - {@link KJUR.crypto.Cipher} - class for encrypting and decrypting data
+ * - {@link KJUR.crypto.Util} - cryptographic utility functions and properties
+ *
+ * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
+ *
+ * @name KJUR.crypto
+ * @namespace
+ */
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.Util
+ * @class static object for cryptographic function utilities
+ * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms
+ * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms
+ * @description
+ */
+KJUR.crypto.Util = new function() {
+ this.DIGESTINFOHEAD = {
+ 'sha1': "3021300906052b0e03021a05000414",
+ 'sha224': "302d300d06096086480165030402040500041c",
+ 'sha256': "3031300d060960864801650304020105000420",
+ 'sha384': "3041300d060960864801650304020205000430",
+ 'sha512': "3051300d060960864801650304020305000440",
+ 'md2': "3020300c06082a864886f70d020205000410",
+ 'md5': "3020300c06082a864886f70d020505000410",
+ 'ripemd160': "3021300906052b2403020105000414",
+ };
+
+ /*
+ * @since crypto 1.1.1
+ */
+ this.DEFAULTPROVIDER = {
+ 'md5': 'cryptojs',
+ 'sha1': 'cryptojs',
+ 'sha224': 'cryptojs',
+ 'sha256': 'cryptojs',
+ 'sha384': 'cryptojs',
+ 'sha512': 'cryptojs',
+ 'ripemd160': 'cryptojs',
+ 'hmacmd5': 'cryptojs',
+ 'hmacsha1': 'cryptojs',
+ 'hmacsha224': 'cryptojs',
+ 'hmacsha256': 'cryptojs',
+ 'hmacsha384': 'cryptojs',
+ 'hmacsha512': 'cryptojs',
+ 'hmacripemd160': 'cryptojs',
+
+ 'MD5withRSA': 'cryptojs/jsrsa',
+ 'SHA1withRSA': 'cryptojs/jsrsa',
+ 'SHA224withRSA': 'cryptojs/jsrsa',
+ 'SHA256withRSA': 'cryptojs/jsrsa',
+ 'SHA384withRSA': 'cryptojs/jsrsa',
+ 'SHA512withRSA': 'cryptojs/jsrsa',
+ 'RIPEMD160withRSA': 'cryptojs/jsrsa',
+
+ 'MD5withECDSA': 'cryptojs/jsrsa',
+ 'SHA1withECDSA': 'cryptojs/jsrsa',
+ 'SHA224withECDSA': 'cryptojs/jsrsa',
+ 'SHA256withECDSA': 'cryptojs/jsrsa',
+ 'SHA384withECDSA': 'cryptojs/jsrsa',
+ 'SHA512withECDSA': 'cryptojs/jsrsa',
+ 'RIPEMD160withECDSA': 'cryptojs/jsrsa',
+
+ 'SHA1withDSA': 'cryptojs/jsrsa',
+ 'SHA224withDSA': 'cryptojs/jsrsa',
+ 'SHA256withDSA': 'cryptojs/jsrsa',
+
+ 'MD5withRSAandMGF1': 'cryptojs/jsrsa',
+ 'SHA1withRSAandMGF1': 'cryptojs/jsrsa',
+ 'SHA224withRSAandMGF1': 'cryptojs/jsrsa',
+ 'SHA256withRSAandMGF1': 'cryptojs/jsrsa',
+ 'SHA384withRSAandMGF1': 'cryptojs/jsrsa',
+ 'SHA512withRSAandMGF1': 'cryptojs/jsrsa',
+ 'RIPEMD160withRSAandMGF1': 'cryptojs/jsrsa',
+ };
+
+ /*
+ * @since crypto 1.1.2
+ */
+ this.CRYPTOJSMESSAGEDIGESTNAME = {
+ 'md5': CryptoJS.algo.MD5,
+ 'sha1': CryptoJS.algo.SHA1,
+ 'sha224': CryptoJS.algo.SHA224,
+ 'sha256': CryptoJS.algo.SHA256,
+ 'sha384': CryptoJS.algo.SHA384,
+ 'sha512': CryptoJS.algo.SHA512,
+ 'ripemd160': CryptoJS.algo.RIPEMD160
+ };
+
+ /**
+ * get hexadecimal DigestInfo
+ * @name getDigestInfoHex
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} hHash hexadecimal hash value
+ * @param {String} alg hash algorithm name (ex. 'sha1')
+ * @return {String} hexadecimal string DigestInfo ASN.1 structure
+ */
+ this.getDigestInfoHex = function(hHash, alg) {
+ if (typeof this.DIGESTINFOHEAD[alg] == "undefined")
+ throw "alg not supported in Util.DIGESTINFOHEAD: " + alg;
+ return this.DIGESTINFOHEAD[alg] + hHash;
+ };
+
+ /**
+ * get PKCS#1 padded hexadecimal DigestInfo
+ * @name getPaddedDigestInfoHex
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} hHash hexadecimal hash value of message to be signed
+ * @param {String} alg hash algorithm name (ex. 'sha1')
+ * @param {Integer} keySize key bit length (ex. 1024)
+ * @return {String} hexadecimal string of PKCS#1 padded DigestInfo
+ */
+ this.getPaddedDigestInfoHex = function(hHash, alg, keySize) {
+ var hDigestInfo = this.getDigestInfoHex(hHash, alg);
+ var pmStrLen = keySize / 4; // minimum PM length
+
+ if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22
+ throw "key is too short for SigAlg: keylen=" + keySize + "," + alg;
+
+ var hHead = "0001";
+ var hTail = "00" + hDigestInfo;
+ var hMid = "";
+ var fLen = pmStrLen - hHead.length - hTail.length;
+ for (var i = 0; i < fLen; i += 2) {
+ hMid += "ff";
+ }
+ var hPaddedMessage = hHead + hMid + hTail;
+ return hPaddedMessage;
+ };
+
+ /**
+ * get hexadecimal hash of string with specified algorithm
+ * @name hashString
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @param {String} alg hash algorithm name
+ * @return {String} hexadecimal string of hash value
+ * @since 1.1.1
+ */
+ this.hashString = function(s, alg) {
+ var md = new KJUR.crypto.MessageDigest({'alg': alg});
+ return md.digestString(s);
+ };
+
+ /**
+ * get hexadecimal hash of hexadecimal string with specified algorithm
+ * @name hashHex
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} sHex input hexadecimal string to be hashed
+ * @param {String} alg hash algorithm name
+ * @return {String} hexadecimal string of hash value
+ * @since 1.1.1
+ */
+ this.hashHex = function(sHex, alg) {
+ var md = new KJUR.crypto.MessageDigest({'alg': alg});
+ return md.digestHex(sHex);
+ };
+
+ /**
+ * get hexadecimal SHA1 hash of string
+ * @name sha1
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @return {String} hexadecimal string of hash value
+ * @since 1.0.3
+ */
+ this.sha1 = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'});
+ return md.digestString(s);
+ };
+
+ /**
+ * get hexadecimal SHA256 hash of string
+ * @name sha256
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @return {String} hexadecimal string of hash value
+ * @since 1.0.3
+ */
+ this.sha256 = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+ return md.digestString(s);
+ };
+
+ this.sha256Hex = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
+ return md.digestHex(s);
+ };
+
+ /**
+ * get hexadecimal SHA512 hash of string
+ * @name sha512
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @return {String} hexadecimal string of hash value
+ * @since 1.0.3
+ */
+ this.sha512 = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+ return md.digestString(s);
+ };
+
+ this.sha512Hex = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
+ return md.digestHex(s);
+ };
+
+};
+
+/**
+ * get hexadecimal MD5 hash of string
+ * @name md5
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @return {String} hexadecimal string of hash value
+ * @since 1.0.3
+ * @example
+ * Util.md5('aaa') → 47bce5c74f589f4867dbd57e9ca9f808
+ */
+KJUR.crypto.Util.md5 = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'});
+ return md.digestString(s);
+};
+
+/**
+ * get hexadecimal RIPEMD160 hash of string
+ * @name ripemd160
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {String} s input string to be hashed
+ * @return {String} hexadecimal string of hash value
+ * @since 1.0.3
+ * @example
+ * KJUR.crypto.Util.ripemd160("aaa") → 08889bd7b151aa174c21f33f59147fa65381edea
+ */
+KJUR.crypto.Util.ripemd160 = function(s) {
+ var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
+ return md.digestString(s);
+};
+
+// @since jsrsasign 7.0.0 crypto 1.1.11
+KJUR.crypto.Util.SECURERANDOMGEN = new SecureRandom();
+
+/**
+ * get hexadecimal string of random value from with specified byte length
+ * @name getRandomHexOfNbytes
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {Integer} n length of bytes of random
+ * @return {String} hexadecimal string of random
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @example
+ * KJUR.crypto.Util.getRandomHexOfNbytes(3) → "6314af", "000000" or "001fb4"
+ * KJUR.crypto.Util.getRandomHexOfNbytes(128) → "8fbc..." in 1024bits
+ */
+KJUR.crypto.Util.getRandomHexOfNbytes = function(n) {
+ var ba = new Array(n);
+ KJUR.crypto.Util.SECURERANDOMGEN.nextBytes(ba);
+ return BAtohex(ba);
+};
+
+/**
+ * get BigInteger object of random value from with specified byte length
+ * @name getRandomBigIntegerOfNbytes
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {Integer} n length of bytes of random
+ * @return {BigInteger} BigInteger object of specified random value
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @example
+ * KJUR.crypto.Util.getRandomBigIntegerOfNbytes(3) → 6314af of BigInteger
+ * KJUR.crypto.Util.getRandomBigIntegerOfNbytes(128) → 8fbc... of BigInteger
+ */
+KJUR.crypto.Util.getRandomBigIntegerOfNbytes = function(n) {
+ return new BigInteger(KJUR.crypto.Util.getRandomHexOfNbytes(n), 16);
+};
+
+/**
+ * get hexadecimal string of random value from with specified bit length
+ * @name getRandomHexOfNbits
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {Integer} n length of bits of random
+ * @return {String} hexadecimal string of random
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @example
+ * KJUR.crypto.Util.getRandomHexOfNbits(24) → "6314af", "000000" or "001fb4"
+ * KJUR.crypto.Util.getRandomHexOfNbits(1024) → "8fbc..." in 1024bits
+ */
+KJUR.crypto.Util.getRandomHexOfNbits = function(n) {
+ var n_remainder = n % 8;
+ var n_quotient = (n - n_remainder) / 8;
+ var ba = new Array(n_quotient + 1);
+ KJUR.crypto.Util.SECURERANDOMGEN.nextBytes(ba);
+ ba[0] = (((255 << n_remainder) & 255) ^ 255) & ba[0];
+ return BAtohex(ba);
+};
+
+/**
+ * get BigInteger object of random value from with specified bit length
+ * @name getRandomBigIntegerOfNbits
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {Integer} n length of bits of random
+ * @return {BigInteger} BigInteger object of specified random value
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @example
+ * KJUR.crypto.Util.getRandomBigIntegerOfNbits(24) → 6314af of BigInteger
+ * KJUR.crypto.Util.getRandomBigIntegerOfNbits(1024) → 8fbc... of BigInteger
+ */
+KJUR.crypto.Util.getRandomBigIntegerOfNbits = function(n) {
+ return new BigInteger(KJUR.crypto.Util.getRandomHexOfNbits(n), 16);
+};
+
+/**
+ * get BigInteger object of random value from zero to max value
+ * @name getRandomBigIntegerZeroToMax
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {BigInteger} biMax max value of BigInteger object for random value
+ * @return {BigInteger} BigInteger object of specified random value
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @description
+ * This static method generates a BigInteger object with random value
+ * greater than or equal to zero and smaller than or equal to biMax
+ * (i.e. 0 ≤ result ≤ biMax).
+ * @example
+ * biMax = new BigInteger("3fa411...", 16);
+ * KJUR.crypto.Util.getRandomBigIntegerZeroToMax(biMax) → 8fbc... of BigInteger
+ */
+KJUR.crypto.Util.getRandomBigIntegerZeroToMax = function(biMax) {
+ var bitLenMax = biMax.bitLength();
+ while (1) {
+ var biRand = KJUR.crypto.Util.getRandomBigIntegerOfNbits(bitLenMax);
+ if (biMax.compareTo(biRand) != -1) return biRand;
+ }
+};
+
+/**
+ * get BigInteger object of random value from min value to max value
+ * @name getRandomBigIntegerMinToMax
+ * @memberOf KJUR.crypto.Util
+ * @function
+ * @param {BigInteger} biMin min value of BigInteger object for random value
+ * @param {BigInteger} biMax max value of BigInteger object for random value
+ * @return {BigInteger} BigInteger object of specified random value
+ * @since jsrsasign 7.0.0 crypto 1.1.11
+ * @description
+ * This static method generates a BigInteger object with random value
+ * greater than or equal to biMin and smaller than or equal to biMax
+ * (i.e. biMin ≤ result ≤ biMax).
+ * @example
+ * biMin = new BigInteger("2fa411...", 16);
+ * biMax = new BigInteger("3fa411...", 16);
+ * KJUR.crypto.Util.getRandomBigIntegerMinToMax(biMin, biMax) → 32f1... of BigInteger
+ */
+KJUR.crypto.Util.getRandomBigIntegerMinToMax = function(biMin, biMax) {
+ var flagCompare = biMin.compareTo(biMax);
+ if (flagCompare == 1) throw "biMin is greater than biMax";
+ if (flagCompare == 0) return biMin;
+
+ var biDiff = biMax.subtract(biMin);
+ var biRand = KJUR.crypto.Util.getRandomBigIntegerZeroToMax(biDiff);
+ return biRand.add(biMin);
+};
+
+// === Mac ===============================================================
+
+/**
+ * MessageDigest class which is very similar to java.security.MessageDigest class
+ * @name KJUR.crypto.MessageDigest
+ * @class MessageDigest class which is very similar to java.security.MessageDigest class
+ * @param {Array} params parameters for constructor
+ * @property {Array} HASHLENGTH static Array of resulted byte length of hash (ex. HASHLENGTH["sha1"] == 20)
+ * @description
+ *
+ * Currently this supports following algorithm and providers combination:
+ *
+ * - md5 - cryptojs
+ * - sha1 - cryptojs
+ * - sha224 - cryptojs
+ * - sha256 - cryptojs
+ * - sha384 - cryptojs
+ * - sha512 - cryptojs
+ * - ripemd160 - cryptojs
+ * - sha256 - sjcl (NEW from crypto.js 1.0.4)
+ *
+ * @example
+ * // CryptoJS provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ *
+ * // SJCL(Stanford JavaScript Crypto Library) provider sample
+ * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
+ * md.updateString('aaa')
+ * var mdHex = md.digest()
+ *
+ * // HASHLENGTH property
+ * KJUR.crypto.MessageDigest.HASHLENGTH['sha1'] &rarr 20
+ * KJUR.crypto.MessageDigest.HASHLENGTH['sha512'] &rarr 64
+ */
+KJUR.crypto.MessageDigest = function(params) {
+ var md = null;
+ var algName = null;
+ var provName = null;
+
+ /**
+ * set hash algorithm and provider
+ * @name setAlgAndProvider
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @param {String} alg hash algorithm name
+ * @param {String} prov provider name
+ * @description
+ * This methods set an algorithm and a cryptographic provider.
+ * Here is acceptable algorithm names ignoring cases and hyphens:
+ *
+ * - MD5
+ * - SHA1
+ * - SHA224
+ * - SHA256
+ * - SHA384
+ * - SHA512
+ * - RIPEMD160
+ *
+ * NOTE: Since jsrsasign 6.2.0 crypto 1.1.10, this method ignores
+ * upper or lower cases. Also any hyphens (i.e. "-") will be ignored
+ * so that "SHA1" or "SHA-1" will be acceptable.
+ * @example
+ * // for SHA1
+ * md.setAlgAndProvider('sha1', 'cryptojs');
+ * md.setAlgAndProvider('SHA1');
+ * // for RIPEMD160
+ * md.setAlgAndProvider('ripemd160', 'cryptojs');
+ */
+ this.setAlgAndProvider = function(alg, prov) {
+ alg = KJUR.crypto.MessageDigest.getCanonicalAlgName(alg);
+
+ if (alg !== null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+
+ // for cryptojs
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
+ prov == 'cryptojs') {
+ try {
+ this.md = KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg].create();
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.md.update(str);
+ };
+ this.updateHex = function(hex) {
+ var wHex = CryptoJS.enc.Hex.parse(hex);
+ this.md.update(wHex);
+ };
+ this.digest = function() {
+ var hash = this.md.finalize();
+ return hash.toString(CryptoJS.enc.Hex);
+ };
+ this.digestString = function(str) {
+ this.updateString(str);
+ return this.digest();
+ };
+ this.digestHex = function(hex) {
+ this.updateHex(hex);
+ return this.digest();
+ };
+ }
+ if (':sha256:'.indexOf(alg) != -1 &&
+ prov == 'sjcl') {
+ try {
+ this.md = new sjcl.hash.sha256();
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.md.update(str);
+ };
+ this.updateHex = function(hex) {
+ var baHex = sjcl.codec.hex.toBits(hex);
+ this.md.update(baHex);
+ };
+ this.digest = function() {
+ var hash = this.md.finalize();
+ return sjcl.codec.hex.fromBits(hash);
+ };
+ this.digestString = function(str) {
+ this.updateString(str);
+ return this.digest();
+ };
+ this.digestHex = function(hex) {
+ this.updateHex(hex);
+ return this.digest();
+ };
+ }
+ };
+
+ /**
+ * update digest by specified string
+ * @name updateString
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @param {String} str string to update
+ * @description
+ * @example
+ * md.updateString('New York');
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * update digest by specified hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @param {String} hex hexadecimal string to update
+ * @description
+ * @example
+ * md.updateHex('0afe36');
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * completes hash calculation and returns hash result
+ * @name digest
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @description
+ * @example
+ * md.digest()
+ */
+ this.digest = function() {
+ throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * performs final update on the digest using string, then completes the digest computation
+ * @name digestString
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @param {String} str string to final update
+ * @description
+ * @example
+ * md.digestString('aaa')
+ */
+ this.digestString = function(str) {
+ throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ /**
+ * performs final update on the digest using hexadecimal string, then completes the digest computation
+ * @name digestHex
+ * @memberOf KJUR.crypto.MessageDigest#
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @description
+ * @example
+ * md.digestHex('0f2abd')
+ */
+ this.digestHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
+ };
+
+ if (params !== undefined) {
+ if (params['alg'] !== undefined) {
+ this.algName = params['alg'];
+ if (params['prov'] === undefined)
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ this.setAlgAndProvider(this.algName, this.provName);
+ }
+ }
+};
+
+/**
+ * get canonical hash algorithm name
+ * @name getCanonicalAlgName
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} alg hash algorithm name (ex. MD5, SHA-1, SHA1, SHA512 et.al.)
+ * @return {String} canonical hash algorithm name
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * This static method normalizes from any hash algorithm name such as
+ * "SHA-1", "SHA1", "MD5", "sha512" to lower case name without hyphens
+ * such as "sha1".
+ * @example
+ * KJUR.crypto.MessageDigest.getCanonicalAlgName("SHA-1") &rarr "sha1"
+ * KJUR.crypto.MessageDigest.getCanonicalAlgName("MD5") &rarr "md5"
+ */
+KJUR.crypto.MessageDigest.getCanonicalAlgName = function(alg) {
+ if (typeof alg === "string") {
+ alg = alg.toLowerCase();
+ alg = alg.replace(/-/, '');
+ }
+ return alg;
+};
+
+/**
+ * get resulted hash byte length for specified algorithm name
+ * @name getHashLength
+ * @memberOf KJUR.crypto.MessageDigest
+ * @function
+ * @param {String} alg non-canonicalized hash algorithm name (ex. MD5, SHA-1, SHA1, SHA512 et.al.)
+ * @return {Integer} resulted hash byte length
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * This static method returns resulted byte length for specified algorithm name such as "SHA-1".
+ * @example
+ * KJUR.crypto.MessageDigest.getHashLength("SHA-1") &rarr 20
+ * KJUR.crypto.MessageDigest.getHashLength("sha1") &rarr 20
+ */
+KJUR.crypto.MessageDigest.getHashLength = function(alg) {
+ var MD = KJUR.crypto.MessageDigest
+ var alg2 = MD.getCanonicalAlgName(alg);
+ if (MD.HASHLENGTH[alg2] === undefined)
+ throw "not supported algorithm: " + alg;
+ return MD.HASHLENGTH[alg2];
+};
+
+// described in KJUR.crypto.MessageDigest class (since jsrsasign 6.2.0 crypto 1.1.10)
+KJUR.crypto.MessageDigest.HASHLENGTH = {
+ 'md5': 16,
+ 'sha1': 20,
+ 'sha224': 28,
+ 'sha256': 32,
+ 'sha384': 48,
+ 'sha512': 64,
+ 'ripemd160': 20
+};
+
+// === Mac ===============================================================
+
+/**
+ * Mac(Message Authentication Code) class which is very similar to java.security.Mac class
+ * @name KJUR.crypto.Mac
+ * @class Mac class which is very similar to java.security.Mac class
+ * @param {Array} params parameters for constructor
+ * @description
+ *
+ * Currently this supports following algorithm and providers combination:
+ *
+ * - hmacmd5 - cryptojs
+ * - hmacsha1 - cryptojs
+ * - hmacsha224 - cryptojs
+ * - hmacsha256 - cryptojs
+ * - hmacsha384 - cryptojs
+ * - hmacsha512 - cryptojs
+ *
+ * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4.
+ * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS
+ * to avoid those issue.
+ *
+ * NOTE2: Hmac signature bug was fixed in jsrsasign 4.9.0 by providing CryptoJS
+ * bug workaround.
+ *
+ * Please see {@link KJUR.crypto.Mac.setPassword}, how to provide password
+ * in various ways in detail.
+ * @example
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", "pass": "pass"});
+ * mac.updateString('aaa')
+ * var macHex = mac.doFinal()
+ *
+ * // other password representation
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"hex": "6161"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"utf8": "aa"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"rstr": "\x61\x61"}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64": "Mi02/+...a=="}});
+ * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64u": "Mi02_-...a"}});
+ */
+KJUR.crypto.Mac = function(params) {
+ var mac = null;
+ var pass = null;
+ var algName = null;
+ var provName = null;
+ var algProv = null;
+
+ this.setAlgAndProvider = function(alg, prov) {
+ alg = alg.toLowerCase();
+
+ if (alg == null) alg = "hmacsha1";
+
+ alg = alg.toLowerCase();
+ if (alg.substr(0, 4) != "hmac") {
+ throw "setAlgAndProvider unsupported HMAC alg: " + alg;
+ }
+
+ if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
+ this.algProv = alg + "/" + prov;
+
+ var hashAlg = alg.substr(4);
+
+ // for cryptojs
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 &&
+ prov == 'cryptojs') {
+ try {
+ var mdObj = KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg];
+ this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass);
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex;
+ }
+ this.updateString = function(str) {
+ this.mac.update(str);
+ };
+ this.updateHex = function(hex) {
+ var wHex = CryptoJS.enc.Hex.parse(hex);
+ this.mac.update(wHex);
+ };
+ this.doFinal = function() {
+ var hash = this.mac.finalize();
+ return hash.toString(CryptoJS.enc.Hex);
+ };
+ this.doFinalString = function(str) {
+ this.updateString(str);
+ return this.doFinal();
+ };
+ this.doFinalHex = function(hex) {
+ this.updateHex(hex);
+ return this.doFinal();
+ };
+ }
+ };
+
+ /**
+ * update digest by specified string
+ * @name updateString
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @param {String} str string to update
+ * @description
+ * @example
+ * mac.updateString('New York');
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * update digest by specified hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @param {String} hex hexadecimal string to update
+ * @description
+ * @example
+ * mac.updateHex('0afe36');
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * completes hash calculation and returns hash result
+ * @name doFinal
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @description
+ * @example
+ * mac.digest()
+ */
+ this.doFinal = function() {
+ throw "digest() not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * performs final update on the digest using string, then completes the digest computation
+ * @name doFinalString
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @param {String} str string to final update
+ * @description
+ * @example
+ * mac.digestString('aaa')
+ */
+ this.doFinalString = function(str) {
+ throw "digestString(str) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * performs final update on the digest using hexadecimal string,
+ * then completes the digest computation
+ * @name doFinalHex
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @description
+ * @example
+ * mac.digestHex('0f2abd')
+ */
+ this.doFinalHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
+ };
+
+ /**
+ * set password for Mac
+ * @name setPassword
+ * @memberOf KJUR.crypto.Mac#
+ * @function
+ * @param {Object} pass password for Mac
+ * @since crypto 1.1.7 jsrsasign 4.9.0
+ * @description
+ * This method will set password for (H)Mac internally.
+ * Argument 'pass' can be specified as following:
+ *
+ * - even length string of 0..9, a..f or A-F: implicitly specified as hexadecimal string
+ * - not above string: implicitly specified as raw string
+ * - {rstr: "\x65\x70"}: explicitly specified as raw string
+ * - {hex: "6570"}: explicitly specified as hexacedimal string
+ * - {utf8: "秘密"}: explicitly specified as UTF8 string
+ * - {b64: "Mi78..=="}: explicitly specified as Base64 string
+ * - {b64u: "Mi7-_"}: explicitly specified as Base64URL string
+ *
+ * It is *STRONGLY RECOMMENDED* that explicit representation of password argument
+ * to avoid ambiguity. For example string "6161" can mean a string "6161" or
+ * a hexadecimal string of "aa" (i.e. \x61\x61).
+ * @example
+ * mac = KJUR.crypto.Mac({'alg': 'hmacsha256'});
+ * // set password by implicit raw string
+ * mac.setPassword("\x65\x70\xb9\x0b");
+ * mac.setPassword("password");
+ * // set password by implicit hexadecimal string
+ * mac.setPassword("6570b90b");
+ * mac.setPassword("6570B90B");
+ * // set password by explicit raw string
+ * mac.setPassword({"rstr": "\x65\x70\xb9\x0b"});
+ * // set password by explicit hexadecimal string
+ * mac.setPassword({"hex": "6570b90b"});
+ * // set password by explicit utf8 string
+ * mac.setPassword({"utf8": "passwordパスワード");
+ * // set password by explicit Base64 string
+ * mac.setPassword({"b64": "Mb+c3f/=="});
+ * // set password by explicit Base64URL string
+ * mac.setPassword({"b64u": "Mb-c3f_"});
+ */
+ this.setPassword = function(pass) {
+ // internal this.pass shall be CryptoJS DWord Object for CryptoJS bug
+ // work around. CrytoJS HMac password can be passed by
+ // raw string as described in the manual however it doesn't
+ // work properly in some case. If password was passed
+ // by CryptoJS DWord which is not described in the manual
+ // it seems to work. (fixed since crypto 1.1.7)
+
+ if (typeof pass == 'string') {
+ var hPass = pass;
+ if (pass.length % 2 == 1 || ! pass.match(/^[0-9A-Fa-f]+$/)) { // raw str
+ hPass = rstrtohex(pass);
+ }
+ this.pass = CryptoJS.enc.Hex.parse(hPass);
+ return;
+ }
+
+ if (typeof pass != 'object')
+ throw "KJUR.crypto.Mac unsupported password type: " + pass;
+
+ var hPass = null;
+ if (pass.hex !== undefined) {
+ if (pass.hex.length % 2 != 0 || ! pass.hex.match(/^[0-9A-Fa-f]+$/))
+ throw "Mac: wrong hex password: " + pass.hex;
+ hPass = pass.hex;
+ }
+ if (pass.utf8 !== undefined) hPass = utf8tohex(pass.utf8);
+ if (pass.rstr !== undefined) hPass = rstrtohex(pass.rstr);
+ if (pass.b64 !== undefined) hPass = b64tohex(pass.b64);
+ if (pass.b64u !== undefined) hPass = b64utohex(pass.b64u);
+
+ if (hPass == null)
+ throw "KJUR.crypto.Mac unsupported password type: " + pass;
+
+ this.pass = CryptoJS.enc.Hex.parse(hPass);
+ };
+
+ if (params !== undefined) {
+ if (params.pass !== undefined) {
+ this.setPassword(params.pass);
+ }
+ if (params.alg !== undefined) {
+ this.algName = params.alg;
+ if (params['prov'] === undefined)
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ this.setAlgAndProvider(this.algName, this.provName);
+ }
+ }
+};
+
+// ====== Signature class =========================================================
+/**
+ * Signature class which is very similar to java.security.Signature class
+ * @name KJUR.crypto.Signature
+ * @class Signature class which is very similar to java.security.Signature class
+ * @param {Array} params parameters for constructor
+ * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
+ * @description
+ *
+ * As for params of constructor's argument, it can be specify following attributes:
+ *
+ * - alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})
+ * - provider - currently 'cryptojs/jsrsa' only
+ *
+ * SUPPORTED ALGORITHMS AND PROVIDERS
+ * This Signature class supports following signature algorithm and provider names:
+ *
+ * - MD5withRSA - cryptojs/jsrsa
+ * - SHA1withRSA - cryptojs/jsrsa
+ * - SHA224withRSA - cryptojs/jsrsa
+ * - SHA256withRSA - cryptojs/jsrsa
+ * - SHA384withRSA - cryptojs/jsrsa
+ * - SHA512withRSA - cryptojs/jsrsa
+ * - RIPEMD160withRSA - cryptojs/jsrsa
+ * - MD5withECDSA - cryptojs/jsrsa
+ * - SHA1withECDSA - cryptojs/jsrsa
+ * - SHA224withECDSA - cryptojs/jsrsa
+ * - SHA256withECDSA - cryptojs/jsrsa
+ * - SHA384withECDSA - cryptojs/jsrsa
+ * - SHA512withECDSA - cryptojs/jsrsa
+ * - RIPEMD160withECDSA - cryptojs/jsrsa
+ * - MD5withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA1withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA224withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA256withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA384withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA512withRSAandMGF1 - cryptojs/jsrsa
+ * - RIPEMD160withRSAandMGF1 - cryptojs/jsrsa
+ * - SHA1withDSA - cryptojs/jsrsa
+ * - SHA224withDSA - cryptojs/jsrsa
+ * - SHA256withDSA - cryptojs/jsrsa
+ *
+ * Here are supported elliptic cryptographic curve names and their aliases for ECDSA:
+ *
+ * - secp256k1
+ * - secp256r1, NIST P-256, P-256, prime256v1
+ * - secp384r1, NIST P-384, P-384
+ *
+ * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5.
+ * EXAMPLES
+ * @example
+ * // RSA signature generation
+ * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var hSigVal = sig.sign();
+ *
+ * // DSA signature validation
+ * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
+ * sig2.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig2.verify(hSigVal);
+ *
+ * // ECDSA signing
+ * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(prvKeyPEM);
+ * sig.updateString('aaa');
+ * var sigValueHex = sig.sign();
+ *
+ * // ECDSA verifying
+ * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
+ * sig.init(certPEM);
+ * sig.updateString('aaa');
+ * var isValid = sig.verify(sigValueHex);
+ */
+KJUR.crypto.Signature = function(params) {
+ var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing
+ var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying
+
+ var md = null; // KJUR.crypto.MessageDigest object
+ var sig = null;
+ var algName = null;
+ var provName = null;
+ var algProvName = null;
+ var mdAlgName = null;
+ var pubkeyAlgName = null; // rsa,ecdsa,rsaandmgf1(=rsapss)
+ var state = null;
+ var pssSaltLen = -1;
+ var initParams = null;
+
+ var sHashHex = null; // hex hash value for hex
+ var hDigestInfo = null;
+ var hPaddedDigestInfo = null;
+ var hSign = null;
+
+ this._setAlgNames = function() {
+ var matchResult = this.algName.match(/^(.+)with(.+)$/);
+ if (matchResult) {
+ this.mdAlgName = matchResult[1].toLowerCase();
+ this.pubkeyAlgName = matchResult[2].toLowerCase();
+ }
+ };
+
+ this._zeroPaddingOfSignature = function(hex, bitLength) {
+ var s = "";
+ var nZero = bitLength / 4 - hex.length;
+ for (var i = 0; i < nZero; i++) {
+ s = s + "0";
+ }
+ return s + hex;
+ };
+
+ /**
+ * set signature algorithm and provider
+ * @name setAlgAndProvider
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} alg signature algorithm name
+ * @param {String} prov provider name
+ * @description
+ * @example
+ * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
+ */
+ this.setAlgAndProvider = function(alg, prov) {
+ this._setAlgNames();
+ if (prov != 'cryptojs/jsrsa')
+ throw "provider not supported: " + prov;
+
+ if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
+ try {
+ this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName});
+ } catch (ex) {
+ throw "setAlgAndProvider hash alg set fail alg=" +
+ this.mdAlgName + "/" + ex;
+ }
+
+ this.init = function(keyparam, pass) {
+ var keyObj = null;
+ try {
+ if (pass === undefined) {
+ keyObj = KEYUTIL.getKey(keyparam);
+ } else {
+ keyObj = KEYUTIL.getKey(keyparam, pass);
+ }
+ } catch (ex) {
+ throw "init failed:" + ex;
+ }
+
+ if (keyObj.isPrivate === true) {
+ this.prvKey = keyObj;
+ this.state = "SIGN";
+ } else if (keyObj.isPublic === true) {
+ this.pubKey = keyObj;
+ this.state = "VERIFY";
+ } else {
+ throw "init failed.:" + keyObj;
+ }
+ };
+
+ this.updateString = function(str) {
+ this.md.updateString(str);
+ };
+
+ this.updateHex = function(hex) {
+ this.md.updateHex(hex);
+ };
+
+ this.sign = function() {
+ this.sHashHex = this.md.digest();
+ if (typeof this.ecprvhex != "undefined" &&
+ typeof this.eccurvename != "undefined") {
+ var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
+ this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
+ } else if (this.prvKey instanceof RSAKey &&
+ this.pubkeyAlgName === "rsaandmgf1") {
+ this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
+ this.mdAlgName,
+ this.pssSaltLen);
+ } else if (this.prvKey instanceof RSAKey &&
+ this.pubkeyAlgName === "rsa") {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex,
+ this.mdAlgName);
+ } else if (this.prvKey instanceof KJUR.crypto.ECDSA) {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+ } else if (this.prvKey instanceof KJUR.crypto.DSA) {
+ this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
+ } else {
+ throw "Signature: unsupported private key alg: " + this.pubkeyAlgName;
+ }
+ return this.hSign;
+ };
+ this.signString = function(str) {
+ this.updateString(str);
+ return this.sign();
+ };
+ this.signHex = function(hex) {
+ this.updateHex(hex);
+ return this.sign();
+ };
+ this.verify = function(hSigVal) {
+ this.sHashHex = this.md.digest();
+ if (typeof this.ecpubhex != "undefined" &&
+ typeof this.eccurvename != "undefined") {
+ var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
+ return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
+ } else if (this.pubKey instanceof RSAKey &&
+ this.pubkeyAlgName === "rsaandmgf1") {
+ return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal,
+ this.mdAlgName,
+ this.pssSaltLen);
+ } else if (this.pubKey instanceof RSAKey &&
+ this.pubkeyAlgName === "rsa") {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else if (KJUR.crypto.ECDSA !== undefined &&
+ this.pubKey instanceof KJUR.crypto.ECDSA) {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else if (KJUR.crypto.DSA !== undefined &&
+ this.pubKey instanceof KJUR.crypto.DSA) {
+ return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
+ } else {
+ throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
+ }
+ };
+ }
+ };
+
+ /**
+ * Initialize this object for signing or verifying depends on key
+ * @name init
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object
+ * @param {String} pass (OPTION) passcode for encrypted private key
+ * @since crypto 1.1.3
+ * @description
+ * This method is very useful initialize method for Signature class since
+ * you just specify key then this method will automatically initialize it
+ * using {@link KEYUTIL.getKey} method.
+ * As for 'key', following argument type are supported:
+ * signing
+ *
+ * - PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"
+ * - PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"
+ * - PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"
+ * - PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"
+ * - RSAKey object of private key
+ * - KJUR.crypto.ECDSA object of private key
+ * - KJUR.crypto.DSA object of private key
+ *
+ * verification
+ *
+ * - PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"
+ * - PEM formatted X.509 certificate with RSA/EC/DSA public key concluding
+ * "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".
+ * - RSAKey object of public key
+ * - KJUR.crypto.ECDSA object of public key
+ * - KJUR.crypto.DSA object of public key
+ *
+ * @example
+ * sig.init(sCertPEM)
+ */
+ this.init = function(key, pass) {
+ throw "init(key, pass) not supported for this alg:prov=" +
+ this.algProvName;
+ };
+
+ /**
+ * Updates the data to be signed or verified by a string
+ * @name updateString
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} str string to use for the update
+ * @description
+ * @example
+ * sig.updateString('aaa')
+ */
+ this.updateString = function(str) {
+ throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * Updates the data to be signed or verified by a hexadecimal string
+ * @name updateHex
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} hex hexadecimal string to use for the update
+ * @description
+ * @example
+ * sig.updateHex('1f2f3f')
+ */
+ this.updateHex = function(hex) {
+ throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * Returns the signature bytes of all data updates as a hexadecimal string
+ * @name sign
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @return the signature bytes as a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.sign()
+ */
+ this.sign = function() {
+ throw "sign() not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
+ * @name signString
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} str string to final update
+ * @return the signature bytes of a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.signString('aaa')
+ */
+ this.signString = function(str) {
+ throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
+ * @name signHex
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} hex hexadecimal string to final update
+ * @return the signature bytes of a hexadecimal string
+ * @description
+ * @example
+ * var hSigValue = sig.signHex('1fdc33')
+ */
+ this.signHex = function(hex) {
+ throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ /**
+ * verifies the passed-in signature.
+ * @name verify
+ * @memberOf KJUR.crypto.Signature#
+ * @function
+ * @param {String} str string to final update
+ * @return {Boolean} true if the signature was verified, otherwise false
+ * @description
+ * @example
+ * var isValid = sig.verify('1fbcefdca4823a7(snip)')
+ */
+ this.verify = function(hSigVal) {
+ throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
+ };
+
+ this.initParams = params;
+
+ if (params !== undefined) {
+ if (params.alg !== undefined) {
+ this.algName = params.alg;
+ if (params.prov === undefined) {
+ this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
+ } else {
+ this.provName = params.prov;
+ }
+ this.algProvName = this.algName + ":" + this.provName;
+ this.setAlgAndProvider(this.algName, this.provName);
+ this._setAlgNames();
+ }
+
+ if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen'];
+
+ if (params.prvkeypem !== undefined) {
+ if (params.prvkeypas !== undefined) {
+ throw "both prvkeypem and prvkeypas parameters not supported";
+ } else {
+ try {
+ var prvKey = KEYUTIL.getKey(params.prvkeypem);
+ this.init(prvKey);
+ } catch (ex) {
+ throw "fatal error to load pem private key: " + ex;
+ }
+ }
+ }
+ }
+};
+
+// ====== Cipher class ============================================================
+/**
+ * Cipher class to encrypt and decrypt data
+ * @name KJUR.crypto.Cipher
+ * @class Cipher class to encrypt and decrypt data
+ * @param {Array} params parameters for constructor
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * Here is supported canonicalized cipher algorithm names and its standard names:
+ *
+ * - RSA - RSA/ECB/PKCS1Padding (default for RSAKey)
+ * - RSAOAEP - RSA/ECB/OAEPWithSHA-1AndMGF1Padding
+ * - RSAOAEP224 - RSA/ECB/OAEPWithSHA-224AndMGF1Padding(*)
+ * - RSAOAEP256 - RSA/ECB/OAEPWithSHA-256AndMGF1Padding
+ * - RSAOAEP384 - RSA/ECB/OAEPWithSHA-384AndMGF1Padding(*)
+ * - RSAOAEP512 - RSA/ECB/OAEPWithSHA-512AndMGF1Padding(*)
+ *
+ * NOTE: (*) is not supported in Java JCE.
+ * Currently this class supports only RSA encryption and decryption.
+ * However it is planning to implement also symmetric ciphers near in the future.
+ * @example
+ */
+KJUR.crypto.Cipher = function(params) {
+};
+
+/**
+ * encrypt raw string by specified key and algorithm
+ * @name encrypt
+ * @memberOf KJUR.crypto.Cipher
+ * @function
+ * @param {String} s input string to encrypt
+ * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key
+ * @param {String} algName short/long algorithm name for encryption/decryption
+ * @return {String} hexadecimal encrypted string
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * This static method encrypts raw string with specified key and algorithm.
+ * @example
+ * KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj) → "1abc2d..."
+ * KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj, "RSAOAEP") → "23ab02..."
+ */
+KJUR.crypto.Cipher.encrypt = function(s, keyObj, algName) {
+ if (keyObj instanceof RSAKey && keyObj.isPublic) {
+ var algName2 = KJUR.crypto.Cipher.getAlgByKeyAndName(keyObj, algName);
+ if (algName2 === "RSA") return keyObj.encrypt(s);
+ if (algName2 === "RSAOAEP") return keyObj.encryptOAEP(s, "sha1");
+
+ var a = algName2.match(/^RSAOAEP(\d+)$/);
+ if (a !== null) return keyObj.encryptOAEP(s, "sha" + a[1]);
+
+ throw "Cipher.encrypt: unsupported algorithm for RSAKey: " + algName;
+ } else {
+ throw "Cipher.encrypt: unsupported key or algorithm";
+ }
+};
+
+/**
+ * decrypt encrypted hexadecimal string with specified key and algorithm
+ * @name decrypt
+ * @memberOf KJUR.crypto.Cipher
+ * @function
+ * @param {String} hex hexadecial string of encrypted message
+ * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key
+ * @param {String} algName short/long algorithm name for encryption/decryption
+ * @return {String} hexadecimal encrypted string
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * This static method decrypts encrypted hexadecimal string with specified key and algorithm.
+ * @example
+ * KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj) → "1abc2d..."
+ * KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj, "RSAOAEP) → "23ab02..."
+ */
+KJUR.crypto.Cipher.decrypt = function(hex, keyObj, algName) {
+ if (keyObj instanceof RSAKey && keyObj.isPrivate) {
+ var algName2 = KJUR.crypto.Cipher.getAlgByKeyAndName(keyObj, algName);
+ if (algName2 === "RSA") return keyObj.decrypt(hex);
+ if (algName2 === "RSAOAEP") return keyObj.decryptOAEP(hex, "sha1");
+
+ var a = algName2.match(/^RSAOAEP(\d+)$/);
+ if (a !== null) return keyObj.decryptOAEP(hex, "sha" + a[1]);
+
+ throw "Cipher.decrypt: unsupported algorithm for RSAKey: " + algName;
+ } else {
+ throw "Cipher.decrypt: unsupported key or algorithm";
+ }
+};
+
+/**
+ * get canonicalized encrypt/decrypt algorithm name by key and short/long algorithm name
+ * @name getAlgByKeyAndName
+ * @memberOf KJUR.crypto.Cipher
+ * @function
+ * @param {Object} keyObj RSAKey object or hexadecimal string of symmetric cipher key
+ * @param {String} algName short/long algorithm name for encryption/decryption
+ * @return {String} canonicalized algorithm name for encryption/decryption
+ * @since jsrsasign 6.2.0 crypto 1.1.10
+ * @description
+ * Here is supported canonicalized cipher algorithm names and its standard names:
+ *
+ * - RSA - RSA/ECB/PKCS1Padding (default for RSAKey)
+ * - RSAOAEP - RSA/ECB/OAEPWithSHA-1AndMGF1Padding
+ * - RSAOAEP224 - RSA/ECB/OAEPWithSHA-224AndMGF1Padding(*)
+ * - RSAOAEP256 - RSA/ECB/OAEPWithSHA-256AndMGF1Padding
+ * - RSAOAEP384 - RSA/ECB/OAEPWithSHA-384AndMGF1Padding(*)
+ * - RSAOAEP512 - RSA/ECB/OAEPWithSHA-512AndMGF1Padding(*)
+ *
+ * NOTE: (*) is not supported in Java JCE.
+ * @example
+ * KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey) → "RSA"
+ * KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey, "RSAOAEP") → "RSAOAEP"
+ */
+KJUR.crypto.Cipher.getAlgByKeyAndName = function(keyObj, algName) {
+ if (keyObj instanceof RSAKey) {
+ if (":RSA:RSAOAEP:RSAOAEP224:RSAOAEP256:RSAOAEP384:RSAOAEP512:".indexOf(algName) != -1)
+ return algName;
+ if (algName === null || algName === undefined) return "RSA";
+ throw "getAlgByKeyAndName: not supported algorithm name for RSAKey: " + algName;
+ }
+ throw "getAlgByKeyAndName: not supported algorithm name: " + algName;
+}
+
+// ====== Other Utility class =====================================================
+
+/**
+ * static object for cryptographic function utilities
+ * @name KJUR.crypto.OID
+ * @class static object for cryptography related OIDs
+ * @property {Array} oidhex2name key value of hexadecimal OID and its name
+ * (ex. '2a8648ce3d030107' and 'secp256r1')
+ * @since crypto 1.1.3
+ * @description
+ */
+KJUR.crypto.OID = new function() {
+ this.oidhex2name = {
+ '2a864886f70d010101': 'rsaEncryption',
+ '2a8648ce3d0201': 'ecPublicKey',
+ '2a8648ce380401': 'dsa',
+ '2a8648ce3d030107': 'secp256r1',
+ '2b8104001f': 'secp192k1',
+ '2b81040021': 'secp224r1',
+ '2b8104000a': 'secp256k1',
+ '2b81040023': 'secp521r1',
+ '2b81040022': 'secp384r1',
+ '2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3
+ '608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1
+ '608648016503040302': 'SHA256withDSA', // 2.16.840.1.101.3.4.3.2
+ };
+};
diff --git a/source/cryptojs-312-core-fix.js b/source/cryptojs-312-core-fix.js
new file mode 100644
index 0000000..4e67688
--- /dev/null
+++ b/source/cryptojs-312-core-fix.js
@@ -0,0 +1,711 @@
+/*! CryptoJS v3.1.2 core-fix.js
+ * code.google.com/p/crypto-js
+ * (c) 2009-2013 by Jeff Mott. All rights reserved.
+ * code.google.com/p/crypto-js/wiki/License
+ * THIS IS FIX of 'core.js' to fix Hmac issue.
+ * https://code.google.com/p/crypto-js/issues/detail?id=84
+ * https://crypto-js.googlecode.com/svn-history/r667/branches/3.x/src/core.js
+ */
+/**
+ * CryptoJS core components.
+ */
+var CryptoJS = CryptoJS || (function (Math, undefined) {
+ /**
+ * CryptoJS namespace.
+ */
+ var C = {};
+
+ /**
+ * Library namespace.
+ */
+ var C_lib = C.lib = {};
+
+ /**
+ * Base object for prototypal inheritance.
+ */
+ var Base = C_lib.Base = (function () {
+ function F() {}
+
+ return {
+ /**
+ * Creates a new object that inherits from this object.
+ *
+ * @param {Object} overrides Properties to copy into the new object.
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * field: 'value',
+ *
+ * method: function () {
+ * }
+ * });
+ */
+ extend: function (overrides) {
+ // Spawn
+ F.prototype = this;
+ var subtype = new F();
+
+ // Augment
+ if (overrides) {
+ subtype.mixIn(overrides);
+ }
+
+ // Create default initializer
+ if (!subtype.hasOwnProperty('init')) {
+ subtype.init = function () {
+ subtype.$super.init.apply(this, arguments);
+ };
+ }
+
+ // Initializer's prototype is the subtype object
+ subtype.init.prototype = subtype;
+
+ // Reference supertype
+ subtype.$super = this;
+
+ return subtype;
+ },
+
+ /**
+ * Extends this object and runs the init method.
+ * Arguments to create() will be passed to init().
+ *
+ * @return {Object} The new object.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var instance = MyType.create();
+ */
+ create: function () {
+ var instance = this.extend();
+ instance.init.apply(instance, arguments);
+
+ return instance;
+ },
+
+ /**
+ * Initializes a newly created object.
+ * Override this method to add some logic when your objects are created.
+ *
+ * @example
+ *
+ * var MyType = CryptoJS.lib.Base.extend({
+ * init: function () {
+ * // ...
+ * }
+ * });
+ */
+ init: function () {
+ },
+
+ /**
+ * Copies properties into this object.
+ *
+ * @param {Object} properties The properties to mix in.
+ *
+ * @example
+ *
+ * MyType.mixIn({
+ * field: 'value'
+ * });
+ */
+ mixIn: function (properties) {
+ for (var propertyName in properties) {
+ if (properties.hasOwnProperty(propertyName)) {
+ this[propertyName] = properties[propertyName];
+ }
+ }
+
+ // IE won't copy toString using the loop above
+ if (properties.hasOwnProperty('toString')) {
+ this.toString = properties.toString;
+ }
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = instance.clone();
+ */
+ clone: function () {
+ return this.init.prototype.extend(this);
+ }
+ };
+ }());
+
+ /**
+ * An array of 32-bit words.
+ *
+ * @property {Array} words The array of 32-bit words.
+ * @property {number} sigBytes The number of significant bytes in this word array.
+ */
+ var WordArray = C_lib.WordArray = Base.extend({
+ /**
+ * Initializes a newly created word array.
+ *
+ * @param {Array} words (Optional) An array of 32-bit words.
+ * @param {number} sigBytes (Optional) The number of significant bytes in the words.
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.create();
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
+ * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
+ */
+ init: function (words, sigBytes) {
+ words = this.words = words || [];
+
+ if (sigBytes != undefined) {
+ this.sigBytes = sigBytes;
+ } else {
+ this.sigBytes = words.length * 4;
+ }
+ },
+
+ /**
+ * Converts this word array to a string.
+ *
+ * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
+ *
+ * @return {string} The stringified word array.
+ *
+ * @example
+ *
+ * var string = wordArray + '';
+ * var string = wordArray.toString();
+ * var string = wordArray.toString(CryptoJS.enc.Utf8);
+ */
+ toString: function (encoder) {
+ return (encoder || Hex).stringify(this);
+ },
+
+ /**
+ * Concatenates a word array to this word array.
+ *
+ * @param {WordArray} wordArray The word array to append.
+ *
+ * @return {WordArray} This word array.
+ *
+ * @example
+ *
+ * wordArray1.concat(wordArray2);
+ */
+ concat: function (wordArray) {
+ // Shortcuts
+ var thisWords = this.words;
+ var thatWords = wordArray.words;
+ var thisSigBytes = this.sigBytes;
+ var thatSigBytes = wordArray.sigBytes;
+
+ // Clamp excess bits
+ this.clamp();
+
+ // Concat
+ if (thisSigBytes % 4) {
+ // Copy one byte at a time
+ for (var i = 0; i < thatSigBytes; i++) {
+ var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
+ }
+ } else {
+ // Copy one word at a time
+ for (var i = 0; i < thatSigBytes; i += 4) {
+ thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
+ }
+ }
+ this.sigBytes += thatSigBytes;
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Removes insignificant bits.
+ *
+ * @example
+ *
+ * wordArray.clamp();
+ */
+ clamp: function () {
+ // Shortcuts
+ var words = this.words;
+ var sigBytes = this.sigBytes;
+
+ // Clamp
+ words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
+ words.length = Math.ceil(sigBytes / 4);
+ },
+
+ /**
+ * Creates a copy of this word array.
+ *
+ * @return {WordArray} The clone.
+ *
+ * @example
+ *
+ * var clone = wordArray.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone.words = this.words.slice(0);
+
+ return clone;
+ },
+
+ /**
+ * Creates a word array filled with random bytes.
+ *
+ * @param {number} nBytes The number of random bytes to generate.
+ *
+ * @return {WordArray} The random word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.lib.WordArray.random(16);
+ */
+ random: function (nBytes) {
+ var words = [];
+ for (var i = 0; i < nBytes; i += 4) {
+ words.push((Math.random() * 0x100000000) | 0);
+ }
+
+ return new WordArray.init(words, nBytes);
+ }
+ });
+
+ /**
+ * Encoder namespace.
+ */
+ var C_enc = C.enc = {};
+
+ /**
+ * Hex encoding strategy.
+ */
+ var Hex = C_enc.Hex = {
+ /**
+ * Converts a word array to a hex string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The hex string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hexString = CryptoJS.enc.Hex.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var hexChars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ hexChars.push((bite >>> 4).toString(16));
+ hexChars.push((bite & 0x0f).toString(16));
+ }
+
+ return hexChars.join('');
+ },
+
+ /**
+ * Converts a hex string to a word array.
+ *
+ * @param {string} hexStr The hex string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Hex.parse(hexString);
+ */
+ parse: function (hexStr) {
+ // Shortcut
+ var hexStrLength = hexStr.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < hexStrLength; i += 2) {
+ words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
+ }
+
+ return new WordArray.init(words, hexStrLength / 2);
+ }
+ };
+
+ /**
+ * Latin1 encoding strategy.
+ */
+ var Latin1 = C_enc.Latin1 = {
+ /**
+ * Converts a word array to a Latin1 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The Latin1 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ // Shortcuts
+ var words = wordArray.words;
+ var sigBytes = wordArray.sigBytes;
+
+ // Convert
+ var latin1Chars = [];
+ for (var i = 0; i < sigBytes; i++) {
+ var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
+ latin1Chars.push(String.fromCharCode(bite));
+ }
+
+ return latin1Chars.join('');
+ },
+
+ /**
+ * Converts a Latin1 string to a word array.
+ *
+ * @param {string} latin1Str The Latin1 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
+ */
+ parse: function (latin1Str) {
+ // Shortcut
+ var latin1StrLength = latin1Str.length;
+
+ // Convert
+ var words = [];
+ for (var i = 0; i < latin1StrLength; i++) {
+ words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
+ }
+
+ return new WordArray.init(words, latin1StrLength);
+ }
+ };
+
+ /**
+ * UTF-8 encoding strategy.
+ */
+ var Utf8 = C_enc.Utf8 = {
+ /**
+ * Converts a word array to a UTF-8 string.
+ *
+ * @param {WordArray} wordArray The word array.
+ *
+ * @return {string} The UTF-8 string.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
+ */
+ stringify: function (wordArray) {
+ try {
+ return decodeURIComponent(escape(Latin1.stringify(wordArray)));
+ } catch (e) {
+ throw new Error('Malformed UTF-8 data');
+ }
+ },
+
+ /**
+ * Converts a UTF-8 string to a word array.
+ *
+ * @param {string} utf8Str The UTF-8 string.
+ *
+ * @return {WordArray} The word array.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
+ */
+ parse: function (utf8Str) {
+ return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
+ }
+ };
+
+ /**
+ * Abstract buffered block algorithm template.
+ *
+ * The property blockSize must be implemented in a concrete subtype.
+ *
+ * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
+ */
+ var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
+ /**
+ * Resets this block algorithm's data buffer to its initial state.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm.reset();
+ */
+ reset: function () {
+ // Initial values
+ this._data = new WordArray.init();
+ this._nDataBytes = 0;
+ },
+
+ /**
+ * Adds new data to this block algorithm's buffer.
+ *
+ * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
+ *
+ * @example
+ *
+ * bufferedBlockAlgorithm._append('data');
+ * bufferedBlockAlgorithm._append(wordArray);
+ */
+ _append: function (data) {
+ // Convert string to WordArray, else assume WordArray already
+ if (typeof data == 'string') {
+ data = Utf8.parse(data);
+ }
+
+ // Append
+ this._data.concat(data);
+ this._nDataBytes += data.sigBytes;
+ },
+
+ /**
+ * Processes available data blocks.
+ *
+ * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
+ *
+ * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
+ *
+ * @return {WordArray} The processed data.
+ *
+ * @example
+ *
+ * var processedData = bufferedBlockAlgorithm._process();
+ * var processedData = bufferedBlockAlgorithm._process(!!'flush');
+ */
+ _process: function (doFlush) {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+ var dataSigBytes = data.sigBytes;
+ var blockSize = this.blockSize;
+ var blockSizeBytes = blockSize * 4;
+
+ // Count blocks ready
+ var nBlocksReady = dataSigBytes / blockSizeBytes;
+ if (doFlush) {
+ // Round up to include partial blocks
+ nBlocksReady = Math.ceil(nBlocksReady);
+ } else {
+ // Round down to include only full blocks,
+ // less the number of blocks that must remain in the buffer
+ nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
+ }
+
+ // Count words ready
+ var nWordsReady = nBlocksReady * blockSize;
+
+ // Count bytes ready
+ var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
+
+ // Process blocks
+ if (nWordsReady) {
+ for (var offset = 0; offset < nWordsReady; offset += blockSize) {
+ // Perform concrete-algorithm logic
+ this._doProcessBlock(dataWords, offset);
+ }
+
+ // Remove processed words
+ var processedWords = dataWords.splice(0, nWordsReady);
+ data.sigBytes -= nBytesReady;
+ }
+
+ // Return processed words
+ return new WordArray.init(processedWords, nBytesReady);
+ },
+
+ /**
+ * Creates a copy of this object.
+ *
+ * @return {Object} The clone.
+ *
+ * @example
+ *
+ * var clone = bufferedBlockAlgorithm.clone();
+ */
+ clone: function () {
+ var clone = Base.clone.call(this);
+ clone._data = this._data.clone();
+
+ return clone;
+ },
+
+ _minBufferSize: 0
+ });
+
+ /**
+ * Abstract hasher template.
+ *
+ * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
+ */
+ var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
+ /**
+ * Configuration options.
+ */
+ cfg: Base.extend(),
+
+ /**
+ * Initializes a newly created hasher.
+ *
+ * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
+ *
+ * @example
+ *
+ * var hasher = CryptoJS.algo.SHA256.create();
+ */
+ init: function (cfg) {
+ // Apply config defaults
+ this.cfg = this.cfg.extend(cfg);
+
+ // Set initial values
+ this.reset();
+ },
+
+ /**
+ * Resets this hasher to its initial state.
+ *
+ * @example
+ *
+ * hasher.reset();
+ */
+ reset: function () {
+ // Reset data buffer
+ BufferedBlockAlgorithm.reset.call(this);
+
+ // Perform concrete-hasher logic
+ this._doReset();
+ },
+
+ /**
+ * Updates this hasher with a message.
+ *
+ * @param {WordArray|string} messageUpdate The message to append.
+ *
+ * @return {Hasher} This hasher.
+ *
+ * @example
+ *
+ * hasher.update('message');
+ * hasher.update(wordArray);
+ */
+ update: function (messageUpdate) {
+ // Append
+ this._append(messageUpdate);
+
+ // Update the hash
+ this._process();
+
+ // Chainable
+ return this;
+ },
+
+ /**
+ * Finalizes the hash computation.
+ * Note that the finalize operation is effectively a destructive, read-once operation.
+ *
+ * @param {WordArray|string} messageUpdate (Optional) A final message update.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @example
+ *
+ * var hash = hasher.finalize();
+ * var hash = hasher.finalize('message');
+ * var hash = hasher.finalize(wordArray);
+ */
+ finalize: function (messageUpdate) {
+ // Final message update
+ if (messageUpdate) {
+ this._append(messageUpdate);
+ }
+
+ // Perform concrete-hasher logic
+ var hash = this._doFinalize();
+
+ return hash;
+ },
+
+ blockSize: 512/32,
+
+ /**
+ * Creates a shortcut function to a hasher's object interface.
+ *
+ * @param {Hasher} hasher The hasher to create a helper for.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
+ */
+ _createHelper: function (hasher) {
+ return function (message, cfg) {
+ return new hasher.init(cfg).finalize(message);
+ };
+ },
+
+ /**
+ * Creates a shortcut function to the HMAC's object interface.
+ *
+ * @param {Hasher} hasher The hasher to use in this HMAC helper.
+ *
+ * @return {Function} The shortcut function.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
+ */
+ _createHmacHelper: function (hasher) {
+ return function (message, key) {
+ return new C_algo.HMAC.init(hasher, key).finalize(message);
+ };
+ }
+ });
+
+ /**
+ * Algorithm namespace.
+ */
+ var C_algo = C.algo = {};
+
+ return C;
+}(Math));
diff --git a/source/ec.js b/source/ec.js
new file mode 100644
index 0000000..71aedee
--- /dev/null
+++ b/source/ec.js
@@ -0,0 +1,318 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// Basic Javascript Elliptic Curve implementation
+// Ported loosely from BouncyCastle's Java EC code
+// Only Fp curves implemented for now
+
+// Requires jsbn.js and jsbn2.js
+
+// ----------------
+// ECFieldElementFp
+
+// constructor
+function ECFieldElementFp(q,x) {
+ this.x = x;
+ // TODO if(x.compareTo(q) >= 0) error
+ this.q = q;
+}
+
+function feFpEquals(other) {
+ if(other == this) return true;
+ return (this.q.equals(other.q) && this.x.equals(other.x));
+}
+
+function feFpToBigInteger() {
+ return this.x;
+}
+
+function feFpNegate() {
+ return new ECFieldElementFp(this.q, this.x.negate().mod(this.q));
+}
+
+function feFpAdd(b) {
+ return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
+}
+
+function feFpSubtract(b) {
+ return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
+}
+
+function feFpMultiply(b) {
+ return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
+}
+
+function feFpSquare() {
+ return new ECFieldElementFp(this.q, this.x.square().mod(this.q));
+}
+
+function feFpDivide(b) {
+ return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
+}
+
+ECFieldElementFp.prototype.equals = feFpEquals;
+ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger;
+ECFieldElementFp.prototype.negate = feFpNegate;
+ECFieldElementFp.prototype.add = feFpAdd;
+ECFieldElementFp.prototype.subtract = feFpSubtract;
+ECFieldElementFp.prototype.multiply = feFpMultiply;
+ECFieldElementFp.prototype.square = feFpSquare;
+ECFieldElementFp.prototype.divide = feFpDivide;
+
+// ----------------
+// ECPointFp
+
+// constructor
+function ECPointFp(curve,x,y,z) {
+ this.curve = curve;
+ this.x = x;
+ this.y = y;
+ // Projective coordinates: either zinv == null or z * zinv == 1
+ // z and zinv are just BigIntegers, not fieldElements
+ if(z == null) {
+ this.z = BigInteger.ONE;
+ }
+ else {
+ this.z = z;
+ }
+ this.zinv = null;
+ //TODO: compression flag
+}
+
+function pointFpGetX() {
+ if(this.zinv == null) {
+ this.zinv = this.z.modInverse(this.curve.q);
+ }
+ return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+}
+
+function pointFpGetY() {
+ if(this.zinv == null) {
+ this.zinv = this.z.modInverse(this.curve.q);
+ }
+ return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
+}
+
+function pointFpEquals(other) {
+ if(other == this) return true;
+ if(this.isInfinity()) return other.isInfinity();
+ if(other.isInfinity()) return this.isInfinity();
+ var u, v;
+ // u = Y2 * Z1 - Y1 * Z2
+ u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
+ if(!u.equals(BigInteger.ZERO)) return false;
+ // v = X2 * Z1 - X1 * Z2
+ v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
+ return v.equals(BigInteger.ZERO);
+}
+
+function pointFpIsInfinity() {
+ if((this.x == null) && (this.y == null)) return true;
+ return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
+}
+
+function pointFpNegate() {
+ return new ECPointFp(this.curve, this.x, this.y.negate(), this.z);
+}
+
+function pointFpAdd(b) {
+ if(this.isInfinity()) return b;
+ if(b.isInfinity()) return this;
+
+ // u = Y2 * Z1 - Y1 * Z2
+ var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q);
+ // v = X2 * Z1 - X1 * Z2
+ var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q);
+
+ if(BigInteger.ZERO.equals(v)) {
+ if(BigInteger.ZERO.equals(u)) {
+ return this.twice(); // this == b, so double
+ }
+ return this.curve.getInfinity(); // this = -b, so infinity
+ }
+
+ var THREE = new BigInteger("3");
+ var x1 = this.x.toBigInteger();
+ var y1 = this.y.toBigInteger();
+ var x2 = b.x.toBigInteger();
+ var y2 = b.y.toBigInteger();
+
+ var v2 = v.square();
+ var v3 = v2.multiply(v);
+ var x1v2 = x1.multiply(v2);
+ var zu2 = u.square().multiply(this.z);
+
+ // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
+ var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q);
+ // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
+ var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q);
+ // z3 = v^3 * z1 * z2
+ var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q);
+
+ return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+}
+
+function pointFpTwice() {
+ if(this.isInfinity()) return this;
+ if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity();
+
+ // TODO: optimized handling of constants
+ var THREE = new BigInteger("3");
+ var x1 = this.x.toBigInteger();
+ var y1 = this.y.toBigInteger();
+
+ var y1z1 = y1.multiply(this.z);
+ var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q);
+ var a = this.curve.a.toBigInteger();
+
+ // w = 3 * x1^2 + a * z1^2
+ var w = x1.square().multiply(THREE);
+ if(!BigInteger.ZERO.equals(a)) {
+ w = w.add(this.z.square().multiply(a));
+ }
+ w = w.mod(this.curve.q);
+ // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
+ var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q);
+ // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
+ var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q);
+ // z3 = 8 * (y1 * z1)^3
+ var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q);
+
+ return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
+}
+
+// Simple NAF (Non-Adjacent Form) multiplication algorithm
+// TODO: modularize the multiplication algorithm
+function pointFpMultiply(k) {
+ if(this.isInfinity()) return this;
+ if(k.signum() == 0) return this.curve.getInfinity();
+
+ var e = k;
+ var h = e.multiply(new BigInteger("3"));
+
+ var neg = this.negate();
+ var R = this;
+
+ var i;
+ for(i = h.bitLength() - 2; i > 0; --i) {
+ R = R.twice();
+
+ var hBit = h.testBit(i);
+ var eBit = e.testBit(i);
+
+ if (hBit != eBit) {
+ R = R.add(hBit ? this : neg);
+ }
+ }
+
+ return R;
+}
+
+// Compute this*j + x*k (simultaneous multiplication)
+function pointFpMultiplyTwo(j,x,k) {
+ var i;
+ if(j.bitLength() > k.bitLength())
+ i = j.bitLength() - 1;
+ else
+ i = k.bitLength() - 1;
+
+ var R = this.curve.getInfinity();
+ var both = this.add(x);
+ while(i >= 0) {
+ R = R.twice();
+ if(j.testBit(i)) {
+ if(k.testBit(i)) {
+ R = R.add(both);
+ }
+ else {
+ R = R.add(this);
+ }
+ }
+ else {
+ if(k.testBit(i)) {
+ R = R.add(x);
+ }
+ }
+ --i;
+ }
+
+ return R;
+}
+
+ECPointFp.prototype.getX = pointFpGetX;
+ECPointFp.prototype.getY = pointFpGetY;
+ECPointFp.prototype.equals = pointFpEquals;
+ECPointFp.prototype.isInfinity = pointFpIsInfinity;
+ECPointFp.prototype.negate = pointFpNegate;
+ECPointFp.prototype.add = pointFpAdd;
+ECPointFp.prototype.twice = pointFpTwice;
+ECPointFp.prototype.multiply = pointFpMultiply;
+ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo;
+
+// ----------------
+// ECCurveFp
+
+// constructor
+function ECCurveFp(q,a,b) {
+ this.q = q;
+ this.a = this.fromBigInteger(a);
+ this.b = this.fromBigInteger(b);
+ this.infinity = new ECPointFp(this, null, null);
+}
+
+function curveFpGetQ() {
+ return this.q;
+}
+
+function curveFpGetA() {
+ return this.a;
+}
+
+function curveFpGetB() {
+ return this.b;
+}
+
+function curveFpEquals(other) {
+ if(other == this) return true;
+ return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b));
+}
+
+function curveFpGetInfinity() {
+ return this.infinity;
+}
+
+function curveFpFromBigInteger(x) {
+ return new ECFieldElementFp(this.q, x);
+}
+
+// for now, work with hex strings because they're easier in JS
+function curveFpDecodePointHex(s) {
+ switch(parseInt(s.substr(0,2), 16)) { // first byte
+ case 0:
+ return this.infinity;
+ case 2:
+ case 3:
+ // point compression not supported yet
+ return null;
+ case 4:
+ case 6:
+ case 7:
+ var len = (s.length - 2) / 2;
+ var xHex = s.substr(2, len);
+ var yHex = s.substr(len+2, len);
+
+ return new ECPointFp(this,
+ this.fromBigInteger(new BigInteger(xHex, 16)),
+ this.fromBigInteger(new BigInteger(yHex, 16)));
+
+ default: // unsupported
+ return null;
+ }
+}
+
+ECCurveFp.prototype.getQ = curveFpGetQ;
+ECCurveFp.prototype.getA = curveFpGetA;
+ECCurveFp.prototype.getB = curveFpGetB;
+ECCurveFp.prototype.equals = curveFpEquals;
+ECCurveFp.prototype.getInfinity = curveFpGetInfinity;
+ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger;
+ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex;
diff --git a/source/ecdsa-modified-1.0.js b/source/ecdsa-modified-1.0.js
new file mode 100644
index 0000000..c46039d
--- /dev/null
+++ b/source/ecdsa-modified-1.0.js
@@ -0,0 +1,839 @@
+/* ecdsa-modified-1.1.1.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
+ */
+/*
+ * ecdsa-modified.js - modified Bitcoin.ECDSA class
+ *
+ * Copyright (c) 2013-2017 Stefan Thomas (github.com/justmoon)
+ * Kenji Urushima (kenji.urushima@gmail.com)
+ * LICENSE
+ * https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
+ */
+
+/**
+ * @fileOverview
+ * @name ecdsa-modified-1.0.js
+ * @author Stefan Thomas (github.com/justmoon) and Kenji Urushima (kenji.urushima@gmail.com)
+ * @version jsrsasign 7.2.0 ecdsa-modified 1.1.1 (2017-May-12)
+ * @since jsrsasign 4.0
+ * @license MIT License
+ */
+
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
+
+/**
+ * class for EC key generation, ECDSA signing and verifcation
+ * @name KJUR.crypto.ECDSA
+ * @class class for EC key generation, ECDSA signing and verifcation
+ * @description
+ *
+ * CAUTION: Most of the case, you don't need to use this class except
+ * for generating an EC key pair. Please use {@link KJUR.crypto.Signature} class instead.
+ *
+ *
+ * This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
+ * (See {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js})
+ * Currently this class supports following named curves and their aliases.
+ *
+ * - secp256r1, NIST P-256, P-256, prime256v1 (*)
+ * - secp256k1 (*)
+ * - secp384r1, NIST P-384, P-384 (*)
+ *
+ *
+ */
+KJUR.crypto.ECDSA = function(params) {
+ var curveName = "secp256r1"; // curve name default
+ var ecparams = null;
+ var prvKeyHex = null;
+ var pubKeyHex = null;
+
+ var rng = new SecureRandom();
+
+ var P_OVER_FOUR = null;
+
+ this.type = "EC";
+ this.isPrivate = false;
+ this.isPublic = false;
+
+ function implShamirsTrick(P, k, Q, l) {
+ var m = Math.max(k.bitLength(), l.bitLength());
+ var Z = P.add2D(Q);
+ var R = P.curve.getInfinity();
+
+ for (var i = m - 1; i >= 0; --i) {
+ R = R.twice2D();
+
+ R.z = BigInteger.ONE;
+
+ if (k.testBit(i)) {
+ if (l.testBit(i)) {
+ R = R.add2D(Z);
+ } else {
+ R = R.add2D(P);
+ }
+ } else {
+ if (l.testBit(i)) {
+ R = R.add2D(Q);
+ }
+ }
+ }
+
+ return R;
+ };
+
+ //===========================
+ // PUBLIC METHODS
+ //===========================
+ this.getBigRandom = function (limit) {
+ return new BigInteger(limit.bitLength(), rng)
+ .mod(limit.subtract(BigInteger.ONE))
+ .add(BigInteger.ONE)
+ ;
+ };
+
+ this.setNamedCurve = function(curveName) {
+ this.ecparams = KJUR.crypto.ECParameterDB.getByName(curveName);
+ this.prvKeyHex = null;
+ this.pubKeyHex = null;
+ this.curveName = curveName;
+ };
+
+ this.setPrivateKeyHex = function(prvKeyHex) {
+ this.isPrivate = true;
+ this.prvKeyHex = prvKeyHex;
+ };
+
+ this.setPublicKeyHex = function(pubKeyHex) {
+ this.isPublic = true;
+ this.pubKeyHex = pubKeyHex;
+ };
+
+ /**
+ * get X and Y hexadecimal string value of public key
+ * @name getPublicKeyXYHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @return {Array} associative array of x and y value of public key
+ * @since ecdsa-modified 1.0.5 jsrsasign 5.0.14
+ * @example
+ * ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1', 'pub': pubHex});
+ * ec.getPublicKeyXYHex() → { x: '01bacf...', y: 'c3bc22...' }
+ */
+ this.getPublicKeyXYHex = function() {
+ var h = this.pubKeyHex;
+ if (h.substr(0, 2) !== "04")
+ throw "this method supports uncompressed format(04) only";
+
+ var charlen = this.ecparams.keylen / 4;
+ if (h.length !== 2 + charlen * 2)
+ throw "malformed public key hex length";
+
+ var result = {};
+ result.x = h.substr(2, charlen);
+ result.y = h.substr(2 + charlen);
+ return result;
+ };
+
+ /**
+ * get NIST curve short name such as "P-256" or "P-384"
+ * @name getShortNISTPCurveName
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @return {String} short NIST P curve name such as "P-256" or "P-384" if it's NIST P curve otherwise null;
+ * @since ecdsa-modified 1.0.5 jsrsasign 5.0.14
+ * @example
+ * ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1', 'pub': pubHex});
+ * ec.getShortPCurveName() → "P-256";
+ */
+ this.getShortNISTPCurveName = function() {
+ var s = this.curveName;
+ if (s === "secp256r1" || s === "NIST P-256" ||
+ s === "P-256" || s === "prime256v1")
+ return "P-256";
+ if (s === "secp384r1" || s === "NIST P-384" || s === "P-384")
+ return "P-384";
+ return null;
+ };
+
+ /**
+ * generate a EC key pair
+ * @name generateKeyPairHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @return {Array} associative array of hexadecimal string of private and public key
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var keypair = ec.generateKeyPairHex();
+ * var pubhex = keypair.ecpubhex; // hexadecimal string of EC public key
+ * var prvhex = keypair.ecprvhex; // hexadecimal string of EC private key (=d)
+ */
+ this.generateKeyPairHex = function() {
+ var biN = this.ecparams['n'];
+ var biPrv = this.getBigRandom(biN);
+ var epPub = this.ecparams['G'].multiply(biPrv);
+ var biX = epPub.getX().toBigInteger();
+ var biY = epPub.getY().toBigInteger();
+
+ var charlen = this.ecparams['keylen'] / 4;
+ var hPrv = ("0000000000" + biPrv.toString(16)).slice(- charlen);
+ var hX = ("0000000000" + biX.toString(16)).slice(- charlen);
+ var hY = ("0000000000" + biY.toString(16)).slice(- charlen);
+ var hPub = "04" + hX + hY;
+
+ this.setPrivateKeyHex(hPrv);
+ this.setPublicKeyHex(hPub);
+ return {'ecprvhex': hPrv, 'ecpubhex': hPub};
+ };
+
+ this.signWithMessageHash = function(hashHex) {
+ return this.signHex(hashHex, this.prvKeyHex);
+ };
+
+ /**
+ * signing to message hash
+ * @name signHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} hashHex hexadecimal string of hash value of signing message
+ * @param {String} privHex hexadecimal string of EC private key
+ * @return {String} hexadecimal string of ECDSA signature
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sigValue = ec.signHex(hash, prvKey);
+ */
+ this.signHex = function (hashHex, privHex) {
+ var d = new BigInteger(privHex, 16);
+ var n = this.ecparams['n'];
+ var e = new BigInteger(hashHex, 16);
+
+ do {
+ var k = this.getBigRandom(n);
+ var G = this.ecparams['G'];
+ var Q = G.multiply(k);
+ var r = Q.getX().toBigInteger().mod(n);
+ } while (r.compareTo(BigInteger.ZERO) <= 0);
+
+ var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+
+ return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r, s);
+ };
+
+ this.sign = function (hash, priv) {
+ var d = priv;
+ var n = this.ecparams['n'];
+ var e = BigInteger.fromByteArrayUnsigned(hash);
+
+ do {
+ var k = this.getBigRandom(n);
+ var G = this.ecparams['G'];
+ var Q = G.multiply(k);
+ var r = Q.getX().toBigInteger().mod(n);
+ } while (r.compareTo(BigInteger.ZERO) <= 0);
+
+ var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+ return this.serializeSig(r, s);
+ };
+
+ this.verifyWithMessageHash = function(hashHex, sigHex) {
+ return this.verifyHex(hashHex, sigHex, this.pubKeyHex);
+ };
+
+ /**
+ * verifying signature with message hash and public key
+ * @name verifyHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} hashHex hexadecimal string of hash value of signing message
+ * @param {String} sigHex hexadecimal string of signature value
+ * @param {String} pubkeyHex hexadecimal string of public key
+ * @return {Boolean} true if the signature is valid, otherwise false
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var result = ec.verifyHex(msgHashHex, sigHex, pubkeyHex);
+ */
+ this.verifyHex = function(hashHex, sigHex, pubkeyHex) {
+ var r,s;
+
+ var obj = KJUR.crypto.ECDSA.parseSigHex(sigHex);
+ r = obj.r;
+ s = obj.s;
+
+ var Q;
+ Q = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
+ var e = new BigInteger(hashHex, 16);
+
+ return this.verifyRaw(e, r, s, Q);
+ };
+
+ this.verify = function (hash, sig, pubkey) {
+ var r,s;
+ if (Bitcoin.Util.isArray(sig)) {
+ var obj = this.parseSig(sig);
+ r = obj.r;
+ s = obj.s;
+ } else if ("object" === typeof sig && sig.r && sig.s) {
+ r = sig.r;
+ s = sig.s;
+ } else {
+ throw "Invalid value for signature";
+ }
+
+ var Q;
+ if (pubkey instanceof ECPointFp) {
+ Q = pubkey;
+ } else if (Bitcoin.Util.isArray(pubkey)) {
+ Q = ECPointFp.decodeFrom(this.ecparams['curve'], pubkey);
+ } else {
+ throw "Invalid format for pubkey value, must be byte array or ECPointFp";
+ }
+ var e = BigInteger.fromByteArrayUnsigned(hash);
+
+ return this.verifyRaw(e, r, s, Q);
+ };
+
+ this.verifyRaw = function (e, r, s, Q) {
+ var n = this.ecparams['n'];
+ var G = this.ecparams['G'];
+
+ if (r.compareTo(BigInteger.ONE) < 0 ||
+ r.compareTo(n) >= 0)
+ return false;
+
+ if (s.compareTo(BigInteger.ONE) < 0 ||
+ s.compareTo(n) >= 0)
+ return false;
+
+ var c = s.modInverse(n);
+
+ var u1 = e.multiply(c).mod(n);
+ var u2 = r.multiply(c).mod(n);
+
+ // TODO(!!!): For some reason Shamir's trick isn't working with
+ // signed message verification!? Probably an implementation
+ // error!
+ //var point = implShamirsTrick(G, u1, Q, u2);
+ var point = G.multiply(u1).add(Q.multiply(u2));
+
+ var v = point.getX().toBigInteger().mod(n);
+
+ return v.equals(r);
+ };
+
+ /**
+ * Serialize a signature into DER format.
+ *
+ * Takes two BigIntegers representing r and s and returns a byte array.
+ */
+ this.serializeSig = function (r, s) {
+ var rBa = r.toByteArraySigned();
+ var sBa = s.toByteArraySigned();
+
+ var sequence = [];
+ sequence.push(0x02); // INTEGER
+ sequence.push(rBa.length);
+ sequence = sequence.concat(rBa);
+
+ sequence.push(0x02); // INTEGER
+ sequence.push(sBa.length);
+ sequence = sequence.concat(sBa);
+
+ sequence.unshift(sequence.length);
+ sequence.unshift(0x30); // SEQUENCE
+ return sequence;
+ };
+
+ /**
+ * Parses a byte array containing a DER-encoded signature.
+ *
+ * This function will return an object of the form:
+ *
+ * {
+ * r: BigInteger,
+ * s: BigInteger
+ * }
+ */
+ this.parseSig = function (sig) {
+ var cursor;
+ if (sig[0] != 0x30)
+ throw new Error("Signature not a valid DERSequence");
+
+ cursor = 2;
+ if (sig[cursor] != 0x02)
+ throw new Error("First element in signature must be a DERInteger");;
+ var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+ cursor += 2+sig[cursor+1];
+ if (sig[cursor] != 0x02)
+ throw new Error("Second element in signature must be a DERInteger");
+ var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
+
+ cursor += 2+sig[cursor+1];
+
+ //if (cursor != sig.length)
+ // throw new Error("Extra bytes in signature");
+
+ var r = BigInteger.fromByteArrayUnsigned(rBa);
+ var s = BigInteger.fromByteArrayUnsigned(sBa);
+
+ return {r: r, s: s};
+ };
+
+ this.parseSigCompact = function (sig) {
+ if (sig.length !== 65) {
+ throw "Signature has the wrong length";
+ }
+
+ // Signature is prefixed with a type byte storing three bits of
+ // information.
+ var i = sig[0] - 27;
+ if (i < 0 || i > 7) {
+ throw "Invalid signature type";
+ }
+
+ var n = this.ecparams['n'];
+ var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
+ var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
+
+ return {r: r, s: s, i: i};
+ };
+
+ /**
+ * read an ASN.1 hexadecimal string of PKCS#1/5 plain ECC private key
+ * @name readPKCS5PrvKeyHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} h hexadecimal string of PKCS#1/5 ECC private key
+ * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
+ */
+ this.readPKCS5PrvKeyHex = function(h) {
+ var _ASN1HEX = ASN1HEX;
+ var _getName = KJUR.crypto.ECDSA.getName;
+ var _getVbyList = _ASN1HEX.getVbyList;
+
+ if (_ASN1HEX.isASN1HEX(h) === false)
+ throw "not ASN.1 hex string";
+
+ var hCurve, hPrv, hPub;
+ try {
+ hCurve = _getVbyList(h, 0, [2, 0], "06");
+ hPrv = _getVbyList(h, 0, [1], "04");
+ try {
+ hPub = _getVbyList(h, 0, [3, 0], "03").substr(2);
+ } catch(ex) {};
+ } catch(ex) {
+ throw "malformed PKCS#1/5 plain ECC private key";
+ }
+
+ this.curveName = _getName(hCurve);
+ if (this.curveName === undefined) throw "unsupported curve name";
+
+ this.setNamedCurve(this.curveName);
+ this.setPublicKeyHex(hPub);
+ this.setPrivateKeyHex(hPrv);
+ this.isPublic = false;
+ };
+
+ /**
+ * read an ASN.1 hexadecimal string of PKCS#8 plain ECC private key
+ * @name readPKCS8PrvKeyHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} h hexadecimal string of PKCS#8 ECC private key
+ * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
+ */
+ this.readPKCS8PrvKeyHex = function(h) {
+ var _ASN1HEX = ASN1HEX;
+ var _getName = KJUR.crypto.ECDSA.getName;
+ var _getVbyList = _ASN1HEX.getVbyList;
+
+ if (_ASN1HEX.isASN1HEX(h) === false)
+ throw "not ASN.1 hex string";
+
+ var hECOID, hCurve, hPrv, hPub;
+ try {
+ hECOID = _getVbyList(h, 0, [1, 0], "06");
+ hCurve = _getVbyList(h, 0, [1, 1], "06");
+ hPrv = _getVbyList(h, 0, [2, 0, 1], "04");
+ try {
+ hPub = _getVbyList(h, 0, [2, 0, 2, 0], "03").substr(2);
+ } catch(ex) {};
+ } catch(ex) {
+ throw "malformed PKCS#8 plain ECC private key";
+ }
+
+ this.curveName = _getName(hCurve);
+ if (this.curveName === undefined) throw "unsupported curve name";
+
+ this.setNamedCurve(this.curveName);
+ this.setPublicKeyHex(hPub);
+ this.setPrivateKeyHex(hPrv);
+ this.isPublic = false;
+ };
+
+ /**
+ * read an ASN.1 hexadecimal string of PKCS#8 ECC public key
+ * @name readPKCS8PubKeyHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} h hexadecimal string of PKCS#8 ECC public key
+ * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
+ */
+ this.readPKCS8PubKeyHex = function(h) {
+ var _ASN1HEX = ASN1HEX;
+ var _getName = KJUR.crypto.ECDSA.getName;
+ var _getVbyList = _ASN1HEX.getVbyList;
+
+ if (_ASN1HEX.isASN1HEX(h) === false)
+ throw "not ASN.1 hex string";
+
+ var hECOID, hCurve, hPub;
+ try {
+ hECOID = _getVbyList(h, 0, [0, 0], "06");
+ hCurve = _getVbyList(h, 0, [0, 1], "06");
+ hPub = _getVbyList(h, 0, [1], "03").substr(2);
+ } catch(ex) {
+ throw "malformed PKCS#8 ECC public key";
+ }
+
+ this.curveName = _getName(hCurve);
+ if (this.curveName === null) throw "unsupported curve name";
+
+ this.setNamedCurve(this.curveName);
+ this.setPublicKeyHex(hPub);
+ };
+
+ /**
+ * read an ASN.1 hexadecimal string of X.509 ECC public key certificate
+ * @name readCertPubKeyHex
+ * @memberOf KJUR.crypto.ECDSA#
+ * @function
+ * @param {String} h hexadecimal string of X.509 ECC public key certificate
+ * @param {Integer} nthPKI nth index of publicKeyInfo. (DEFAULT: 6 for X509v3)
+ * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
+ */
+ this.readCertPubKeyHex = function(h, nthPKI) {
+ if (nthPKI !== 5) nthPKI = 6;
+ var _ASN1HEX = ASN1HEX;
+ var _getName = KJUR.crypto.ECDSA.getName;
+ var _getVbyList = _ASN1HEX.getVbyList;
+
+ if (_ASN1HEX.isASN1HEX(h) === false)
+ throw "not ASN.1 hex string";
+
+ var hCurve, hPub;
+ try {
+ hCurve = _getVbyList(h, 0, [0, nthPKI, 0, 1], "06");
+ hPub = _getVbyList(h, 0, [0, nthPKI, 1], "03").substr(2);
+ } catch(ex) {
+ throw "malformed X.509 certificate ECC public key";
+ }
+
+ this.curveName = _getName(hCurve);
+ if (this.curveName === null) throw "unsupported curve name";
+
+ this.setNamedCurve(this.curveName);
+ this.setPublicKeyHex(hPub);
+ };
+
+ /*
+ * Recover a public key from a signature.
+ *
+ * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
+ * Key Recovery Operation".
+ *
+ * http://www.secg.org/download/aid-780/sec1-v2.pdf
+ */
+ /*
+ recoverPubKey: function (r, s, hash, i) {
+ // The recovery parameter i has two bits.
+ i = i & 3;
+
+ // The less significant bit specifies whether the y coordinate
+ // of the compressed point is even or not.
+ var isYEven = i & 1;
+
+ // The more significant bit specifies whether we should use the
+ // first or second candidate key.
+ var isSecondKey = i >> 1;
+
+ var n = this.ecparams['n'];
+ var G = this.ecparams['G'];
+ var curve = this.ecparams['curve'];
+ var p = curve.getQ();
+ var a = curve.getA().toBigInteger();
+ var b = curve.getB().toBigInteger();
+
+ // We precalculate (p + 1) / 4 where p is if the field order
+ if (!P_OVER_FOUR) {
+ P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
+ }
+
+ // 1.1 Compute x
+ var x = isSecondKey ? r.add(n) : r;
+
+ // 1.3 Convert x to point
+ var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
+ var beta = alpha.modPow(P_OVER_FOUR, p);
+
+ var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
+ // If beta is even, but y isn't or vice versa, then convert it,
+ // otherwise we're done and y == beta.
+ var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
+
+ // 1.4 Check that nR is at infinity
+ var R = new ECPointFp(curve,
+ curve.fromBigInteger(x),
+ curve.fromBigInteger(y));
+ R.validate();
+
+ // 1.5 Compute e from M
+ var e = BigInteger.fromByteArrayUnsigned(hash);
+ var eNeg = BigInteger.ZERO.subtract(e).mod(n);
+
+ // 1.6 Compute Q = r^-1 (sR - eG)
+ var rInv = r.modInverse(n);
+ var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
+
+ Q.validate();
+ if (!this.verifyRaw(e, r, s, Q)) {
+ throw "Pubkey recovery unsuccessful";
+ }
+
+ var pubKey = new Bitcoin.ECKey();
+ pubKey.pub = Q;
+ return pubKey;
+ },
+ */
+
+ /*
+ * Calculate pubkey extraction parameter.
+ *
+ * When extracting a pubkey from a signature, we have to
+ * distinguish four different cases. Rather than putting this
+ * burden on the verifier, Bitcoin includes a 2-bit value with the
+ * signature.
+ *
+ * This function simply tries all four cases and returns the value
+ * that resulted in a successful pubkey recovery.
+ */
+ /*
+ calcPubkeyRecoveryParam: function (address, r, s, hash) {
+ for (var i = 0; i < 4; i++) {
+ try {
+ var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
+ if (pubkey.getBitcoinAddress().toString() == address) {
+ return i;
+ }
+ } catch (e) {}
+ }
+ throw "Unable to find valid recovery factor";
+ }
+ */
+
+ if (params !== undefined) {
+ if (params['curve'] !== undefined) {
+ this.curveName = params['curve'];
+ }
+ }
+ if (this.curveName === undefined) this.curveName = curveName;
+ this.setNamedCurve(this.curveName);
+ if (params !== undefined) {
+ if (params.prv !== undefined) this.setPrivateKeyHex(params.prv);
+ if (params.pub !== undefined) this.setPublicKeyHex(params.pub);
+ }
+};
+
+/**
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHex
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s of BigInteger
+ * @since ecdsa-modified 1.0.1
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHex('30...');
+ * var biR = sig.r; // BigInteger object for 'r' field of signature.
+ * var biS = sig.s; // BigInteger object for 's' field of signature.
+ */
+KJUR.crypto.ECDSA.parseSigHex = function(sigHex) {
+ var p = KJUR.crypto.ECDSA.parseSigHexInHexRS(sigHex);
+ var biR = new BigInteger(p.r, 16);
+ var biS = new BigInteger(p.s, 16);
+
+ return {'r': biR, 's': biS};
+};
+
+/**
+ * parse ASN.1 DER encoded ECDSA signature
+ * @name parseSigHexInHexRS
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} sigHex hexadecimal string of ECDSA signature value
+ * @return {Array} associative array of signature field r and s in hexadecimal
+ * @since ecdsa-modified 1.0.3
+ * @example
+ * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
+ * var sig = ec.parseSigHexInHexRS('30...');
+ * var hR = sig.r; // hexadecimal string for 'r' field of signature.
+ * var hS = sig.s; // hexadecimal string for 's' field of signature.
+ */
+KJUR.crypto.ECDSA.parseSigHexInHexRS = function(sigHex) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getV = _ASN1HEX.getV;
+
+ // 1. ASN.1 Sequence Check
+ if (sigHex.substr(0, 2) != "30")
+ throw "signature is not a ASN.1 sequence";
+
+ // 2. Items of ASN.1 Sequence Check
+ var a = _getChildIdx(sigHex, 0);
+ if (a.length != 2)
+ throw "number of signature ASN.1 sequence elements seem wrong";
+
+ // 3. Integer check
+ var iTLV1 = a[0];
+ var iTLV2 = a[1];
+ if (sigHex.substr(iTLV1, 2) != "02")
+ throw "1st item of sequene of signature is not ASN.1 integer";
+ if (sigHex.substr(iTLV2, 2) != "02")
+ throw "2nd item of sequene of signature is not ASN.1 integer";
+
+ // 4. getting value
+ var hR = _getV(sigHex, iTLV1);
+ var hS = _getV(sigHex, iTLV2);
+
+ return {'r': hR, 's': hS};
+};
+
+/**
+ * convert hexadecimal ASN.1 encoded signature to concatinated signature
+ * @name asn1SigToConcatSig
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} asn1Hex hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @return {String} r-s concatinated format of ECDSA signature value
+ * @since ecdsa-modified 1.0.3
+ */
+KJUR.crypto.ECDSA.asn1SigToConcatSig = function(asn1Sig) {
+ var pSig = KJUR.crypto.ECDSA.parseSigHexInHexRS(asn1Sig);
+ var hR = pSig.r;
+ var hS = pSig.s;
+
+ // R and S length is assumed multiple of 128bit(32chars in hex).
+ // If leading is "00" and modulo of length is 2(chars) then
+ // leading "00" is for two's complement and will be removed.
+ if (hR.substr(0, 2) == "00" && (hR.length % 32) == 2)
+ hR = hR.substr(2);
+
+ if (hS.substr(0, 2) == "00" && (hS.length % 32) == 2)
+ hS = hS.substr(2);
+
+ // R and S length is assumed multiple of 128bit(32chars in hex).
+ // If missing two chars then it will be padded by "00".
+ if ((hR.length % 32) == 30) hR = "00" + hR;
+ if ((hS.length % 32) == 30) hS = "00" + hS;
+
+ // If R and S length is not still multiple of 128bit(32 chars),
+ // then error
+ if (hR.length % 32 != 0)
+ throw "unknown ECDSA sig r length error";
+ if (hS.length % 32 != 0)
+ throw "unknown ECDSA sig s length error";
+
+ return hR + hS;
+};
+
+/**
+ * convert hexadecimal concatinated signature to ASN.1 encoded signature
+ * @name concatSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} concatSig r-s concatinated format of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
+ */
+KJUR.crypto.ECDSA.concatSigToASN1Sig = function(concatSig) {
+ if ((((concatSig.length / 2) * 8) % (16 * 8)) != 0)
+ throw "unknown ECDSA concatinated r-s sig length error";
+
+ var hR = concatSig.substr(0, concatSig.length / 2);
+ var hS = concatSig.substr(concatSig.length / 2);
+ return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(hR, hS);
+};
+
+/**
+ * convert hexadecimal R and S value of signature to ASN.1 encoded signature
+ * @name hexRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} hR hexadecimal string of R field of ECDSA signature value
+ * @param {String} hS hexadecimal string of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
+ */
+KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function(hR, hS) {
+ var biR = new BigInteger(hR, 16);
+ var biS = new BigInteger(hS, 16);
+ return KJUR.crypto.ECDSA.biRSSigToASN1Sig(biR, biS);
+};
+
+/**
+ * convert R and S BigInteger object of signature to ASN.1 encoded signature
+ * @name biRSSigToASN1Sig
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {BigInteger} biR BigInteger object of R field of ECDSA signature value
+ * @param {BigInteger} biS BIgInteger object of S field of ECDSA signature value
+ * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
+ * @since ecdsa-modified 1.0.3
+ */
+KJUR.crypto.ECDSA.biRSSigToASN1Sig = function(biR, biS) {
+ var _KJUR_asn1 = KJUR.asn1;
+ var derR = new _KJUR_asn1.DERInteger({'bigint': biR});
+ var derS = new _KJUR_asn1.DERInteger({'bigint': biS});
+ var derSeq = new _KJUR_asn1.DERSequence({'array': [derR, derS]});
+ return derSeq.getEncodedHex();
+};
+
+/**
+ * static method to get normalized EC curve name from curve name or hexadecimal OID value
+ * @name getName
+ * @memberOf KJUR.crypto.ECDSA
+ * @function
+ * @static
+ * @param {String} s curve name (ex. P-256) or hexadecimal OID value (ex. 2a86...)
+ * @return {String} normalized EC curve name (ex. secp256r1)
+ * @since jsrsasign 7.1.0 ecdsa-modified 1.1.0
+ * @description
+ * This static method returns normalized EC curve name
+ * which is supported in jsrsasign
+ * from curve name or hexadecimal OID value.
+ * When curve is not supported in jsrsasign, this method returns null.
+ * Normalized name will be "secp*" in jsrsasign.
+ * @example
+ * KJUR.crypto.ECDSA.getName("2b8104000a") → "secp256k1"
+ * KJUR.crypto.ECDSA.getName("NIST P-256") → "secp256r1"
+ * KJUR.crypto.ECDSA.getName("P-521") → undefined // not supported
+ */
+KJUR.crypto.ECDSA.getName = function(s) {
+ if (s === "2a8648ce3d030107") return "secp256r1"; // 1.2.840.10045.3.1.7
+ if (s === "2b8104000a") return "secp256k1"; // 1.3.132.0.10
+ if (s === "2b81040022") return "secp384r1"; // 1.3.132.0.34
+ if ("|secp256r1|NIST P-256|P-256|prime256v1|".indexOf(s) !== -1) return "secp256r1";
+ if ("|secp256k1|".indexOf(s) !== -1) return "secp256k1";
+ if ("|secp384r1|NIST P-384|P-384|".indexOf(s) !== -1) return "secp384r1";
+ return null;
+};
+
diff --git a/source/ecparam-1.0.js b/source/ecparam-1.0.js
new file mode 100644
index 0000000..9626c3d
--- /dev/null
+++ b/source/ecparam-1.0.js
@@ -0,0 +1,248 @@
+/* ecparam-1.0.0.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * ecparam.js - Elliptic Curve Cryptography Curve Parameter Definition class
+ *
+ * Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * https://kjur.github.io/jsrsasign/license
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+
+/**
+ * @fileOverview
+ * @name ecparam-1.1.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version 1.0.0 (2013-Jul-17)
+ * @since jsrsasign 4.0
+ * @license MIT License
+ */
+
+if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
+if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
+
+/**
+ * static object for elliptic curve names and parameters
+ * @name KJUR.crypto.ECParameterDB
+ * @class static object for elliptic curve names and parameters
+ * @description
+ * This class provides parameters for named elliptic curves.
+ * Currently it supoprts following curve names and aliases however
+ * the name marked (*) are available for {@link KJUR.crypto.ECDSA} and
+ * {@link KJUR.crypto.Signature} classes.
+ *
+ * - secp128r1
+ * - secp160r1
+ * - secp160k1
+ * - secp192r1
+ * - secp192k1
+ * - secp224r1
+ * - secp256r1, NIST P-256, P-256, prime256v1 (*)
+ * - secp256k1 (*)
+ * - secp384r1, NIST P-384, P-384 (*)
+ * - secp521r1, NIST P-521, P-521
+ *
+ * You can register new curves by using 'register' method.
+ */
+KJUR.crypto.ECParameterDB = new function() {
+ var db = {};
+ var aliasDB = {};
+
+ function hex2bi(hex) {
+ return new BigInteger(hex, 16);
+ }
+
+ /**
+ * get curve inforamtion associative array for curve name or alias
+ * @name getByName
+ * @memberOf KJUR.crypto.ECParameterDB
+ * @function
+ * @param {String} nameOrAlias curve name or alias name
+ * @return {Array} associative array of curve parameters
+ * @example
+ * var param = KJUR.crypto.ECParameterDB.getByName('prime256v1');
+ * var keylen = param['keylen'];
+ * var n = param['n'];
+ */
+ this.getByName = function(nameOrAlias) {
+ var name = nameOrAlias;
+ if (typeof aliasDB[name] != "undefined") {
+ name = aliasDB[nameOrAlias];
+ }
+ if (typeof db[name] != "undefined") {
+ return db[name];
+ }
+ throw "unregistered EC curve name: " + name;
+ };
+
+ /**
+ * register new curve
+ * @name regist
+ * @memberOf KJUR.crypto.ECParameterDB
+ * @function
+ * @param {String} name name of curve
+ * @param {Integer} keylen key length
+ * @param {String} pHex hexadecimal value of p
+ * @param {String} aHex hexadecimal value of a
+ * @param {String} bHex hexadecimal value of b
+ * @param {String} nHex hexadecimal value of n
+ * @param {String} hHex hexadecimal value of h
+ * @param {String} gxHex hexadecimal value of Gx
+ * @param {String} gyHex hexadecimal value of Gy
+ * @param {Array} aliasList array of string for curve names aliases
+ * @param {String} oid Object Identifier for the curve
+ * @param {String} info information string for the curve
+ */
+ this.regist = function(name, keylen, pHex, aHex, bHex, nHex, hHex, gxHex, gyHex, aliasList, oid, info) {
+ db[name] = {};
+ var p = hex2bi(pHex);
+ var a = hex2bi(aHex);
+ var b = hex2bi(bHex);
+ var n = hex2bi(nHex);
+ var h = hex2bi(hHex);
+ var curve = new ECCurveFp(p, a, b);
+ var G = curve.decodePointHex("04" + gxHex + gyHex);
+ db[name]['name'] = name;
+ db[name]['keylen'] = keylen;
+ db[name]['curve'] = curve;
+ db[name]['G'] = G;
+ db[name]['n'] = n;
+ db[name]['h'] = h;
+ db[name]['oid'] = oid;
+ db[name]['info'] = info;
+
+ for (var i = 0; i < aliasList.length; i++) {
+ aliasDB[aliasList[i]] = name;
+ }
+ };
+};
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp128r1", // name / p = 2^128 - 2^97 - 1
+ 128,
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", // p
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", // a
+ "E87579C11079F43DD824993C2CEE5ED3", // b
+ "FFFFFFFE0000000075A30D1B9038A115", // n
+ "1", // h
+ "161FF7528B899B2D0C28607CA52C5B86", // gx
+ "CF5AC8395BAFEB13C02DA292DDED7A83", // gy
+ [], // alias
+ "", // oid (underconstruction)
+ "secp128r1 : SECG curve over a 128 bit prime field"); // info
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp160k1", // name / p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ 160,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", // p
+ "0", // a
+ "7", // b
+ "0100000000000000000001B8FA16DFAB9ACA16B6B3", // n
+ "1", // h
+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", // gx
+ "938CF935318FDCED6BC28286531733C3F03C4FEE", // gy
+ [], // alias
+ "", // oid
+ "secp160k1 : SECG curve over a 160 bit prime field"); // info
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp160r1", // name / p = 2^160 - 2^31 - 1
+ 160,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", // p
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", // a
+ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", // b
+ "0100000000000000000001F4C8F927AED3CA752257", // n
+ "1", // h
+ "4A96B5688EF573284664698968C38BB913CBFC82", // gx
+ "23A628553168947D59DCC912042351377AC5FB32", // gy
+ [], // alias
+ "", // oid
+ "secp160r1 : SECG curve over a 160 bit prime field"); // info
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp192k1", // name / p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ 192,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", // p
+ "0", // a
+ "3", // b
+ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", // n
+ "1", // h
+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", // gx
+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", // gy
+ []); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp192r1", // name / p = 2^192 - 2^64 - 1
+ 192,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", // p
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", // a
+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", // b
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", // n
+ "1", // h
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", // gx
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", // gy
+ []); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp224r1", // name / p = 2^224 - 2^96 + 1
+ 224,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", // p
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", // a
+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", // b
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", // n
+ "1", // h
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", // gx
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", // gy
+ []); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp256k1", // name / p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ 256,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", // p
+ "0", // a
+ "7", // b
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", // n
+ "1", // h
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", // gx
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", // gy
+ []); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp256r1", // name / p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+ 256,
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", // p
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", // a
+ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", // b
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", // n
+ "1", // h
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", // gx
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", // gy
+ ["NIST P-256", "P-256", "prime256v1"]); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp384r1", // name
+ 384,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", // p
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", // a
+ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", // b
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", // n
+ "1", // h
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", // gx
+ "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", // gy
+ ["NIST P-384", "P-384"]); // alias
+
+KJUR.crypto.ECParameterDB.regist(
+ "secp521r1", // name
+ 521,
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // p
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", // a
+ "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", // b
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", // n
+ "1", // h
+ "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", // gx
+ "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", // gy
+ ["NIST P-521", "P-521"]); // alias
+
diff --git a/source/jsbn.js b/source/jsbn.js
new file mode 100644
index 0000000..cc8ed54
--- /dev/null
+++ b/source/jsbn.js
@@ -0,0 +1,561 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// 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<= 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))<>(this.DB-sh));
+ }
+ else
+ this[this.t-1] |= x<= 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)< 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< 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+=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<= 0; --i) {
+ r[i+ds+1] = (this[i]>>cbs)|c;
+ c = (this[i]&bm)<= 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;
+ for(var i = ds+1; i < this.t; ++i) {
+ r[i-ds-1] |= (this[i]&bm)<>bs;
+ }
+ if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= 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<1)?y[ys-2]>>this.F2:0);
+ var d1 = this.FV/yt, d2 = (1<= 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< 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);
diff --git a/source/jsbn2.js b/source/jsbn2.js
new file mode 100644
index 0000000..732ffae
--- /dev/null
+++ b/source/jsbn2.js
@@ -0,0 +1,658 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// 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))<>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< 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+=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<>= 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< 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< 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)
diff --git a/source/keyutil-1.0.js b/source/keyutil-1.0.js
new file mode 100644
index 0000000..99c97d1
--- /dev/null
+++ b/source/keyutil-1.0.js
@@ -0,0 +1,1756 @@
+/* keyutil-1.2.0.js (c) 2013-2017 Kenji Urushima | kjur.github.com/jsrsasign/license
+ */
+/*
+ * keyutil.js - key utility for PKCS#1/5/8 PEM, RSA/DSA/ECDSA key object
+ *
+ * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com)
+ *
+ * This software is licensed under the terms of the MIT License.
+ * https://kjur.github.io/jsrsasign/license
+ *
+ * The above copyright and license notice shall be
+ * included in all copies or substantial portions of the Software.
+ */
+/**
+ * @fileOverview
+ * @name keyutil-1.0.js
+ * @author Kenji Urushima kenji.urushima@gmail.com
+ * @version jsrsasign 8.0.0 keyutil 1.2.0 (2017-Jun-26)
+ * @since jsrsasign 4.1.4
+ * @license MIT License
+ */
+
+/**
+ * @name KEYUTIL
+ * @class class for RSA/ECC/DSA key utility
+ * @description
+ *
+ * {@link KEYUTIL} class is an update of former {@link PKCS5PKEY} class.
+ * {@link KEYUTIL} class has following features:
+ *
+ * - key loading - {@link KEYUTIL.getKey}
+ *
-
+ *
+ * - supports RSAKey and KJUR.crypto.{ECDSA,DSA} key object
+ * - supports private key and public key
+ * - supports encrypted and plain private key
+ * - supports PKCS#1, PKCS#5 and PKCS#8 key
+ * - supports public key in X.509 certificate
+ * - key represented by JSON object
+ *
+ * NOTE1: Encrypted PKCS#8 only supports PBKDF2/HmacSHA1/3DES
+ * NOTE2: Encrypted PKCS#5 supports DES-CBC, DES-EDE3-CBC, AES-{128,192.256}-CBC
+ *
+ * - exporting key - {@link KEYUTIL.getPEM}
+ *
-
+ * {@link KEYUTIL.getPEM} method supports following formats:
+ *
+ * - supports RSA/EC/DSA keys
+ * - PKCS#1 plain RSA/EC/DSA private key
+ * - PKCS#5 encrypted RSA/EC/DSA private key with DES-CBC, DES-EDE3-CBC, AES-{128,192.256}-CBC
+ * - PKCS#8 plain RSA/EC/DSA private key
+ * - PKCS#8 encrypted RSA/EC/DSA private key with PBKDF2_HmacSHA1_3DES
+ *
+ *
+ * - keypair generation - {@link KEYUTIL.generateKeypair}
+ *
+ * - generate key pair of {@link RSAKey} or {@link KJUR.crypto.ECDSA}.
+ * - generate private key and convert it to PKCS#5 encrypted private key.
+ *
+ * NOTE: {@link KJUR.crypto.DSA} is not yet supported.
+ *
+ *
+ * @example
+ * // 1. loading PEM private key
+ * var key = KEYUTIL.getKey(pemPKCS1PrivateKey);
+ * var key = KEYUTIL.getKey(pemPKCS5EncryptedPrivateKey, "passcode");
+ * var key = KEYUTIL.getKey(pemPKC85PlainPrivateKey);
+ * var key = KEYUTIL.getKey(pemPKC85EncryptedPrivateKey, "passcode");
+ * // 2. loading PEM public key
+ * var key = KEYUTIL.getKey(pemPKCS8PublicKey);
+ * var key = KEYUTIL.getKey(pemX509Certificate);
+ * // 3. exporting private key
+ * var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS1PRV");
+ * var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS5PRV", "passcode"); // DES-EDE3-CBC by default
+ * var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS5PRV", "passcode", "DES-CBC");
+ * var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS8PRV");
+ * var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS8PRV", "passcode");
+ * // 4. exporting public key
+ * var pem = KEYUTIL.getPEM(publicKeyObj);
+ */
+var KEYUTIL = function() {
+ // *****************************************************************
+ // *** PRIVATE PROPERTIES AND METHODS *******************************
+ // *****************************************************************
+ // shared key decryption ------------------------------------------
+ var decryptAES = function(dataHex, keyHex, ivHex) {
+ return decryptGeneral(CryptoJS.AES, dataHex, keyHex, ivHex);
+ };
+
+ var decrypt3DES = function(dataHex, keyHex, ivHex) {
+ return decryptGeneral(CryptoJS.TripleDES, dataHex, keyHex, ivHex);
+ };
+
+ var decryptDES = function(dataHex, keyHex, ivHex) {
+ return decryptGeneral(CryptoJS.DES, dataHex, keyHex, ivHex);
+ };
+
+ var decryptGeneral = function(f, dataHex, keyHex, ivHex) {
+ var data = CryptoJS.enc.Hex.parse(dataHex);
+ var key = CryptoJS.enc.Hex.parse(keyHex);
+ var iv = CryptoJS.enc.Hex.parse(ivHex);
+ var encrypted = {};
+ encrypted.key = key;
+ encrypted.iv = iv;
+ encrypted.ciphertext = data;
+ var decrypted = f.decrypt(encrypted, key, { iv: iv });
+ return CryptoJS.enc.Hex.stringify(decrypted);
+ };
+
+ // shared key decryption ------------------------------------------
+ var encryptAES = function(dataHex, keyHex, ivHex) {
+ return encryptGeneral(CryptoJS.AES, dataHex, keyHex, ivHex);
+ };
+
+ var encrypt3DES = function(dataHex, keyHex, ivHex) {
+ return encryptGeneral(CryptoJS.TripleDES, dataHex, keyHex, ivHex);
+ };
+
+ var encryptDES = function(dataHex, keyHex, ivHex) {
+ return encryptGeneral(CryptoJS.DES, dataHex, keyHex, ivHex);
+ };
+
+ var encryptGeneral = function(f, dataHex, keyHex, ivHex) {
+ var data = CryptoJS.enc.Hex.parse(dataHex);
+ var key = CryptoJS.enc.Hex.parse(keyHex);
+ var iv = CryptoJS.enc.Hex.parse(ivHex);
+ var encryptedHex = f.encrypt(data, key, { iv: iv });
+ var encryptedWA = CryptoJS.enc.Hex.parse(encryptedHex.toString());
+ var encryptedB64 = CryptoJS.enc.Base64.stringify(encryptedWA);
+ return encryptedB64;
+ };
+
+ // other methods and properties ----------------------------------------
+ var ALGLIST = {
+ 'AES-256-CBC': { 'proc': decryptAES, 'eproc': encryptAES, keylen: 32, ivlen: 16 },
+ 'AES-192-CBC': { 'proc': decryptAES, 'eproc': encryptAES, keylen: 24, ivlen: 16 },
+ 'AES-128-CBC': { 'proc': decryptAES, 'eproc': encryptAES, keylen: 16, ivlen: 16 },
+ 'DES-EDE3-CBC': { 'proc': decrypt3DES, 'eproc': encrypt3DES, keylen: 24, ivlen: 8 },
+ 'DES-CBC': { 'proc': decryptDES, 'eproc': encryptDES, keylen: 8, ivlen: 8 }
+ };
+
+ var getFuncByName = function(algName) {
+ return ALGLIST[algName]['proc'];
+ };
+
+ var _generateIvSaltHex = function(numBytes) {
+ var wa = CryptoJS.lib.WordArray.random(numBytes);
+ var hex = CryptoJS.enc.Hex.stringify(wa);
+ return hex;
+ };
+
+ var _parsePKCS5PEM = function(sPKCS5PEM) {
+ var info = {};
+ var matchResult1 = sPKCS5PEM.match(new RegExp("DEK-Info: ([^,]+),([0-9A-Fa-f]+)", "m"));
+ if (matchResult1) {
+ info.cipher = matchResult1[1];
+ info.ivsalt = matchResult1[2];
+ }
+ var matchResult2 = sPKCS5PEM.match(new RegExp("-----BEGIN ([A-Z]+) PRIVATE KEY-----"));
+ if (matchResult2) {
+ info.type = matchResult2[1];
+ }
+ var i1 = -1;
+ var lenNEWLINE = 0;
+ if (sPKCS5PEM.indexOf("\r\n\r\n") != -1) {
+ i1 = sPKCS5PEM.indexOf("\r\n\r\n");
+ lenNEWLINE = 2;
+ }
+ if (sPKCS5PEM.indexOf("\n\n") != -1) {
+ i1 = sPKCS5PEM.indexOf("\n\n");
+ lenNEWLINE = 1;
+ }
+ var i2 = sPKCS5PEM.indexOf("-----END");
+ if (i1 != -1 && i2 != -1) {
+ var s = sPKCS5PEM.substring(i1 + lenNEWLINE * 2, i2 - lenNEWLINE);
+ s = s.replace(/\s+/g, '');
+ info.data = s;
+ }
+ return info;
+ };
+
+ var _getKeyAndUnusedIvByPasscodeAndIvsalt = function(algName, passcode, ivsaltHex) {
+ //alert("ivsaltHex(2) = " + ivsaltHex);
+ var saltHex = ivsaltHex.substring(0, 16);
+ //alert("salt = " + saltHex);
+
+ var salt = CryptoJS.enc.Hex.parse(saltHex);
+ var data = CryptoJS.enc.Utf8.parse(passcode);
+ //alert("salt = " + salt);
+ //alert("data = " + data);
+
+ var nRequiredBytes = ALGLIST[algName]['keylen'] + ALGLIST[algName]['ivlen'];
+ var hHexValueJoined = '';
+ var hLastValue = null;
+ //alert("nRequiredBytes = " + nRequiredBytes);
+ for (;;) {
+ var h = CryptoJS.algo.MD5.create();
+ if (hLastValue != null) {
+ h.update(hLastValue);
+ }
+ h.update(data);
+ h.update(salt);
+ hLastValue = h.finalize();
+ hHexValueJoined = hHexValueJoined + CryptoJS.enc.Hex.stringify(hLastValue);
+ //alert("joined = " + hHexValueJoined);
+ if (hHexValueJoined.length >= nRequiredBytes * 2) {
+ break;
+ }
+ }
+ var result = {};
+ result.keyhex = hHexValueJoined.substr(0, ALGLIST[algName]['keylen'] * 2);
+ result.ivhex = hHexValueJoined.substr(ALGLIST[algName]['keylen'] * 2, ALGLIST[algName]['ivlen'] * 2);
+ return result;
+ };
+
+ /*
+ * @param {String} privateKeyB64 base64 string of encrypted private key
+ * @param {String} sharedKeyAlgName algorithm name of shared key encryption
+ * @param {String} sharedKeyHex hexadecimal string of shared key to encrypt
+ * @param {String} ivsaltHex hexadecimal string of IV and salt
+ * @param {String} hexadecimal string of decrypted private key
+ */
+ var _decryptKeyB64 = function(privateKeyB64, sharedKeyAlgName, sharedKeyHex, ivsaltHex) {
+ var privateKeyWA = CryptoJS.enc.Base64.parse(privateKeyB64);
+ var privateKeyHex = CryptoJS.enc.Hex.stringify(privateKeyWA);
+ var f = ALGLIST[sharedKeyAlgName]['proc'];
+ var decryptedKeyHex = f(privateKeyHex, sharedKeyHex, ivsaltHex);
+ return decryptedKeyHex;
+ };
+
+ /*
+ * @param {String} privateKeyHex hexadecimal string of private key
+ * @param {String} sharedKeyAlgName algorithm name of shared key encryption
+ * @param {String} sharedKeyHex hexadecimal string of shared key to encrypt
+ * @param {String} ivsaltHex hexadecimal string of IV and salt
+ * @param {String} base64 string of encrypted private key
+ */
+ var _encryptKeyHex = function(privateKeyHex, sharedKeyAlgName, sharedKeyHex, ivsaltHex) {
+ var f = ALGLIST[sharedKeyAlgName]['eproc'];
+ var encryptedKeyB64 = f(privateKeyHex, sharedKeyHex, ivsaltHex);
+ return encryptedKeyB64;
+ };
+
+ // *****************************************************************
+ // *** PUBLIC PROPERTIES AND METHODS *******************************
+ // *****************************************************************
+ return {
+ // -- UTILITY METHODS ------------------------------------------------------------
+ /**
+ * decrypt private key by shared key
+ * @name version
+ * @memberOf KEYUTIL
+ * @property {String} version
+ * @description version string of KEYUTIL class
+ */
+ version: "1.0.0",
+
+ /**
+ * parse PEM formatted passcode protected PKCS#5 private key
+ * @name parsePKCS5PEM
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} sEncryptedPEM PEM formatted protected passcode protected PKCS#5 private key
+ * @return {Hash} hash of key information
+ * @description
+ * Resulted hash has following attributes.
+ *
+ * - cipher - symmetric key algorithm name (ex. 'DES-EBE3-CBC', 'AES-256-CBC')
+ * - ivsalt - IV used for decrypt. Its heading 8 bytes will be used for passcode salt.
+ * - type - asymmetric key algorithm name of private key described in PEM header.
+ * - data - base64 encoded encrypted private key.
+ *
+ *
+ */
+ parsePKCS5PEM: function(sPKCS5PEM) {
+ return _parsePKCS5PEM(sPKCS5PEM);
+ },
+
+ /**
+ * the same function as OpenSSL EVP_BytsToKey to generate shared key and IV
+ * @name getKeyAndUnusedIvByPasscodeAndIvsalt
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} algName name of symmetric key algorithm (ex. 'DES-EBE3-CBC')
+ * @param {String} passcode passcode to decrypt private key (ex. 'password')
+ * @param {String} hexadecimal string of IV. heading 8 bytes will be used for passcode salt
+ * @return {Hash} hash of key and unused IV (ex. {keyhex:2fe3..., ivhex:3fad..})
+ */
+ getKeyAndUnusedIvByPasscodeAndIvsalt: function(algName, passcode, ivsaltHex) {
+ return _getKeyAndUnusedIvByPasscodeAndIvsalt(algName, passcode, ivsaltHex);
+ },
+
+ decryptKeyB64: function(privateKeyB64, sharedKeyAlgName, sharedKeyHex, ivsaltHex) {
+ return _decryptKeyB64(privateKeyB64, sharedKeyAlgName, sharedKeyHex, ivsaltHex);
+ },
+
+ /**
+ * decrypt PEM formatted protected PKCS#5 private key with passcode
+ * @name getDecryptedKeyHex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} sEncryptedPEM PEM formatted protected passcode protected PKCS#5 private key
+ * @param {String} passcode passcode to decrypt private key (ex. 'password')
+ * @return {String} hexadecimal string of decrypted RSA priavte key
+ */
+ getDecryptedKeyHex: function(sEncryptedPEM, passcode) {
+ // 1. parse pem
+ var info = _parsePKCS5PEM(sEncryptedPEM);
+ var publicKeyAlgName = info.type;
+ var sharedKeyAlgName = info.cipher;
+ var ivsaltHex = info.ivsalt;
+ var privateKeyB64 = info.data;
+ //alert("ivsaltHex = " + ivsaltHex);
+
+ // 2. generate shared key
+ var sharedKeyInfo = _getKeyAndUnusedIvByPasscodeAndIvsalt(sharedKeyAlgName, passcode, ivsaltHex);
+ var sharedKeyHex = sharedKeyInfo.keyhex;
+ //alert("sharedKeyHex = " + sharedKeyHex);
+
+ // 3. decrypt private key
+ var decryptedKey = _decryptKeyB64(privateKeyB64, sharedKeyAlgName, sharedKeyHex, ivsaltHex);
+ return decryptedKey;
+ },
+
+ /*
+ * get PEM formatted encrypted PKCS#5 private key from hexadecimal string of plain private key
+ * @name getEncryptedPKCS5PEMFromPrvKeyHex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pemHeadAlg algorithm name in the pem header (i.e. RSA,EC or DSA)
+ * @param {String} hPrvKey hexadecimal string of plain private key
+ * @param {String} passcode pass code to protect private key (ex. password)
+ * @param {String} sharedKeyAlgName algorithm name to protect private key (ex. AES-256-CBC)
+ * @param {String} ivsaltHex hexadecimal string of IV and salt
+ * @return {String} string of PEM formatted encrypted PKCS#5 private key
+ * @since pkcs5pkey 1.0.2
+ * @description
+ *
+ * generate PEM formatted encrypted PKCS#5 private key by hexadecimal string encoded
+ * ASN.1 object of plain RSA private key.
+ * Following arguments can be omitted.
+ *
+ * - alg - AES-256-CBC will be used if omitted.
+ * - ivsaltHex - automatically generate IV and salt which length depends on algorithm
+ *
+ * NOTE1: DES-CBC, DES-EDE3-CBC, AES-{128,192.256}-CBC algorithm are supported.
+ * @example
+ * var pem =
+ * KEYUTIL.getEncryptedPKCS5PEMFromPrvKeyHex(plainKeyHex, "password");
+ * var pem2 =
+ * KEYUTIL.getEncryptedPKCS5PEMFromPrvKeyHex(plainKeyHex, "password", "AES-128-CBC");
+ * var pem3 =
+ * KEYUTIL.getEncryptedPKCS5PEMFromPrvKeyHex(plainKeyHex, "password", "AES-128-CBC", "1f3d02...");
+ */
+ getEncryptedPKCS5PEMFromPrvKeyHex: function(pemHeadAlg, hPrvKey, passcode, sharedKeyAlgName, ivsaltHex) {
+ var sPEM = "";
+
+ // 1. set sharedKeyAlgName if undefined (default AES-256-CBC)
+ if (typeof sharedKeyAlgName == "undefined" || sharedKeyAlgName == null) {
+ sharedKeyAlgName = "AES-256-CBC";
+ }
+ if (typeof ALGLIST[sharedKeyAlgName] == "undefined")
+ throw "KEYUTIL unsupported algorithm: " + sharedKeyAlgName;
+
+ // 2. set ivsaltHex if undefined
+ if (typeof ivsaltHex == "undefined" || ivsaltHex == null) {
+ var ivlen = ALGLIST[sharedKeyAlgName]['ivlen'];
+ var randIV = _generateIvSaltHex(ivlen);
+ ivsaltHex = randIV.toUpperCase();
+ }
+
+ // 3. get shared key
+ //alert("ivsalthex=" + ivsaltHex);
+ var sharedKeyInfo = _getKeyAndUnusedIvByPasscodeAndIvsalt(sharedKeyAlgName, passcode, ivsaltHex);
+ var sharedKeyHex = sharedKeyInfo.keyhex;
+ // alert("sharedKeyHex = " + sharedKeyHex);
+
+ // 3. get encrypted Key in Base64
+ var encryptedKeyB64 = _encryptKeyHex(hPrvKey, sharedKeyAlgName, sharedKeyHex, ivsaltHex);
+
+ var pemBody = encryptedKeyB64.replace(/(.{64})/g, "$1\r\n");
+ var sPEM = "-----BEGIN " + pemHeadAlg + " PRIVATE KEY-----\r\n";
+ sPEM += "Proc-Type: 4,ENCRYPTED\r\n";
+ sPEM += "DEK-Info: " + sharedKeyAlgName + "," + ivsaltHex + "\r\n";
+ sPEM += "\r\n";
+ sPEM += pemBody;
+ sPEM += "\r\n-----END " + pemHeadAlg + " PRIVATE KEY-----\r\n";
+
+ return sPEM;
+ },
+
+ // === PKCS8 ===============================================================
+
+ /**
+ * generate PBKDF2 key hexstring with specified passcode and information
+ * @name parseHexOfEncryptedPKCS8
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} passcode passcode to decrypto private key
+ * @return {Array} info associative array of PKCS#8 parameters
+ * @since pkcs5pkey 1.0.3
+ * @description
+ * The associative array which is returned by this method has following properties:
+ *
+ * - info.pbkdf2Salt - hexadecimal string of PBKDF2 salt
+ * - info.pkbdf2Iter - iteration count
+ * - info.ciphertext - hexadecimal string of encrypted private key
+ * - info.encryptionSchemeAlg - encryption algorithm name (currently TripleDES only)
+ * - info.encryptionSchemeIV - initial vector for encryption algorithm
+ *
+ * Currently, this method only supports PKCS#5v2.0 with PBES2/PBDKF2 of HmacSHA1 and TripleDES.
+ *
+ * - keyDerivationFunc = pkcs5PBKDF2 with HmacSHA1
+ * - encryptionScheme = des-EDE3-CBC(i.e. TripleDES
+ *
+ * @example
+ * // to convert plain PKCS#5 private key to encrypted PKCS#8 private
+ * // key with PBKDF2 with TripleDES
+ * % openssl pkcs8 -in plain_p5.pem -topk8 -v2 -des3 -out encrypted_p8.pem
+ */
+ parseHexOfEncryptedPKCS8: function(sHEX) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getV = _ASN1HEX.getV;
+ var info = {};
+
+ var a0 = _getChildIdx(sHEX, 0);
+ if (a0.length != 2)
+ throw "malformed format: SEQUENCE(0).items != 2: " + a0.length;
+
+ // 1. ciphertext
+ info.ciphertext = _getV(sHEX, a0[1]);
+
+ // 2. pkcs5PBES2
+ var a0_0 = _getChildIdx(sHEX, a0[0]);
+ if (a0_0.length != 2)
+ throw "malformed format: SEQUENCE(0.0).items != 2: " + a0_0.length;
+
+ // 2.1 check if pkcs5PBES2(1 2 840 113549 1 5 13)
+ if (_getV(sHEX, a0_0[0]) != "2a864886f70d01050d")
+ throw "this only supports pkcs5PBES2";
+
+ // 2.2 pkcs5PBES2 param
+ var a0_0_1 = _getChildIdx(sHEX, a0_0[1]);
+ if (a0_0.length != 2)
+ throw "malformed format: SEQUENCE(0.0.1).items != 2: " + a0_0_1.length;
+
+ // 2.2.1 encryptionScheme
+ var a0_0_1_1 = _getChildIdx(sHEX, a0_0_1[1]);
+ if (a0_0_1_1.length != 2)
+ throw "malformed format: SEQUENCE(0.0.1.1).items != 2: " + a0_0_1_1.length;
+ if (_getV(sHEX, a0_0_1_1[0]) != "2a864886f70d0307")
+ throw "this only supports TripleDES";
+ info.encryptionSchemeAlg = "TripleDES";
+
+ // 2.2.1.1 IV of encryptionScheme
+ info.encryptionSchemeIV = _getV(sHEX, a0_0_1_1[1]);
+
+ // 2.2.2 keyDerivationFunc
+ var a0_0_1_0 = _getChildIdx(sHEX, a0_0_1[0]);
+ if (a0_0_1_0.length != 2)
+ throw "malformed format: SEQUENCE(0.0.1.0).items != 2: " + a0_0_1_0.length;
+ if (_getV(sHEX, a0_0_1_0[0]) != "2a864886f70d01050c")
+ throw "this only supports pkcs5PBKDF2";
+
+ // 2.2.2.1 pkcs5PBKDF2 param
+ var a0_0_1_0_1 = _getChildIdx(sHEX, a0_0_1_0[1]);
+ if (a0_0_1_0_1.length < 2)
+ throw "malformed format: SEQUENCE(0.0.1.0.1).items < 2: " + a0_0_1_0_1.length;
+
+ // 2.2.2.1.1 PBKDF2 salt
+ info.pbkdf2Salt = _getV(sHEX, a0_0_1_0_1[0]);
+
+ // 2.2.2.1.2 PBKDF2 iter
+ var iterNumHex = _getV(sHEX, a0_0_1_0_1[1]);
+ try {
+ info.pbkdf2Iter = parseInt(iterNumHex, 16);
+ } catch(ex) {
+ throw "malformed format pbkdf2Iter: " + iterNumHex;
+ }
+
+ return info;
+ },
+
+ /**
+ * generate PBKDF2 key hexstring with specified passcode and information
+ * @name getPBKDF2KeyHexFromParam
+ * @memberOf KEYUTIL
+ * @function
+ * @param {Array} info result of {@link parseHexOfEncryptedPKCS8} which has preference of PKCS#8 file
+ * @param {String} passcode passcode to decrypto private key
+ * @return {String} hexadecimal string of PBKDF2 key
+ * @since pkcs5pkey 1.0.3
+ * @description
+ * As for info, this uses following properties:
+ *
+ * - info.pbkdf2Salt - hexadecimal string of PBKDF2 salt
+ * - info.pkbdf2Iter - iteration count
+ *
+ * Currently, this method only supports PKCS#5v2.0 with PBES2/PBDKF2 of HmacSHA1 and TripleDES.
+ *
+ * - keyDerivationFunc = pkcs5PBKDF2 with HmacSHA1
+ * - encryptionScheme = des-EDE3-CBC(i.e. TripleDES
+ *
+ * @example
+ * // to convert plain PKCS#5 private key to encrypted PKCS#8 private
+ * // key with PBKDF2 with TripleDES
+ * % openssl pkcs8 -in plain_p5.pem -topk8 -v2 -des3 -out encrypted_p8.pem
+ */
+ getPBKDF2KeyHexFromParam: function(info, passcode) {
+ var pbkdf2SaltWS = CryptoJS.enc.Hex.parse(info.pbkdf2Salt);
+ var pbkdf2Iter = info.pbkdf2Iter;
+ var pbkdf2KeyWS = CryptoJS.PBKDF2(passcode,
+ pbkdf2SaltWS,
+ { keySize: 192/32, iterations: pbkdf2Iter });
+ var pbkdf2KeyHex = CryptoJS.enc.Hex.stringify(pbkdf2KeyWS);
+ return pbkdf2KeyHex;
+ },
+
+ /*
+ * read PEM formatted encrypted PKCS#8 private key and returns hexadecimal string of plain PKCS#8 private key
+ * @name getPlainPKCS8HexFromEncryptedPKCS8PEM
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcs8PEM PEM formatted encrypted PKCS#8 private key
+ * @param {String} passcode passcode to decrypto private key
+ * @return {String} hexadecimal string of plain PKCS#8 private key
+ * @since pkcs5pkey 1.0.3
+ * @description
+ * Currently, this method only supports PKCS#5v2.0 with PBES2/PBDKF2 of HmacSHA1 and TripleDES.
+ *
+ * - keyDerivationFunc = pkcs5PBKDF2 with HmacSHA1
+ * - encryptionScheme = des-EDE3-CBC(i.e. TripleDES
+ *
+ * @example
+ * // to convert plain PKCS#5 private key to encrypted PKCS#8 private
+ * // key with PBKDF2 with TripleDES
+ * % openssl pkcs8 -in plain_p5.pem -topk8 -v2 -des3 -out encrypted_p8.pem
+ */
+ _getPlainPKCS8HexFromEncryptedPKCS8PEM: function(pkcs8PEM, passcode) {
+ // 1. derHex - PKCS#8 private key encrypted by PBKDF2
+ var derHex = pemtohex(pkcs8PEM, "ENCRYPTED PRIVATE KEY");
+ // 2. info - PKCS#5 PBES info
+ var info = this.parseHexOfEncryptedPKCS8(derHex);
+ // 3. hKey - PBKDF2 key
+ var pbkdf2KeyHex = KEYUTIL.getPBKDF2KeyHexFromParam(info, passcode);
+ // 4. decrypt ciphertext by PBKDF2 key
+ var encrypted = {};
+ encrypted.ciphertext = CryptoJS.enc.Hex.parse(info.ciphertext);
+ var pbkdf2KeyWS = CryptoJS.enc.Hex.parse(pbkdf2KeyHex);
+ var des3IVWS = CryptoJS.enc.Hex.parse(info.encryptionSchemeIV);
+ var decWS = CryptoJS.TripleDES.decrypt(encrypted, pbkdf2KeyWS, { iv: des3IVWS });
+ var decHex = CryptoJS.enc.Hex.stringify(decWS);
+ return decHex;
+ },
+
+ /**
+ * get RSAKey/ECDSA private key object from encrypted PEM PKCS#8 private key
+ * @name getKeyFromEncryptedPKCS8PEM
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcs8PEM string of PEM formatted PKCS#8 private key
+ * @param {String} passcode passcode string to decrypt key
+ * @return {Object} RSAKey or KJUR.crypto.ECDSA private key object
+ * @since pkcs5pkey 1.0.5
+ */
+ getKeyFromEncryptedPKCS8PEM: function(pkcs8PEM, passcode) {
+ var prvKeyHex = this._getPlainPKCS8HexFromEncryptedPKCS8PEM(pkcs8PEM, passcode);
+ var key = this.getKeyFromPlainPrivatePKCS8Hex(prvKeyHex);
+ return key;
+ },
+
+ /**
+ * parse hexadecimal string of plain PKCS#8 private key
+ * @name parsePlainPrivatePKCS8Hex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcs8PrvHex hexadecimal string of PKCS#8 plain private key
+ * @return {Array} associative array of parsed key
+ * @since pkcs5pkey 1.0.5
+ * @description
+ * Resulted associative array has following properties:
+ *
+ * - algoid - hexadecimal string of OID of asymmetric key algorithm
+ * - algparam - hexadecimal string of OID of ECC curve name or null
+ * - keyidx - string starting index of key in pkcs8PrvHex
+ *
+ */
+ parsePlainPrivatePKCS8Hex: function(pkcs8PrvHex) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getV = _ASN1HEX.getV;
+ var result = {};
+ result.algparam = null;
+
+ // 1. sequence
+ if (pkcs8PrvHex.substr(0, 2) != "30")
+ throw "malformed plain PKCS8 private key(code:001)"; // not sequence
+
+ var a1 = _getChildIdx(pkcs8PrvHex, 0);
+ if (a1.length != 3)
+ throw "malformed plain PKCS8 private key(code:002)";
+
+ // 2. AlgID
+ if (pkcs8PrvHex.substr(a1[1], 2) != "30")
+ throw "malformed PKCS8 private key(code:003)"; // AlgId not sequence
+
+ var a2 = _getChildIdx(pkcs8PrvHex, a1[1]);
+ if (a2.length != 2)
+ throw "malformed PKCS8 private key(code:004)"; // AlgId not have two elements
+
+ // 2.1. AlgID OID
+ if (pkcs8PrvHex.substr(a2[0], 2) != "06")
+ throw "malformed PKCS8 private key(code:005)"; // AlgId.oid is not OID
+
+ result.algoid = _getV(pkcs8PrvHex, a2[0]);
+
+ // 2.2. AlgID param
+ if (pkcs8PrvHex.substr(a2[1], 2) == "06") {
+ result.algparam = _getV(pkcs8PrvHex, a2[1]);
+ }
+
+ // 3. Key index
+ if (pkcs8PrvHex.substr(a1[2], 2) != "04")
+ throw "malformed PKCS8 private key(code:006)"; // not octet string
+
+ result.keyidx = _ASN1HEX.getVidx(pkcs8PrvHex, a1[2]);
+
+ return result;
+ },
+
+ /**
+ * get RSAKey/ECDSA private key object from PEM plain PEM PKCS#8 private key
+ * @name getKeyFromPlainPrivatePKCS8PEM
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcs8PEM string of plain PEM formatted PKCS#8 private key
+ * @return {Object} RSAKey or KJUR.crypto.ECDSA private key object
+ * @since pkcs5pkey 1.0.5
+ */
+ getKeyFromPlainPrivatePKCS8PEM: function(prvKeyPEM) {
+ var prvKeyHex = pemtohex(prvKeyPEM, "PRIVATE KEY");
+ var key = this.getKeyFromPlainPrivatePKCS8Hex(prvKeyHex);
+ return key;
+ },
+
+ /**
+ * get RSAKey/DSA/ECDSA private key object from HEX plain PEM PKCS#8 private key
+ * @name getKeyFromPlainPrivatePKCS8Hex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} prvKeyHex hexadecimal string of plain PKCS#8 private key
+ * @return {Object} RSAKey or KJUR.crypto.{DSA,ECDSA} private key object
+ * @since pkcs5pkey 1.0.5
+ */
+ getKeyFromPlainPrivatePKCS8Hex: function(prvKeyHex) {
+ var p8 = this.parsePlainPrivatePKCS8Hex(prvKeyHex);
+ var key;
+
+ if (p8.algoid == "2a864886f70d010101") { // RSA
+ key = new RSAKey();
+ } else if (p8.algoid == "2a8648ce380401") { // DSA
+ key = new KJUR.crypto.DSA();
+ } else if (p8.algoid == "2a8648ce3d0201") { // ECC
+ key = new KJUR.crypto.ECDSA();
+ } else {
+ throw "unsupported private key algorithm";
+ }
+
+ key.readPKCS8PrvKeyHex(prvKeyHex);
+ return key;
+ },
+
+ // === PKCS8 RSA Public Key ================================================
+
+ /*
+ * get RSAKey/DSA/ECDSA public key object from hexadecimal string of PKCS#8 public key
+ * @name _getKeyFromPublicPKCS8Hex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcsPub8Hex hexadecimal string of PKCS#8 public key
+ * @return {Object} RSAKey or KJUR.crypto.{ECDSA,DSA} private key object
+ * @since pkcs5pkey 1.0.5
+ */
+ _getKeyFromPublicPKCS8Hex: function(h) {
+ var key;
+ var hOID = ASN1HEX.getVbyList(h, 0, [0, 0], "06");
+
+ if (hOID === "2a864886f70d010101") { // oid=RSA
+ key = new RSAKey();
+ } else if (hOID === "2a8648ce380401") { // oid=DSA
+ key = new KJUR.crypto.DSA();
+ } else if (hOID === "2a8648ce3d0201") { // oid=ECPUB
+ key = new KJUR.crypto.ECDSA();
+ } else {
+ throw "unsupported PKCS#8 public key hex";
+ }
+ key.readPKCS8PubKeyHex(h);
+ return key;
+ },
+
+ /**
+ * parse hexadecimal string of plain PKCS#8 private key
+ * @name parsePublicRawRSAKeyHex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pubRawRSAHex hexadecimal string of ASN.1 encoded PKCS#8 public key
+ * @return {Array} associative array of parsed key
+ * @since pkcs5pkey 1.0.5
+ * @description
+ * Resulted associative array has following properties:
+ *
+ * - n - hexadecimal string of public key
+ *
- e - hexadecimal string of public exponent
+ *
+ */
+ parsePublicRawRSAKeyHex: function(pubRawRSAHex) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getV = _ASN1HEX.getV;
+ var result = {};
+
+ // 1. Sequence
+ if (pubRawRSAHex.substr(0, 2) != "30")
+ throw "malformed RSA key(code:001)"; // not sequence
+
+ var a1 = _getChildIdx(pubRawRSAHex, 0);
+ if (a1.length != 2)
+ throw "malformed RSA key(code:002)"; // not 2 items in seq
+
+ // 2. public key "N"
+ if (pubRawRSAHex.substr(a1[0], 2) != "02")
+ throw "malformed RSA key(code:003)"; // 1st item is not integer
+
+ result.n = _getV(pubRawRSAHex, a1[0]);
+
+ // 3. public key "E"
+ if (pubRawRSAHex.substr(a1[1], 2) != "02")
+ throw "malformed RSA key(code:004)"; // 2nd item is not integer
+
+ result.e = _getV(pubRawRSAHex, a1[1]);
+
+ return result;
+ },
+
+ /**
+ * parse hexadecimal string of PKCS#8 RSA/EC/DSA public key
+ * @name parsePublicPKCS8Hex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} pkcs8PubHex hexadecimal string of PKCS#8 public key
+ * @return {Hash} hash of key information
+ * @description
+ * Resulted hash has following attributes.
+ *
+ * - algoid - hexadecimal string of OID of asymmetric key algorithm
+ * - algparam - hexadecimal string of OID of ECC curve name, parameter SEQUENCE of DSA or null
+ * - key - hexadecimal string of public key
+ *
+ */
+ parsePublicPKCS8Hex: function(pkcs8PubHex) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getV = _ASN1HEX.getV;
+ var result = {};
+ result.algparam = null;
+
+ // 1. AlgID and Key bit string
+ var a1 = _getChildIdx(pkcs8PubHex, 0);
+ if (a1.length != 2)
+ throw "outer DERSequence shall have 2 elements: " + a1.length;
+
+ // 2. AlgID
+ var idxAlgIdTLV = a1[0];
+ if (pkcs8PubHex.substr(idxAlgIdTLV, 2) != "30")
+ throw "malformed PKCS8 public key(code:001)"; // AlgId not sequence
+
+ var a2 = _getChildIdx(pkcs8PubHex, idxAlgIdTLV);
+ if (a2.length != 2)
+ throw "malformed PKCS8 public key(code:002)"; // AlgId not have two elements
+
+ // 2.1. AlgID OID
+ if (pkcs8PubHex.substr(a2[0], 2) != "06")
+ throw "malformed PKCS8 public key(code:003)"; // AlgId.oid is not OID
+
+ result.algoid = _getV(pkcs8PubHex, a2[0]);
+
+ // 2.2. AlgID param
+ if (pkcs8PubHex.substr(a2[1], 2) == "06") { // OID for EC
+ result.algparam = _getV(pkcs8PubHex, a2[1]);
+ } else if (pkcs8PubHex.substr(a2[1], 2) == "30") { // SEQ for DSA
+ result.algparam = {};
+ result.algparam.p = _ASN1HEX.getVbyList(pkcs8PubHex, a2[1], [0], "02");
+ result.algparam.q = _ASN1HEX.getVbyList(pkcs8PubHex, a2[1], [1], "02");
+ result.algparam.g = _ASN1HEX.getVbyList(pkcs8PubHex, a2[1], [2], "02");
+ }
+
+ // 3. Key
+ if (pkcs8PubHex.substr(a1[1], 2) != "03")
+ throw "malformed PKCS8 public key(code:004)"; // Key is not bit string
+
+ result.key = _getV(pkcs8PubHex, a1[1]).substr(2);
+
+ // 4. return result assoc array
+ return result;
+ },
+ };
+}();
+
+// -- MAJOR PUBLIC METHODS -------------------------------------------------------
+/**
+ * get private or public key object from any arguments
+ * @name getKey
+ * @memberOf KEYUTIL
+ * @function
+ * @static
+ * @param {Object} param parameter to get key object. see description in detail.
+ * @param {String} passcode (OPTION) parameter to get key object. see description in detail.
+ * @param {String} hextype (OPTOIN) parameter to get key object. see description in detail.
+ * @return {Object} {@link RSAKey}, {@link KJUR.crypto.ECDSA} or {@link KJUR.crypto.ECDSA} object
+ * @since keyutil 1.0.0
+ * @description
+ * This method gets private or public key object({@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA})
+ * for RSA, DSA and ECC.
+ * Arguments for this methods depends on a key format you specify.
+ * Following key representations are supported.
+ *
+ * - ECC private/public key object(as is): param=KJUR.crypto.ECDSA
+ * - DSA private/public key object(as is): param=KJUR.crypto.DSA
+ * - RSA private/public key object(as is): param=RSAKey
+ * - ECC private key parameters: param={d: d, curve: curveName}
+ * - RSA private key parameters: param={n: n, e: e, d: d, p: p, q: q, dp: dp, dq: dq, co: co}
+ * NOTE: Each value shall be hexadecimal string of key spec.
+ * - DSA private key parameters: param={p: p, q: q, g: g, y: y, x: x}
+ * NOTE: Each value shall be hexadecimal string of key spec.
+ * - ECC public key parameters: param={xy: xy, curve: curveName}
+ * NOTE: ECC public key 'xy' shall be concatination of "04", x-bytes-hex and y-bytes-hex.
+ * - DSA public key parameters: param={p: p, q: q, g: g, y: y}
+ * NOTE: Each value shall be hexadecimal string of key spec.
+ * - RSA public key parameters: param={n: n, e: e}
+ * - X.509v1/v3 PEM certificate (RSA/DSA/ECC): param=pemString
+ * - PKCS#8 hexadecimal RSA/ECC public key: param=pemString, null, "pkcs8pub"
+ * - PKCS#8 PEM RSA/DSA/ECC public key: param=pemString
+ * - PKCS#5 plain hexadecimal RSA private key: param=hexString, null, "pkcs5prv"
+ * - PKCS#5 plain PEM DSA/RSA private key: param=pemString
+ * - PKCS#8 plain PEM RSA/ECDSA private key: param=pemString
+ * - PKCS#5 encrypted PEM RSA/DSA private key: param=pemString, passcode
+ * - PKCS#8 encrypted PEM RSA/ECDSA private key: param=pemString, passcode
+ *
+ * Please note following limitation on encrypted keys:
+ *
+ * - Encrypted PKCS#8 only supports PBKDF2/HmacSHA1/3DES
+ * - Encrypted PKCS#5 supports DES-CBC, DES-EDE3-CBC, AES-{128,192.256}-CBC
+ * - JWT plain ECC private/public key
+ * - JWT plain RSA public key
+ * - JWT plain RSA private key with P/Q/DP/DQ/COEFF
+ * - JWT plain RSA private key without P/Q/DP/DQ/COEFF (since jsrsasign 5.0.0)
+ *
+ * NOTE1: RFC 7517 JSON Web Key(JWK) support for RSA/ECC private/public key from jsrsasign 4.8.1.
+ * NOTE2: X509v1 support is added since jsrsasign 5.0.11.
+ *
+ * EXAMPLE
+ * @example
+ * // 1. loading private key from PEM string
+ * keyObj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY...");
+ * keyObj = KEYUTIL.getKey("-----BEGIN RSA PRIVATE KEY..., "passcode");
+ * keyObj = KEYUTIL.getKey("-----BEGIN PRIVATE KEY...");
+ * keyObj = KEYUTIL.getKey("-----BEGIN PRIVATE KEY...", "passcode");
+ * // 2. loading public key from PEM string
+ * keyObj = KEYUTIL.getKey("-----BEGIN PUBLIC KEY...");
+ * keyObj = KEYUTIL.getKey("-----BEGIN X509 CERTIFICATE...");
+ * // 3. loading hexadecimal PKCS#5/PKCS#8 key
+ * keyObj = KEYUTIL.getKey("308205c1...", null, "pkcs8pub");
+ * keyObj = KEYUTIL.getKey("3082048b...", null, "pkcs5prv");
+ * // 4. loading JSON Web Key(JWK)
+ * keyObj = KEYUTIL.getKey({kty: "RSA", n: "0vx7...", e: "AQAB"});
+ * keyObj = KEYUTIL.getKey({kty: "EC", crv: "P-256",
+ * x: "MKBC...", y: "4Etl6...", d: "870Mb..."});
+ * // 5. bare hexadecimal key
+ * keyObj = KEYUTIL.getKey({n: "75ab..", e: "010001"});
+ */
+KEYUTIL.getKey = function(param, passcode, hextype) {
+ var _ASN1HEX = ASN1HEX,
+ _getChildIdx = _ASN1HEX.getChildIdx,
+ _getV = _ASN1HEX.getV,
+ _getVbyList = _ASN1HEX.getVbyList,
+ _KJUR_crypto = KJUR.crypto,
+ _KJUR_crypto_ECDSA = _KJUR_crypto.ECDSA,
+ _KJUR_crypto_DSA = _KJUR_crypto.DSA,
+ _RSAKey = RSAKey,
+ _pemtohex = pemtohex,
+ _KEYUTIL = KEYUTIL;
+
+ // 1. by key RSAKey/KJUR.crypto.ECDSA/KJUR.crypto.DSA object
+ if (typeof _RSAKey != 'undefined' && param instanceof _RSAKey)
+ return param;
+ if (typeof _KJUR_crypto_ECDSA != 'undefined' && param instanceof _KJUR_crypto_ECDSA)
+ return param;
+ if (typeof _KJUR_crypto_DSA != 'undefined' && param instanceof _KJUR_crypto_DSA)
+ return param;
+
+ // 2. by parameters of key
+
+ // 2.1. bare ECC
+ // 2.1.1. bare ECC public key by hex values
+ if (param.curve !== undefined &&
+ param.xy !== undefined && param.d === undefined) {
+ return new _KJUR_crypto_ECDSA({pub: param.xy, curve: param.curve});
+ }
+
+ // 2.1.2. bare ECC private key by hex values
+ if (param.curve !== undefined && param.d !== undefined) {
+ return new _KJUR_crypto_ECDSA({prv: param.d, curve: param.curve});
+ }
+
+ // 2.2. bare RSA
+ // 2.2.1. bare RSA public key by hex values
+ if (param.kty === undefined &&
+ param.n !== undefined && param.e !== undefined &&
+ param.d === undefined) {
+ var key = new _RSAKey();
+ key.setPublic(param.n, param.e);
+ return key;
+ }
+
+ // 2.2.2. bare RSA private key with P/Q/DP/DQ/COEFF by hex values
+ if (param.kty === undefined &&
+ param.n !== undefined &&
+ param.e !== undefined &&
+ param.d !== undefined &&
+ param.p !== undefined &&
+ param.q !== undefined &&
+ param.dp !== undefined &&
+ param.dq !== undefined &&
+ param.co !== undefined &&
+ param.qi === undefined) {
+ var key = new _RSAKey();
+ key.setPrivateEx(param.n, param.e, param.d, param.p, param.q,
+ param.dp, param.dq, param.co);
+ return key;
+ }
+
+ // 2.2.3. bare RSA public key without P/Q/DP/DQ/COEFF by hex values
+ if (param.kty === undefined &&
+ param.n !== undefined &&
+ param.e !== undefined &&
+ param.d !== undefined &&
+ param.p === undefined) {
+ var key = new _RSAKey();
+ key.setPrivate(param.n, param.e, param.d);
+ return key;
+ }
+
+ // 2.3. bare DSA
+ // 2.3.1. bare DSA public key by hex values
+ if (param.p !== undefined && param.q !== undefined &&
+ param.g !== undefined &&
+ param.y !== undefined && param.x === undefined) {
+ var key = new _KJUR_crypto_DSA();
+ key.setPublic(param.p, param.q, param.g, param.y);
+ return key;
+ }
+
+ // 2.3.2. bare DSA private key by hex values
+ if (param.p !== undefined && param.q !== undefined &&
+ param.g !== undefined &&
+ param.y !== undefined && param.x !== undefined) {
+ var key = new _KJUR_crypto_DSA();
+ key.setPrivate(param.p, param.q, param.g, param.y, param.x);
+ return key;
+ }
+
+ // 3. JWK
+ // 3.1. JWK RSA
+ // 3.1.1. JWK RSA public key by b64u values
+ if (param.kty === "RSA" &&
+ param.n !== undefined &&
+ param.e !== undefined &&
+ param.d === undefined) {
+ var key = new _RSAKey();
+ key.setPublic(b64utohex(param.n), b64utohex(param.e));
+ return key;
+ }
+
+ // 3.1.2. JWK RSA private key with p/q/dp/dq/coeff by b64u values
+ if (param.kty === "RSA" &&
+ param.n !== undefined &&
+ param.e !== undefined &&
+ param.d !== undefined &&
+ param.p !== undefined &&
+ param.q !== undefined &&
+ param.dp !== undefined &&
+ param.dq !== undefined &&
+ param.qi !== undefined) {
+ var key = new _RSAKey();
+ key.setPrivateEx(b64utohex(param.n),
+ b64utohex(param.e),
+ b64utohex(param.d),
+ b64utohex(param.p),
+ b64utohex(param.q),
+ b64utohex(param.dp),
+ b64utohex(param.dq),
+ b64utohex(param.qi));
+ return key;
+ }
+
+ // 3.1.3. JWK RSA private key without p/q/dp/dq/coeff by b64u
+ // since jsrsasign 5.0.0 keyutil 1.0.11
+ if (param.kty === "RSA" &&
+ param.n !== undefined &&
+ param.e !== undefined &&
+ param.d !== undefined) {
+ var key = new _RSAKey();
+ key.setPrivate(b64utohex(param.n),
+ b64utohex(param.e),
+ b64utohex(param.d));
+ return key;
+ }
+
+ // 3.2. JWK ECC
+ // 3.2.1. JWK ECC public key by b64u values
+ if (param.kty === "EC" &&
+ param.crv !== undefined &&
+ param.x !== undefined &&
+ param.y !== undefined &&
+ param.d === undefined) {
+ var ec = new _KJUR_crypto_ECDSA({"curve": param.crv});
+ var charlen = ec.ecparams.keylen / 4;
+ var hX = ("0000000000" + b64utohex(param.x)).slice(- charlen);
+ var hY = ("0000000000" + b64utohex(param.y)).slice(- charlen);
+ var hPub = "04" + hX + hY;
+ ec.setPublicKeyHex(hPub);
+ return ec;
+ }
+
+ // 3.2.2. JWK ECC private key by b64u values
+ if (param.kty === "EC" &&
+ param.crv !== undefined &&
+ param.x !== undefined &&
+ param.y !== undefined &&
+ param.d !== undefined) {
+ var ec = new _KJUR_crypto_ECDSA({"curve": param.crv});
+ var charlen = ec.ecparams.keylen / 4;
+ var hX = ("0000000000" + b64utohex(param.x)).slice(- charlen);
+ var hY = ("0000000000" + b64utohex(param.y)).slice(- charlen);
+ var hPub = "04" + hX + hY;
+ var hPrv = ("0000000000" + b64utohex(param.d)).slice(- charlen);
+ ec.setPublicKeyHex(hPub);
+ ec.setPrivateKeyHex(hPrv);
+ return ec;
+ }
+
+ // 4. (plain) hexadecimal data
+ // 4.1. get private key by PKCS#5 plain RSA/DSA/ECDSA hexadecimal string
+ if (hextype === "pkcs5prv") {
+ var h = param, _ASN1HEX = ASN1HEX, a, key;
+ a = _getChildIdx(h, 0);
+ if (a.length === 9) { // RSA (INT x 9)
+ key = new _RSAKey();
+ key.readPKCS5PrvKeyHex(h);
+ } else if (a.length === 6) { // DSA (INT x 6)
+ key = new _KJUR_crypto_DSA();
+ key.readPKCS5PrvKeyHex(h);
+ } else if (a.length > 2 && // ECDSA (INT, OCT prv, [0] curve, [1] pub)
+ h.substr(a[1], 2) === "04") {
+ key = new _KJUR_crypto_ECDSA();
+ key.readPKCS5PrvKeyHex(h);
+ } else {
+ throw "unsupported PKCS#1/5 hexadecimal key";
+ }
+
+ return key;
+ }
+
+ // 4.2. get private key by PKCS#8 plain RSA/DSA/ECDSA hexadecimal string
+ if (hextype === "pkcs8prv") {
+ var key = _KEYUTIL.getKeyFromPlainPrivatePKCS8Hex(param);
+ return key;
+ }
+
+ // 4.3. get public key by PKCS#8 RSA/DSA/ECDSA hexadecimal string
+ if (hextype === "pkcs8pub") {
+ return _KEYUTIL._getKeyFromPublicPKCS8Hex(param);
+ }
+
+ // 4.4. get public key by X.509 hexadecimal string for RSA/DSA/ECDSA
+ if (hextype === "x509pub") {
+ return X509.getPublicKeyFromCertHex(param);
+ }
+
+ // 5. by PEM certificate (-----BEGIN ... CERTIFICATE----)
+ if (param.indexOf("-END CERTIFICATE-", 0) != -1 ||
+ param.indexOf("-END X509 CERTIFICATE-", 0) != -1 ||
+ param.indexOf("-END TRUSTED CERTIFICATE-", 0) != -1) {
+ return X509.getPublicKeyFromCertPEM(param);
+ }
+
+ // 6. public key by PKCS#8 PEM string
+ if (param.indexOf("-END PUBLIC KEY-") != -1) {
+ var pubKeyHex = pemtohex(param, "PUBLIC KEY");
+ return _KEYUTIL._getKeyFromPublicPKCS8Hex(pubKeyHex);
+ }
+
+ // 8.1 private key by plain PKCS#5 PEM RSA string
+ // getKey("-----BEGIN RSA PRIVATE KEY-...")
+ if (param.indexOf("-END RSA PRIVATE KEY-") != -1 &&
+ param.indexOf("4,ENCRYPTED") == -1) {
+ var hex = _pemtohex(param, "RSA PRIVATE KEY");
+ return _KEYUTIL.getKey(hex, null, "pkcs5prv");
+ }
+
+ // 8.2. private key by plain PKCS#5 PEM DSA string
+ if (param.indexOf("-END DSA PRIVATE KEY-") != -1 &&
+ param.indexOf("4,ENCRYPTED") == -1) {
+
+ var hKey = _pemtohex(param, "DSA PRIVATE KEY");
+ var p = _getVbyList(hKey, 0, [1], "02");
+ var q = _getVbyList(hKey, 0, [2], "02");
+ var g = _getVbyList(hKey, 0, [3], "02");
+ var y = _getVbyList(hKey, 0, [4], "02");
+ var x = _getVbyList(hKey, 0, [5], "02");
+ var key = new _KJUR_crypto_DSA();
+ key.setPrivate(new BigInteger(p, 16),
+ new BigInteger(q, 16),
+ new BigInteger(g, 16),
+ new BigInteger(y, 16),
+ new BigInteger(x, 16));
+ return key;
+ }
+
+ // 10. private key by plain PKCS#8 PEM ECC/RSA string
+ if (param.indexOf("-END PRIVATE KEY-") != -1) {
+ return _KEYUTIL.getKeyFromPlainPrivatePKCS8PEM(param);
+ }
+
+ // 11.1 private key by encrypted PKCS#5 PEM RSA string
+ if (param.indexOf("-END RSA PRIVATE KEY-") != -1 &&
+ param.indexOf("4,ENCRYPTED") != -1) {
+ var hPKey = _KEYUTIL.getDecryptedKeyHex(param, passcode);
+ var rsaKey = new RSAKey();
+ rsaKey.readPKCS5PrvKeyHex(hPKey);
+ return rsaKey;
+ }
+
+ // 11.2. private key by encrypted PKCS#5 PEM ECDSA string
+ if (param.indexOf("-END EC PRIVATE KEY-") != -1 &&
+ param.indexOf("4,ENCRYPTED") != -1) {
+ var hKey = _KEYUTIL.getDecryptedKeyHex(param, passcode);
+
+ var key = _getVbyList(hKey, 0, [1], "04");
+ var curveNameOidHex = _getVbyList(hKey, 0, [2,0], "06");
+ var pubkey = _getVbyList(hKey, 0, [3,0], "03").substr(2);
+ var curveName = "";
+
+ if (KJUR.crypto.OID.oidhex2name[curveNameOidHex] !== undefined) {
+ curveName = KJUR.crypto.OID.oidhex2name[curveNameOidHex];
+ } else {
+ throw "undefined OID(hex) in KJUR.crypto.OID: " + curveNameOidHex;
+ }
+
+ var ec = new _KJUR_crypto_ECDSA({'curve': curveName});
+ ec.setPublicKeyHex(pubkey);
+ ec.setPrivateKeyHex(key);
+ ec.isPublic = false;
+ return ec;
+ }
+
+ // 11.3. private key by encrypted PKCS#5 PEM DSA string
+ if (param.indexOf("-END DSA PRIVATE KEY-") != -1 &&
+ param.indexOf("4,ENCRYPTED") != -1) {
+ var hKey = _KEYUTIL.getDecryptedKeyHex(param, passcode);
+ var p = _getVbyList(hKey, 0, [1], "02");
+ var q = _getVbyList(hKey, 0, [2], "02");
+ var g = _getVbyList(hKey, 0, [3], "02");
+ var y = _getVbyList(hKey, 0, [4], "02");
+ var x = _getVbyList(hKey, 0, [5], "02");
+ var key = new _KJUR_crypto_DSA();
+ key.setPrivate(new BigInteger(p, 16),
+ new BigInteger(q, 16),
+ new BigInteger(g, 16),
+ new BigInteger(y, 16),
+ new BigInteger(x, 16));
+ return key;
+ }
+
+ // 11. private key by encrypted PKCS#8 hexadecimal RSA/ECDSA string
+ if (param.indexOf("-END ENCRYPTED PRIVATE KEY-") != -1) {
+ return _KEYUTIL.getKeyFromEncryptedPKCS8PEM(param, passcode);
+ }
+
+ throw "not supported argument";
+};
+
+/**
+ * @name generateKeypair
+ * @memberOf KEYUTIL
+ * @function
+ * @static
+ * @param {String} alg 'RSA' or 'EC'
+ * @param {Object} keylenOrCurve key length for RSA or curve name for EC
+ * @return {Array} associative array of keypair which has prvKeyObj and pubKeyObj parameters
+ * @since keyutil 1.0.1
+ * @description
+ * This method generates a key pair of public key algorithm.
+ * The result will be an associative array which has following
+ * parameters:
+ *
+ * - prvKeyObj - RSAKey or ECDSA object of private key
+ * - pubKeyObj - RSAKey or ECDSA object of public key
+ *
+ * NOTE1: As for RSA algoirthm, public exponent has fixed
+ * value '0x10001'.
+ * NOTE2: As for EC algorithm, supported names of curve are
+ * secp256r1, secp256k1 and secp384r1.
+ * NOTE3: DSA is not supported yet.
+ * @example
+ * var rsaKeypair = KEYUTIL.generateKeypair("RSA", 1024);
+ * var ecKeypair = KEYUTIL.generateKeypair("EC", "secp256r1");
+ *
+ */
+KEYUTIL.generateKeypair = function(alg, keylenOrCurve) {
+ if (alg == "RSA") {
+ var keylen = keylenOrCurve;
+ var prvKey = new RSAKey();
+ prvKey.generate(keylen, '10001');
+ prvKey.isPrivate = true;
+ prvKey.isPublic = true;
+
+ var pubKey = new RSAKey();
+ var hN = prvKey.n.toString(16);
+ var hE = prvKey.e.toString(16);
+ pubKey.setPublic(hN, hE);
+ pubKey.isPrivate = false;
+ pubKey.isPublic = true;
+
+ var result = {};
+ result.prvKeyObj = prvKey;
+ result.pubKeyObj = pubKey;
+ return result;
+ } else if (alg == "EC") {
+ var curve = keylenOrCurve;
+ var ec = new KJUR.crypto.ECDSA({curve: curve});
+ var keypairHex = ec.generateKeyPairHex();
+
+ var prvKey = new KJUR.crypto.ECDSA({curve: curve});
+ prvKey.setPublicKeyHex(keypairHex.ecpubhex);
+ prvKey.setPrivateKeyHex(keypairHex.ecprvhex);
+ prvKey.isPrivate = true;
+ prvKey.isPublic = false;
+
+ var pubKey = new KJUR.crypto.ECDSA({curve: curve});
+ pubKey.setPublicKeyHex(keypairHex.ecpubhex);
+ pubKey.isPrivate = false;
+ pubKey.isPublic = true;
+
+ var result = {};
+ result.prvKeyObj = prvKey;
+ result.pubKeyObj = pubKey;
+ return result;
+ } else {
+ throw "unknown algorithm: " + alg;
+ }
+};
+
+/**
+ * get PEM formatted private or public key file from a RSA/ECDSA/DSA key object
+ * @name getPEM
+ * @memberOf KEYUTIL
+ * @function
+ * @static
+ * @param {Object} keyObjOrHex key object {@link RSAKey}, {@link KJUR.crypto.ECDSA} or {@link KJUR.crypto.DSA} to encode to
+ * @param {String} formatType (OPTION) output format type of "PKCS1PRV", "PKCS5PRV" or "PKCS8PRV" for private key
+ * @param {String} passwd (OPTION) password to protect private key
+ * @param {String} encAlg (OPTION) encryption algorithm for PKCS#5. currently supports DES-CBC, DES-EDE3-CBC and AES-{128,192,256}-CBC
+ * @param {String} hexType (OPTION) type of hex string (ex. pkcs5prv, pkcs8prv)
+ * @param {String} ivsaltHex hexadecimal string of IV and salt (default generated random IV)
+ * @since keyutil 1.0.4
+ * @description
+ *
+ * - NOTE1:
+ *
-
+ * PKCS#5 encrypted private key protection algorithm supports DES-CBC,
+ * DES-EDE3-CBC and AES-{128,192,256}-CBC
+ *
- NOTE2:
+ *
-
+ * OpenSSL supports
+ *
- NOTE3:
+ *
-
+ * Parameter "ivsaltHex" supported since jsrsasign 8.0.0 keyutil 1.2.0.
+ *
+ * @example
+ * KEUUTIL.getPEM(publicKey) => generates PEM PKCS#8 public key
+ * KEUUTIL.getPEM(privateKey, "PKCS1PRV") => generates PEM PKCS#1 plain private key
+ * KEUUTIL.getPEM(privateKey, "PKCS5PRV", "pass") => generates PEM PKCS#5 encrypted private key
+ * with DES-EDE3-CBC (DEFAULT)
+ * KEUUTIL.getPEM(privateKey, "PKCS5PRV", "pass", "DES-CBC") => generates PEM PKCS#5 encrypted
+ * private key with DES-CBC
+ * KEUUTIL.getPEM(privateKey, "PKCS8PRV") => generates PEM PKCS#8 plain private key
+ * KEUUTIL.getPEM(privateKey, "PKCS8PRV", "pass") => generates PEM PKCS#8 encrypted private key
+ * with PBKDF2_HmacSHA1_3DES
+ */
+KEYUTIL.getPEM = function(keyObjOrHex, formatType, passwd, encAlg, hexType, ivsaltHex) {
+ var _KJUR = KJUR,
+ _KJUR_asn1 = _KJUR.asn1,
+ _DERObjectIdentifier = _KJUR_asn1.DERObjectIdentifier,
+ _DERInteger = _KJUR_asn1.DERInteger,
+ _newObject = _KJUR_asn1.ASN1Util.newObject,
+ _KJUR_asn1_x509 = _KJUR_asn1.x509,
+ _SubjectPublicKeyInfo = _KJUR_asn1_x509.SubjectPublicKeyInfo,
+ _KJUR_crypto = _KJUR.crypto,
+ _DSA = _KJUR_crypto.DSA,
+ _ECDSA = _KJUR_crypto.ECDSA,
+ _RSAKey = RSAKey;
+
+ function _rsaprv2asn1obj(keyObjOrHex) {
+ var asn1Obj = _newObject({
+ "seq": [
+ {"int": 0 },
+ {"int": {"bigint": keyObjOrHex.n}},
+ {"int": keyObjOrHex.e},
+ {"int": {"bigint": keyObjOrHex.d}},
+ {"int": {"bigint": keyObjOrHex.p}},
+ {"int": {"bigint": keyObjOrHex.q}},
+ {"int": {"bigint": keyObjOrHex.dmp1}},
+ {"int": {"bigint": keyObjOrHex.dmq1}},
+ {"int": {"bigint": keyObjOrHex.coeff}}
+ ]
+ });
+ return asn1Obj;
+ };
+
+ function _ecdsaprv2asn1obj(keyObjOrHex) {
+ var asn1Obj2 = _newObject({
+ "seq": [
+ {"int": 1 },
+ {"octstr": {"hex": keyObjOrHex.prvKeyHex}},
+ {"tag": ['a0', true, {'oid': {'name': keyObjOrHex.curveName}}]},
+ {"tag": ['a1', true, {'bitstr': {'hex': '00' + keyObjOrHex.pubKeyHex}}]}
+ ]
+ });
+ return asn1Obj2;
+ };
+
+ function _dsaprv2asn1obj(keyObjOrHex) {
+ var asn1Obj = _newObject({
+ "seq": [
+ {"int": 0 },
+ {"int": {"bigint": keyObjOrHex.p}},
+ {"int": {"bigint": keyObjOrHex.q}},
+ {"int": {"bigint": keyObjOrHex.g}},
+ {"int": {"bigint": keyObjOrHex.y}},
+ {"int": {"bigint": keyObjOrHex.x}}
+ ]
+ });
+ return asn1Obj;
+ };
+
+ // 1. public key
+
+ // x. PEM PKCS#8 public key of RSA/ECDSA/DSA public key object
+ if (((_RSAKey !== undefined && keyObjOrHex instanceof _RSAKey) ||
+ (_DSA !== undefined && keyObjOrHex instanceof _DSA) ||
+ (_ECDSA !== undefined && keyObjOrHex instanceof _ECDSA)) &&
+ keyObjOrHex.isPublic == true &&
+ (formatType === undefined || formatType == "PKCS8PUB")) {
+ var asn1Obj = new _SubjectPublicKeyInfo(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+ return hextopem(asn1Hex, "PUBLIC KEY");
+ }
+
+ // 2. private
+
+ // x. PEM PKCS#1 plain private key of RSA private key object
+ if (formatType == "PKCS1PRV" &&
+ _RSAKey !== undefined &&
+ keyObjOrHex instanceof _RSAKey &&
+ (passwd === undefined || passwd == null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj = _rsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+ return hextopem(asn1Hex, "RSA PRIVATE KEY");
+ }
+
+ // x. PEM PKCS#1 plain private key of ECDSA private key object
+ if (formatType == "PKCS1PRV" &&
+ _ECDSA !== undefined &&
+ keyObjOrHex instanceof _ECDSA &&
+ (passwd === undefined || passwd == null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj1 =
+ new _DERObjectIdentifier({'name': keyObjOrHex.curveName});
+ var asn1Hex1 = asn1Obj1.getEncodedHex();
+ var asn1Obj2 = _ecdsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex2 = asn1Obj2.getEncodedHex();
+
+ var s = "";
+ s += hextopem(asn1Hex1, "EC PARAMETERS");
+ s += hextopem(asn1Hex2, "EC PRIVATE KEY");
+ return s;
+ }
+
+ // x. PEM PKCS#1 plain private key of DSA private key object
+ if (formatType == "PKCS1PRV" &&
+ _DSA !== undefined &&
+ keyObjOrHex instanceof _DSA &&
+ (passwd === undefined || passwd == null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj = _dsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+ return hextopem(asn1Hex, "DSA PRIVATE KEY");
+ }
+
+ // 3. private
+
+ // x. PEM PKCS#5 encrypted private key of RSA private key object
+ if (formatType == "PKCS5PRV" &&
+ _RSAKey !== undefined &&
+ keyObjOrHex instanceof _RSAKey &&
+ (passwd !== undefined && passwd != null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj = _rsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+
+ if (encAlg === undefined) encAlg = "DES-EDE3-CBC";
+ return this.getEncryptedPKCS5PEMFromPrvKeyHex("RSA", asn1Hex, passwd, encAlg, ivsaltHex);
+ }
+
+ // x. PEM PKCS#5 encrypted private key of ECDSA private key object
+ if (formatType == "PKCS5PRV" &&
+ _ECDSA !== undefined &&
+ keyObjOrHex instanceof _ECDSA &&
+ (passwd !== undefined && passwd != null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj = _ecdsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+
+ if (encAlg === undefined) encAlg = "DES-EDE3-CBC";
+ return this.getEncryptedPKCS5PEMFromPrvKeyHex("EC", asn1Hex, passwd, encAlg, ivsaltHex);
+ }
+
+ // x. PEM PKCS#5 encrypted private key of DSA private key object
+ if (formatType == "PKCS5PRV" &&
+ _DSA !== undefined &&
+ keyObjOrHex instanceof _DSA &&
+ (passwd !== undefined && passwd != null) &&
+ keyObjOrHex.isPrivate == true) {
+
+ var asn1Obj = _dsaprv2asn1obj(keyObjOrHex);
+ var asn1Hex = asn1Obj.getEncodedHex();
+
+ if (encAlg === undefined) encAlg = "DES-EDE3-CBC";
+ return this.getEncryptedPKCS5PEMFromPrvKeyHex("DSA", asn1Hex, passwd, encAlg, ivsaltHex);
+ }
+
+ // x. ======================================================================
+
+ var _getEncryptedPKCS8 = function(plainKeyHex, passcode) {
+ var info = _getEencryptedPKCS8Info(plainKeyHex, passcode);
+ //alert("iv=" + info.encryptionSchemeIV);
+ //alert("info.ciphertext2[" + info.ciphertext.length + "=" + info.ciphertext);
+ var asn1Obj = new _newObject({
+ "seq": [
+ {"seq": [
+ {"oid": {"name": "pkcs5PBES2"}},
+ {"seq": [
+ {"seq": [
+ {"oid": {"name": "pkcs5PBKDF2"}},
+ {"seq": [
+ {"octstr": {"hex": info.pbkdf2Salt}},
+ {"int": info.pbkdf2Iter}
+ ]}
+ ]},
+ {"seq": [
+ {"oid": {"name": "des-EDE3-CBC"}},
+ {"octstr": {"hex": info.encryptionSchemeIV}}
+ ]}
+ ]}
+ ]},
+ {"octstr": {"hex": info.ciphertext}}
+ ]
+ });
+ return asn1Obj.getEncodedHex();
+ };
+
+ var _getEencryptedPKCS8Info = function(plainKeyHex, passcode) {
+ var pbkdf2Iter = 100;
+ var pbkdf2SaltWS = CryptoJS.lib.WordArray.random(8);
+ var encryptionSchemeAlg = "DES-EDE3-CBC";
+ var encryptionSchemeIVWS = CryptoJS.lib.WordArray.random(8);
+ // PBKDF2 key
+ var pbkdf2KeyWS = CryptoJS.PBKDF2(passcode,
+ pbkdf2SaltWS, { "keySize": 192/32,
+ "iterations": pbkdf2Iter });
+ // ENCRYPT
+ var plainKeyWS = CryptoJS.enc.Hex.parse(plainKeyHex);
+ var encryptedKeyHex =
+ CryptoJS.TripleDES.encrypt(plainKeyWS, pbkdf2KeyWS, { "iv": encryptionSchemeIVWS }) + "";
+
+ //alert("encryptedKeyHex=" + encryptedKeyHex);
+
+ var info = {};
+ info.ciphertext = encryptedKeyHex;
+ //alert("info.ciphertext=" + info.ciphertext);
+ info.pbkdf2Salt = CryptoJS.enc.Hex.stringify(pbkdf2SaltWS);
+ info.pbkdf2Iter = pbkdf2Iter;
+ info.encryptionSchemeAlg = encryptionSchemeAlg;
+ info.encryptionSchemeIV = CryptoJS.enc.Hex.stringify(encryptionSchemeIVWS);
+ return info;
+ };
+
+ // x. PEM PKCS#8 plain private key of RSA private key object
+ if (formatType == "PKCS8PRV" &&
+ _RSAKey != undefined &&
+ keyObjOrHex instanceof _RSAKey &&
+ keyObjOrHex.isPrivate == true) {
+
+ var keyObj = _rsaprv2asn1obj(keyObjOrHex);
+ var keyHex = keyObj.getEncodedHex();
+
+ var asn1Obj = _newObject({
+ "seq": [
+ {"int": 0},
+ {"seq": [{"oid": {"name": "rsaEncryption"}},{"null": true}]},
+ {"octstr": {"hex": keyHex}}
+ ]
+ });
+ var asn1Hex = asn1Obj.getEncodedHex();
+
+ if (passwd === undefined || passwd == null) {
+ return hextopem(asn1Hex, "PRIVATE KEY");
+ } else {
+ var asn1Hex2 = _getEncryptedPKCS8(asn1Hex, passwd);
+ return hextopem(asn1Hex2, "ENCRYPTED PRIVATE KEY");
+ }
+ }
+
+ // x. PEM PKCS#8 plain private key of ECDSA private key object
+ if (formatType == "PKCS8PRV" &&
+ _ECDSA !== undefined &&
+ keyObjOrHex instanceof _ECDSA &&
+ keyObjOrHex.isPrivate == true) {
+
+ var keyObj = new _newObject({
+ "seq": [
+ {"int": 1},
+ {"octstr": {"hex": keyObjOrHex.prvKeyHex}},
+ {"tag": ['a1', true, {"bitstr": {"hex": "00" + keyObjOrHex.pubKeyHex}}]}
+ ]
+ });
+ var keyHex = keyObj.getEncodedHex();
+
+ var asn1Obj = _newObject({
+ "seq": [
+ {"int": 0},
+ {"seq": [
+ {"oid": {"name": "ecPublicKey"}},
+ {"oid": {"name": keyObjOrHex.curveName}}
+ ]},
+ {"octstr": {"hex": keyHex}}
+ ]
+ });
+
+ var asn1Hex = asn1Obj.getEncodedHex();
+ if (passwd === undefined || passwd == null) {
+ return hextopem(asn1Hex, "PRIVATE KEY");
+ } else {
+ var asn1Hex2 = _getEncryptedPKCS8(asn1Hex, passwd);
+ return hextopem(asn1Hex2, "ENCRYPTED PRIVATE KEY");
+ }
+ }
+
+ // x. PEM PKCS#8 plain private key of DSA private key object
+ if (formatType == "PKCS8PRV" &&
+ _DSA !== undefined &&
+ keyObjOrHex instanceof _DSA &&
+ keyObjOrHex.isPrivate == true) {
+
+ var keyObj = new _DERInteger({'bigint': keyObjOrHex.x});
+ var keyHex = keyObj.getEncodedHex();
+
+ var asn1Obj = _newObject({
+ "seq": [
+ {"int": 0},
+ {"seq": [
+ {"oid": {"name": "dsa"}},
+ {"seq": [
+ {"int": {"bigint": keyObjOrHex.p}},
+ {"int": {"bigint": keyObjOrHex.q}},
+ {"int": {"bigint": keyObjOrHex.g}}
+ ]}
+ ]},
+ {"octstr": {"hex": keyHex}}
+ ]
+ });
+
+ var asn1Hex = asn1Obj.getEncodedHex();
+ if (passwd === undefined || passwd == null) {
+ return hextopem(asn1Hex, "PRIVATE KEY");
+ } else {
+ var asn1Hex2 = _getEncryptedPKCS8(asn1Hex, passwd);
+ return hextopem(asn1Hex2, "ENCRYPTED PRIVATE KEY");
+ }
+ }
+
+ throw "unsupported object nor format";
+};
+
+// -- PUBLIC METHODS FOR CSR --------------------------------------------------
+
+/**
+ * get RSAKey/DSA/ECDSA public key object from PEM formatted PKCS#10 CSR string
+ * @name getKeyFromCSRPEM
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} csrPEM PEM formatted PKCS#10 CSR string
+ * @return {Object} RSAKey/DSA/ECDSA public key object
+ * @since keyutil 1.0.5
+ */
+KEYUTIL.getKeyFromCSRPEM = function(csrPEM) {
+ var csrHex = pemtohex(csrPEM, "CERTIFICATE REQUEST");
+ var key = KEYUTIL.getKeyFromCSRHex(csrHex);
+ return key;
+};
+
+/**
+ * get RSAKey/DSA/ECDSA public key object from hexadecimal string of PKCS#10 CSR
+ * @name getKeyFromCSRHex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} csrHex hexadecimal string of PKCS#10 CSR
+ * @return {Object} RSAKey/DSA/ECDSA public key object
+ * @since keyutil 1.0.5
+ */
+KEYUTIL.getKeyFromCSRHex = function(csrHex) {
+ var info = KEYUTIL.parseCSRHex(csrHex);
+ var key = KEYUTIL.getKey(info.p8pubkeyhex, null, "pkcs8pub");
+ return key;
+};
+
+/**
+ * parse hexadecimal string of PKCS#10 CSR (certificate signing request)
+ * @name parseCSRHex
+ * @memberOf KEYUTIL
+ * @function
+ * @param {String} csrHex hexadecimal string of PKCS#10 CSR
+ * @return {Array} associative array of parsed CSR
+ * @since keyutil 1.0.5
+ * @description
+ * Resulted associative array has following properties:
+ *
+ * - p8pubkeyhex - hexadecimal string of subject public key in PKCS#8
+ *
+ */
+KEYUTIL.parseCSRHex = function(csrHex) {
+ var _ASN1HEX = ASN1HEX;
+ var _getChildIdx = _ASN1HEX.getChildIdx;
+ var _getTLV = _ASN1HEX.getTLV;
+ var result = {};
+ var h = csrHex;
+
+ // 1. sequence
+ if (h.substr(0, 2) != "30")
+ throw "malformed CSR(code:001)"; // not sequence
+
+ var a1 = _getChildIdx(h, 0);
+ if (a1.length < 1)
+ throw "malformed CSR(code:002)"; // short length
+
+ // 2. 2nd sequence
+ if (h.substr(a1[0], 2) != "30")
+ throw "malformed CSR(code:003)"; // not sequence
+
+ var a2 = _getChildIdx(h, a1[0]);
+ if (a2.length < 3)
+ throw "malformed CSR(code:004)"; // 2nd seq short elem
+
+ result.p8pubkeyhex = _getTLV(h, a2[2]);
+
+ return result;
+};
+
+// -- OTHER STATIC PUBLIC METHODS -------------------------------------------------
+
+/**
+ * convert from RSAKey/KJUR.crypto.ECDSA public/private key object to RFC 7517 JSON Web Key(JWK)
+ * @name getJWKFromKey
+ * @memberOf KEYUTIL
+ * @function
+ * @static
+ * @param {Object} RSAKey/KJUR.crypto.ECDSA public/private key object
+ * @return {Object} JWK object
+ * @since keyutil 1.0.13 jsrsasign 5.0.14
+ * @description
+ * This static method convert from RSAKey/KJUR.crypto.ECDSA public/private key object
+ * to RFC 7517 JSON Web Key(JWK)
+ * @example
+ * kp1 = KEYUTIL.generateKeypair("EC", "P-256");
+ * jwkPrv1 = KEYUTIL.getJWKFromKey(kp1.prvKeyObj);
+ * jwkPub1 = KEYUTIL.getJWKFromKey(kp1.pubKeyObj);
+ *
+ * kp2 = KEYUTIL.generateKeypair("RSA", 2048);
+ * jwkPrv2 = KEYUTIL.getJWKFromKey(kp2.prvKeyObj);
+ * jwkPub2 = KEYUTIL.getJWKFromKey(kp2.pubKeyObj);
+ *
+ * // if you need RFC 7638 JWK thumprint as kid do like this:
+ * jwkPub2.kid = KJUR.jws.JWS.getJWKthumbprint(jwkPub2);
+ */
+KEYUTIL.getJWKFromKey = function(keyObj) {
+ var jwk = {};
+ if (keyObj instanceof RSAKey && keyObj.isPrivate) {
+ jwk.kty = "RSA";
+ jwk.n = hextob64u(keyObj.n.toString(16));
+ jwk.e = hextob64u(keyObj.e.toString(16));
+ jwk.d = hextob64u(keyObj.d.toString(16));
+ jwk.p = hextob64u(keyObj.p.toString(16));
+ jwk.q = hextob64u(keyObj.q.toString(16));
+ jwk.dp = hextob64u(keyObj.dmp1.toString(16));
+ jwk.dq = hextob64u(keyObj.dmq1.toString(16));
+ jwk.qi = hextob64u(keyObj.coeff.toString(16));
+ return jwk;
+ } else if (keyObj instanceof RSAKey && keyObj.isPublic) {
+ jwk.kty = "RSA";
+ jwk.n = hextob64u(keyObj.n.toString(16));
+ jwk.e = hextob64u(keyObj.e.toString(16));
+ return jwk;
+ } else if (keyObj instanceof KJUR.crypto.ECDSA && keyObj.isPrivate) {
+ var name = keyObj.getShortNISTPCurveName();
+ if (name !== "P-256" && name !== "P-384")
+ throw "unsupported curve name for JWT: " + name;
+ var xy = keyObj.getPublicKeyXYHex();
+ jwk.kty = "EC";
+ jwk.crv = name;
+ jwk.x = hextob64u(xy.x);
+ jwk.y = hextob64u(xy.y);
+ jwk.d = hextob64u(keyObj.prvKeyHex);
+ return jwk;
+ } else if (keyObj instanceof KJUR.crypto.ECDSA && keyObj.isPublic) {
+ var name = keyObj.getShortNISTPCurveName();
+ if (name !== "P-256" && name !== "P-384")
+ throw "unsupported curve name for JWT: " + name;
+ var xy = keyObj.getPublicKeyXYHex();
+ jwk.kty = "EC";
+ jwk.crv = name;
+ jwk.x = hextob64u(xy.x);
+ jwk.y = hextob64u(xy.y);
+ return jwk;
+ }
+ throw "not supported key object";
+};
+
+
diff --git a/source/pack.js b/source/pack.js
new file mode 100644
index 0000000..70e3b09
--- /dev/null
+++ b/source/pack.js
@@ -0,0 +1,384 @@
+module.exports = function pack (format) {
+ // discuss at: http://locutus.io/php/pack/
+ // original by: Tim de Koning (http://www.kingsquare.nl)
+ // parts by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
+ // bugfixed by: Tim de Koning (http://www.kingsquare.nl)
+ // note 1: Float encoding by: Jonas Raoni Soares Silva
+ // note 1: Home: http://www.kingsquare.nl/blog/12-12-2009/13507444
+ // note 1: Feedback: phpjs-pack@kingsquare.nl
+ // note 1: "machine dependent byte order and size" aren't
+ // note 1: applicable for JavaScript; pack works as on a 32bit,
+ // note 1: little endian machine.
+ // example 1: pack('nvc*', 0x1234, 0x5678, 65, 66)
+ // returns 1: '\u00124xVAB'
+ // example 2: pack('H4', '2345')
+ // returns 2: '#E'
+ // example 3: pack('H*', 'D5')
+ // returns 3: 'Õ'
+ // example 4: pack('d', -100.876)
+ // returns 4: "\u0000\u0000\u0000\u0000\u00008YÀ"
+ // test: skip-1
+
+ var formatPointer = 0
+ var argumentPointer = 1
+ var result = ''
+ var argument = ''
+ var i = 0
+ var r = []
+ var instruction, quantifier, word, precisionBits, exponentBits, extraNullCount
+
+ // vars used by float encoding
+ var bias
+ var minExp
+ var maxExp
+ var minUnnormExp
+ var status
+ var exp
+ var len
+ var bin
+ var signal
+ var n
+ var intPart
+ var floatPart
+ var lastBit
+ var rounded
+ var j
+ var k
+ var tmpResult
+
+ while (formatPointer < format.length) {
+ instruction = format.charAt(formatPointer)
+ quantifier = ''
+ formatPointer++
+ while ((formatPointer < format.length) && (format.charAt(formatPointer)
+ .match(/[\d*]/) !== null)) {
+ quantifier += format.charAt(formatPointer)
+ formatPointer++
+ }
+ if (quantifier === '') {
+ quantifier = '1'
+ }
+
+ // Now pack variables: 'quantifier' times 'instruction'
+ switch (instruction) {
+ case 'a':
+ case 'A':
+ // NUL-padded string
+ // SPACE-padded string
+ if (typeof arguments[argumentPointer] === 'undefined') {
+ throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments')
+ } else {
+ argument = String(arguments[argumentPointer])
+ }
+ if (quantifier === '*') {
+ quantifier = argument.length
+ }
+ for (i = 0; i < quantifier; i++) {
+ if (typeof argument[i] === 'undefined') {
+ if (instruction === 'a') {
+ result += String.fromCharCode(0)
+ } else {
+ result += ' '
+ }
+ } else {
+ result += argument[i]
+ }
+ }
+ argumentPointer++
+ break
+ case 'h':
+ case 'H':
+ // Hex string, low nibble first
+ // Hex string, high nibble first
+ if (typeof arguments[argumentPointer] === 'undefined') {
+ throw new Error('Warning: pack() Type ' + instruction + ': not enough arguments')
+ } else {
+ argument = arguments[argumentPointer]
+ }
+ if (quantifier === '*') {
+ quantifier = argument.length
+ }
+ if (quantifier > argument.length) {
+ var msg = 'Warning: pack() Type ' + instruction + ': not enough characters in string'
+ throw new Error(msg)
+ }
+
+ for (i = 0; i < quantifier; i += 2) {
+ // Always get per 2 bytes...
+ word = argument[i]
+ if (((i + 1) >= quantifier) || typeof argument[i + 1] === 'undefined') {
+ word += '0'
+ } else {
+ word += argument[i + 1]
+ }
+ // The fastest way to reverse?
+ if (instruction === 'h') {
+ word = word[1] + word[0]
+ }
+ result += String.fromCharCode(parseInt(word, 16))
+ }
+ argumentPointer++
+ break
+
+ case 'c':
+ case 'C':
+ // signed char
+ // unsigned char
+ // c and C is the same in pack
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer])
+ argumentPointer++
+ }
+ break
+
+ case 's':
+ case 'S':
+ case 'v':
+ // signed short (always 16 bit, machine byte order)
+ // unsigned short (always 16 bit, machine byte order)
+ // s and S is the same in pack
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF)
+ argumentPointer++
+ }
+ break
+
+ case 'n':
+ // unsigned short (always 16 bit, big endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF)
+ argumentPointer++
+ }
+ break
+
+ case 'i':
+ case 'I':
+ case 'l':
+ case 'L':
+ case 'V':
+ // signed integer (machine dependent size and byte order)
+ // unsigned integer (machine dependent size and byte order)
+ // signed long (always 32 bit, machine byte order)
+ // unsigned long (always 32 bit, machine byte order)
+ // unsigned long (always 32 bit, little endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF)
+ argumentPointer++
+ }
+
+ break
+ case 'N':
+ // unsigned long (always 32 bit, big endian byte order)
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF)
+ result += String.fromCharCode(arguments[argumentPointer] & 0xFF)
+ argumentPointer++
+ }
+ break
+
+ case 'f':
+ case 'd':
+ // float (machine dependent size and representation)
+ // double (machine dependent size and representation)
+ // version based on IEEE754
+ precisionBits = 23
+ exponentBits = 8
+ if (instruction === 'd') {
+ precisionBits = 52
+ exponentBits = 11
+ }
+
+ if (quantifier === '*') {
+ quantifier = arguments.length - argumentPointer
+ }
+ if (quantifier > (arguments.length - argumentPointer)) {
+ throw new Error('Warning: pack() Type ' + instruction + ': too few arguments')
+ }
+ for (i = 0; i < quantifier; i++) {
+ argument = arguments[argumentPointer]
+ bias = Math.pow(2, exponentBits - 1) - 1
+ minExp = -bias + 1
+ maxExp = bias
+ minUnnormExp = minExp - precisionBits
+ status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0
+ exp = 0
+ len = 2 * bias + 1 + precisionBits + 3
+ bin = new Array(len)
+ signal = (n = status !== 0 ? 0 : n) < 0
+ n = Math.abs(n)
+ intPart = Math.floor(n)
+ floatPart = n - intPart
+
+ for (k = len; k;) {
+ bin[--k] = 0
+ }
+ for (k = bias + 2; intPart && k;) {
+ bin[--k] = intPart % 2
+ intPart = Math.floor(intPart / 2)
+ }
+ for (k = bias + 1; floatPart > 0 && k; --floatPart) {
+ (bin[++k] = ((floatPart *= 2) >= 1) - 0)
+ }
+ for (k = -1; ++k < len && !bin[k];) {}
+
+ // @todo: Make this more readable:
+ var key = (lastBit = precisionBits - 1 +
+ (k =
+ (exp = bias + 1 - k) >= minExp &&
+ exp <= maxExp ? k + 1 : bias + 1 - (exp = minExp - 1))) + 1
+
+ if (bin[key]) {
+ if (!(rounded = bin[lastBit])) {
+ for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {}
+ }
+ for (j = lastBit + 1; rounded && --j >= 0;
+ (bin[j] = !bin[j] - 0) && (rounded = 0)) {}
+ }
+
+ for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {}
+
+ if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) {
+ ++k
+ } else {
+ if (exp < minExp) {
+ if (exp !== bias + 1 - len && exp < minUnnormExp) {
+ // "encodeFloat::float underflow"
+ }
+ k = bias + 1 - (exp = minExp - 1)
+ }
+ }
+
+ if (intPart || status !== 0) {
+ exp = maxExp + 1
+ k = bias + 2
+ if (status === -Infinity) {
+ signal = 1
+ } else if (isNaN(status)) {
+ bin[k] = 1
+ }
+ }
+
+ n = Math.abs(exp + bias)
+ tmpResult = ''
+
+ for (j = exponentBits + 1; --j;) {
+ tmpResult = (n % 2) + tmpResult
+ n = n >>= 1
+ }
+
+ n = 0
+ j = 0
+ k = (tmpResult = (signal ? '1' : '0') + tmpResult + (bin
+ .slice(k, k + precisionBits)
+ .join(''))
+ ).length
+ r = []
+
+ for (; k;) {
+ n += (1 << j) * tmpResult.charAt(--k)
+ if (j === 7) {
+ r[r.length] = String.fromCharCode(n)
+ n = 0
+ }
+ j = (j + 1) % 8
+ }
+
+ r[r.length] = n ? String.fromCharCode(n) : ''
+ result += r.join('')
+ argumentPointer++
+ }
+ break
+
+ case 'x':
+ // NUL byte
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type x: \'*\' ignored')
+ }
+ for (i = 0; i < quantifier; i++) {
+ result += String.fromCharCode(0)
+ }
+ break
+
+ case 'X':
+ // Back up one byte
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type X: \'*\' ignored')
+ }
+ for (i = 0; i < quantifier; i++) {
+ if (result.length === 0) {
+ throw new Error('Warning: pack(): Type X:' + ' outside of string')
+ } else {
+ result = result.substring(0, result.length - 1)
+ }
+ }
+ break
+
+ case '@':
+ // NUL-fill to absolute position
+ if (quantifier === '*') {
+ throw new Error('Warning: pack(): Type X: \'*\' ignored')
+ }
+ if (quantifier > result.length) {
+ extraNullCount = quantifier - result.length
+ for (i = 0; i < extraNullCount; i++) {
+ result += String.fromCharCode(0)
+ }
+ }
+ if (quantifier < result.length) {
+ result = result.substring(0, quantifier)
+ }
+ break
+
+ default:
+ throw new Error('Warning: pack() Type ' + instruction + ': unknown format code')
+ }
+ }
+ if (argumentPointer < arguments.length) {
+ var msg2 = 'Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused'
+ throw new Error(msg2)
+ }
+
+ return result
+}
diff --git a/source/prng4.js b/source/prng4.js
new file mode 100644
index 0000000..9c4fd68
--- /dev/null
+++ b/source/prng4.js
@@ -0,0 +1,47 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// 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;
diff --git a/source/rng.js b/source/rng.js
new file mode 100644
index 0000000..d7b3848
--- /dev/null
+++ b/source/rng.js
@@ -0,0 +1,81 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// Random number generator - requires a PRNG backend, e.g. prng4.js
+
+// For best results, put code like
+//
+// 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 !== undefined &&
+ (window.crypto !== undefined ||
+ window.msCrypto !== undefined)) {
+ var crypto = window.crypto || window.msCrypto;
+ if (crypto.getRandomValues) {
+ // Use webcrypto if available
+ var ua = new Uint8Array(32);
+ crypto.getRandomValues(ua);
+ for(t = 0; t < 32; ++t)
+ rng_pool[rng_pptr++] = ua[t];
+ } else if (navigator.appName == "Netscape" && navigator.appVersion < "5") {
+ // 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;
diff --git a/source/rsa.js b/source/rsa.js
new file mode 100644
index 0000000..b27c421
--- /dev/null
+++ b/source/rsa.js
@@ -0,0 +1,212 @@
+/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
+ */
+// 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
+ throw "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);
+}
+
+// PKCS#1 (OAEP) mask generation function
+function oaep_mgf1_arr(seed, len, hash)
+{
+ var mask = '', i = 0;
+
+ while (mask.length < len)
+ {
+ mask += hash(String.fromCharCode.apply(String, seed.concat([
+ (i & 0xff000000) >> 24,
+ (i & 0x00ff0000) >> 16,
+ (i & 0x0000ff00) >> 8,
+ i & 0x000000ff])));
+ i += 1;
+ }
+
+ return mask;
+}
+
+/**
+ * PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
+ * @name oaep_pad
+ * @param s raw string of message
+ * @param n key length of RSA key
+ * @param hash JavaScript function to calculate raw hash value from raw string or algorithm name (ex. "SHA1")
+ * @param hashLen byte length of resulted hash value (ex. 20 for SHA1)
+ * @return {BigInteger} BigInteger object of resulted PKCS#1 OAEP padded message
+ * @description
+ * This function calculates OAEP padded message from original message.
+ * NOTE: Since jsrsasign 6.2.0, 'hash' argument can accept an algorithm name such as "sha1".
+ * @example
+ * oaep_pad("aaa", 128) → big integer object // SHA-1 by default
+ * oaep_pad("aaa", 128, function(s) {...}, 20);
+ * oaep_pad("aaa", 128, "sha1");
+ */
+function oaep_pad(s, n, hash, hashLen) {
+ var MD = KJUR.crypto.MessageDigest;
+ var Util = KJUR.crypto.Util;
+ var algName = null;
+
+ if (!hash) hash = "sha1";
+
+ if (typeof hash === "string") {
+ algName = MD.getCanonicalAlgName(hash);
+ hashLen = MD.getHashLength(algName);
+ hash = function(s) {
+ return hextorstr(Util.hashHex(rstrtohex(s), algName));
+ };
+ }
+
+ if (s.length + 2 * hashLen + 2 > n) {
+ throw "Message too long for RSA";
+ }
+
+ var PS = '', i;
+
+ for (i = 0; i < n - s.length - 2 * hashLen - 2; i += 1) {
+ PS += '\x00';
+ }
+
+ var DB = hash('') + PS + '\x01' + s;
+ var seed = new Array(hashLen);
+ new SecureRandom().nextBytes(seed);
+
+ var dbMask = oaep_mgf1_arr(seed, DB.length, hash);
+ var maskedDB = [];
+
+ for (i = 0; i < DB.length; i += 1) {
+ maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
+ }
+
+ var seedMask = oaep_mgf1_arr(maskedDB, seed.length, hash);
+ var maskedSeed = [0];
+
+ for (i = 0; i < seed.length; i += 1) {
+ maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i);
+ }
+
+ return new BigInteger(maskedSeed.concat(maskedDB));
+}
+
+// "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) {
+ this.isPublic = true;
+ this.isPrivate = false;
+ if (typeof N !== "string") {
+ this.n = N;
+ this.e = E;
+ } else if(N != null && E != null && N.length > 0 && E.length > 0) {
+ this.n = parseBigInt(N,16);
+ this.e = parseInt(E,16);
+ } else {
+ throw "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 OAEP RSA encryption of "text" as an even-length hex string
+function RSAEncryptOAEP(text, hash, hashLen) {
+ var m = oaep_pad(text, (this.n.bitLength() + 7) >> 3, hash, hashLen);
+ 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.encryptOAEP = RSAEncryptOAEP;
+//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
+
+RSAKey.prototype.type = "RSA";
diff --git a/source/sha256.js b/source/sha256.js
new file mode 100644
index 0000000..a3790b0
--- /dev/null
+++ b/source/sha256.js
@@ -0,0 +1,185 @@
+/*
+CryptoJS v3.1.2
+code.google.com/p/crypto-js
+(c) 2009-2013 by Jeff Mott. All rights reserved.
+code.google.com/p/crypto-js/wiki/License
+*/
+(function (Math) {
+ // Shortcuts
+ var C = CryptoJS;
+ var C_lib = C.lib;
+ var WordArray = C_lib.WordArray;
+ var Hasher = C_lib.Hasher;
+ var C_algo = C.algo;
+
+ // Initialization and round constants tables
+ var H = [];
+ var K = [];
+
+ // Compute constants
+ (function () {
+ function isPrime(n) {
+ var sqrtN = Math.sqrt(n);
+ for (var factor = 2; factor <= sqrtN; factor++) {
+ if (!(n % factor)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getFractionalBits(n) {
+ return ((n - (n | 0)) * 0x100000000) | 0;
+ }
+
+ var n = 2;
+ var nPrime = 0;
+ while (nPrime < 64) {
+ if (isPrime(n)) {
+ if (nPrime < 8) {
+ H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
+ }
+ K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
+
+ nPrime++;
+ }
+
+ n++;
+ }
+ }());
+
+ // Reusable object
+ var W = [];
+
+ /**
+ * SHA-256 hash algorithm.
+ */
+ var SHA256 = C_algo.SHA256 = Hasher.extend({
+ _doReset: function () {
+ this._hash = new WordArray.init(H.slice(0));
+ },
+
+ _doProcessBlock: function (M, offset) {
+ // Shortcut
+ var H = this._hash.words;
+
+ // Working variables
+ var a = H[0];
+ var b = H[1];
+ var c = H[2];
+ var d = H[3];
+ var e = H[4];
+ var f = H[5];
+ var g = H[6];
+ var h = H[7];
+
+ // Computation
+ for (var i = 0; i < 64; i++) {
+ if (i < 16) {
+ W[i] = M[offset + i] | 0;
+ } else {
+ var gamma0x = W[i - 15];
+ var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
+ ((gamma0x << 14) | (gamma0x >>> 18)) ^
+ (gamma0x >>> 3);
+
+ var gamma1x = W[i - 2];
+ var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
+ ((gamma1x << 13) | (gamma1x >>> 19)) ^
+ (gamma1x >>> 10);
+
+ W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
+ }
+
+ var ch = (e & f) ^ (~e & g);
+ var maj = (a & b) ^ (a & c) ^ (b & c);
+
+ var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
+ var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
+
+ var t1 = h + sigma1 + ch + K[i] + W[i];
+ var t2 = sigma0 + maj;
+
+ h = g;
+ g = f;
+ f = e;
+ e = (d + t1) | 0;
+ d = c;
+ c = b;
+ b = a;
+ a = (t1 + t2) | 0;
+ }
+
+ // Intermediate hash value
+ H[0] = (H[0] + a) | 0;
+ H[1] = (H[1] + b) | 0;
+ H[2] = (H[2] + c) | 0;
+ H[3] = (H[3] + d) | 0;
+ H[4] = (H[4] + e) | 0;
+ H[5] = (H[5] + f) | 0;
+ H[6] = (H[6] + g) | 0;
+ H[7] = (H[7] + h) | 0;
+ },
+
+ _doFinalize: function () {
+ // Shortcuts
+ var data = this._data;
+ var dataWords = data.words;
+
+ var nBitsTotal = this._nDataBytes * 8;
+ var nBitsLeft = data.sigBytes * 8;
+
+ // Add padding
+ dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
+ dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
+ data.sigBytes = dataWords.length * 4;
+
+ // Hash final blocks
+ this._process();
+
+ // Return final computed hash
+ return this._hash;
+ },
+
+ clone: function () {
+ var clone = Hasher.clone.call(this);
+ clone._hash = this._hash.clone();
+
+ return clone;
+ }
+ });
+
+ /**
+ * Shortcut function to the hasher's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ *
+ * @return {WordArray} The hash.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hash = CryptoJS.SHA256('message');
+ * var hash = CryptoJS.SHA256(wordArray);
+ */
+ C.SHA256 = Hasher._createHelper(SHA256);
+
+ /**
+ * Shortcut function to the HMAC's object interface.
+ *
+ * @param {WordArray|string} message The message to hash.
+ * @param {WordArray|string} key The secret key.
+ *
+ * @return {WordArray} The HMAC.
+ *
+ * @static
+ *
+ * @example
+ *
+ * var hmac = CryptoJS.HmacSHA256(message, key);
+ */
+ C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
+}(Math));
diff --git a/source/yahoo.js b/source/yahoo.js
new file mode 100644
index 0000000..b088151
--- /dev/null
+++ b/source/yahoo.js
@@ -0,0 +1,72 @@
+/*!
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.com/yui/license.html
+version: 2.9.0
+*/
+if (YAHOO === undefined) {var YAHOO = {};}
+YAHOO.lang = {
+ /**
+ * Utility to set up the prototype, constructor and superclass properties to
+ * support an inheritance strategy that can chain constructors and methods.
+ * Static members will not be inherited.
+ *
+ * @method extend
+ * @static
+ * @param {Function} subc the object to modify
+ * @param {Function} superc the object to inherit
+ * @param {Object} overrides additional properties/methods to add to the
+ * subclass prototype. These will override the
+ * matching items obtained from the superclass
+ * if present.
+ */
+ extend: function(subc, superc, overrides) {
+ if (! superc || ! subc) {
+ throw new Error("YAHOO.lang.extend failed, please check that " +
+ "all dependencies are included.");
+ }
+
+ var F = function() {};
+ F.prototype = superc.prototype;
+ subc.prototype = new F();
+ subc.prototype.constructor = subc;
+ subc.superclass = superc.prototype;
+
+ if (superc.prototype.constructor == Object.prototype.constructor) {
+ superc.prototype.constructor = superc;
+ }
+
+ if (overrides) {
+ var i;
+ for (i in overrides) {
+ subc.prototype[i] = overrides[i];
+ }
+
+ /*
+ * IE will not enumerate native functions in a derived object even if the
+ * function was overridden. This is a workaround for specific functions
+ * we care about on the Object prototype.
+ * @property _IEEnumFix
+ * @param {Function} r the object to receive the augmentation
+ * @param {Function} s the object that supplies the properties to augment
+ * @static
+ * @private
+ */
+ var _IEEnumFix = function() {},
+ ADD = ["toString", "valueOf"];
+ try {
+ if (/MSIE/.test(navigator.userAgent)) {
+ _IEEnumFix = function(r, s) {
+ for (i = 0; i < ADD.length; i = i + 1) {
+ var fname = ADD[i], f = s[fname];
+ if (typeof f === 'function' && f != Object.prototype[fname]) {
+ r[fname] = f;
+ }
+ }
+ };
+ }
+ } catch (ex) {};
+ _IEEnumFix(subc.prototype, overrides);
+ }
+ }
+};