forked from lsl/xzjl-ui
parent
c19809203e
commit
df95a5ba0a
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,130 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Neo Han
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
File: /src/LICENSE.txt
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2015 Form.io
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
File: /lib/jsrsasign/LICENSE.txt
|
||||||
|
|
||||||
|
|
||||||
|
CONTAINS CODE FROM YUI LIBRARY SEE LICENSE @ http://yuilibrary.com/license/
|
||||||
|
|
||||||
|
The 'jsrsasign'(RSA-Sign JavaScript Library) License
|
||||||
|
|
||||||
|
Copyright (c) 2010-2013 Kenji Urushima
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
File: /lib/jsbn/LICENSE.txt
|
||||||
|
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
---------
|
||||||
|
|
||||||
|
This software is covered under the following copyright:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003-2005 Tom Wu
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||||
|
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
|
||||||
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
|
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
|
||||||
|
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
|
||||||
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* In addition, the following condition applies:
|
||||||
|
*
|
||||||
|
* All redistributions must retain an intact copy of this copyright notice
|
||||||
|
* and disclaimer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Address all questions regarding this license to:
|
||||||
|
|
||||||
|
Tom Wu
|
||||||
|
tjw@cs.Stanford.EDU
|
||||||
|
File: /lib/asn1js/LICENSE.txt
|
||||||
|
|
||||||
|
|
||||||
|
ASN.1 JavaScript decoder
|
||||||
|
Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
import { b64tohex, hex2b64 } from "./lib/jsbn/base64";
|
||||||
|
import { JSEncryptRSAKey } from "./JSEncryptRSAKey";
|
||||||
|
import version from './version.json';
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Object} [options = {}] - An object to customize JSEncrypt behaviour
|
||||||
|
* possible parameters are:
|
||||||
|
* - default_key_size {number} default: 1024 the key size in bit
|
||||||
|
* - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent
|
||||||
|
* - log {boolean} default: false whether log warn/error or not
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
var JSEncrypt = /** @class */ (function () {
|
||||||
|
function JSEncrypt(options) {
|
||||||
|
if (options === void 0) { options = {}; }
|
||||||
|
options = options || {};
|
||||||
|
this.default_key_size = options.default_key_size ? parseInt(options.default_key_size, 10) : 1024;
|
||||||
|
this.default_public_exponent = options.default_public_exponent || "010001"; // 65537 default openssl public exponent for rsa key type
|
||||||
|
this.log = options.log || false;
|
||||||
|
// The private and public key.
|
||||||
|
this.key = null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Method to set the rsa key parameter (one method is enough to set both the public
|
||||||
|
* and the private key, since the private key contains the public key paramenters)
|
||||||
|
* Log a warning if logs are enabled
|
||||||
|
* @param {Object|string} key the pem encoded string or an object (with or without header/footer)
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.setKey = function (key) {
|
||||||
|
if (this.log && this.key) {
|
||||||
|
console.warn("A key was already set, overriding existing.");
|
||||||
|
}
|
||||||
|
this.key = new JSEncryptRSAKey(key);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for setKey, for api compatibility
|
||||||
|
* @see setKey
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.setPrivateKey = function (privkey) {
|
||||||
|
// Create the key.
|
||||||
|
this.setKey(privkey);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for setKey, for api compatibility
|
||||||
|
* @see setKey
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.setPublicKey = function (pubkey) {
|
||||||
|
// Sets the public key.
|
||||||
|
this.setKey(pubkey);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for RSAKey object's decrypt, decrypt the string using the private
|
||||||
|
* components of the rsa key object. Note that if the object was not set will be created
|
||||||
|
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
|
||||||
|
* @param {string} str base64 encoded crypted string to decrypt
|
||||||
|
* @return {string} the decrypted string
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.decrypt = function (str) {
|
||||||
|
// Return the decrypted string.
|
||||||
|
try {
|
||||||
|
return this.getKey().decrypt(b64tohex(str));
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for RSAKey object's encrypt, encrypt the string using the public
|
||||||
|
* components of the rsa key object. Note that if the object was not set will be created
|
||||||
|
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
|
||||||
|
* @param {string} str the string to encrypt
|
||||||
|
* @return {string} the encrypted string encoded in base64
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.encrypt = function (str) {
|
||||||
|
// Return the encrypted string.
|
||||||
|
try {
|
||||||
|
return hex2b64(this.getKey().encrypt(str));
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 超长文本加密
|
||||||
|
JSEncrypt.prototype.encryptLong = function (str) {
|
||||||
|
try {
|
||||||
|
return hex2b64(this.getKey().encryptLong(str));
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 超长文本解密
|
||||||
|
JSEncrypt.prototype.decryptLong = function (str) {
|
||||||
|
try {
|
||||||
|
return this.getKey().decryptLong(b64tohex(str));
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for RSAKey object's sign.
|
||||||
|
* @param {string} str the string to sign
|
||||||
|
* @param {function} digestMethod hash method
|
||||||
|
* @param {string} digestName the name of the hash algorithm
|
||||||
|
* @return {string} the signature encoded in base64
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.sign = function (str, digestMethod, digestName) {
|
||||||
|
// return the RSA signature of 'str' in 'hex' format.
|
||||||
|
try {
|
||||||
|
return hex2b64(this.getKey().sign(str, digestMethod, digestName));
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Proxy method for RSAKey object's verify.
|
||||||
|
* @param {string} str the string to verify
|
||||||
|
* @param {string} signature the signature encoded in base64 to compare the string to
|
||||||
|
* @param {function} digestMethod hash method
|
||||||
|
* @return {boolean} whether the data and signature match
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.verify = function (str, signature, digestMethod) {
|
||||||
|
// Return the decrypted 'digest' of the signature.
|
||||||
|
try {
|
||||||
|
return this.getKey().verify(str, b64tohex(signature), digestMethod);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object
|
||||||
|
* will be created and returned
|
||||||
|
* @param {callback} [cb] the callback to be called if we want the key to be generated
|
||||||
|
* in an async fashion
|
||||||
|
* @returns {JSEncryptRSAKey} the JSEncryptRSAKey object
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.getKey = function (cb) {
|
||||||
|
// Only create new if it does not exist.
|
||||||
|
if (!this.key) {
|
||||||
|
// Get a new private key.
|
||||||
|
this.key = new JSEncryptRSAKey();
|
||||||
|
if (cb && {}.toString.call(cb) === "[object Function]") {
|
||||||
|
this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Generate the key.
|
||||||
|
this.key.generate(this.default_key_size, this.default_public_exponent);
|
||||||
|
}
|
||||||
|
return this.key;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Returns the pem encoded representation of the private key
|
||||||
|
* If the key doesn't exists a new key will be created
|
||||||
|
* @returns {string} pem encoded representation of the private key WITH header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.getPrivateKey = function () {
|
||||||
|
// Return the private representation of this key.
|
||||||
|
return this.getKey().getPrivateKey();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Returns the pem encoded representation of the private key
|
||||||
|
* If the key doesn't exists a new key will be created
|
||||||
|
* @returns {string} pem encoded representation of the private key WITHOUT header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.getPrivateKeyB64 = function () {
|
||||||
|
// Return the private representation of this key.
|
||||||
|
return this.getKey().getPrivateBaseKeyB64();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Returns the pem encoded representation of the public key
|
||||||
|
* If the key doesn't exists a new key will be created
|
||||||
|
* @returns {string} pem encoded representation of the public key WITH header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.getPublicKey = function () {
|
||||||
|
// Return the private representation of this key.
|
||||||
|
return this.getKey().getPublicKey();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Returns the pem encoded representation of the public key
|
||||||
|
* If the key doesn't exists a new key will be created
|
||||||
|
* @returns {string} pem encoded representation of the public key WITHOUT header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncrypt.prototype.getPublicKeyB64 = function () {
|
||||||
|
// Return the private representation of this key.
|
||||||
|
return this.getKey().getPublicBaseKeyB64();
|
||||||
|
};
|
||||||
|
JSEncrypt.version = version.version;
|
||||||
|
return JSEncrypt;
|
||||||
|
}());
|
||||||
|
export { JSEncrypt };
|
||||||
@ -0,0 +1,315 @@
|
|||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
if (typeof b !== "function" && b !== null)
|
||||||
|
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
import { hex2b64 } from "./lib/jsbn/base64";
|
||||||
|
import { Hex } from "./lib/asn1js/hex";
|
||||||
|
import { Base64 } from "./lib/asn1js/base64";
|
||||||
|
import { ASN1 } from "./lib/asn1js/asn1";
|
||||||
|
import { RSAKey } from "./lib/jsbn/rsa";
|
||||||
|
import { parseBigInt } from "./lib/jsbn/jsbn";
|
||||||
|
import { KJUR } from "./lib/jsrsasign/asn1-1.0";
|
||||||
|
/**
|
||||||
|
* Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
|
||||||
|
* This object is just a decorator for parsing the key parameter
|
||||||
|
* @param {string|Object} key - The key in string format, or an object containing
|
||||||
|
* the parameters needed to build a RSAKey object.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
var JSEncryptRSAKey = /** @class */ (function (_super) {
|
||||||
|
__extends(JSEncryptRSAKey, _super);
|
||||||
|
function JSEncryptRSAKey(key) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
// Call the super constructor.
|
||||||
|
// RSAKey.call(this);
|
||||||
|
// If a key key was provided.
|
||||||
|
if (key) {
|
||||||
|
// If this is a string...
|
||||||
|
if (typeof key === "string") {
|
||||||
|
_this.parseKey(key);
|
||||||
|
}
|
||||||
|
else if (JSEncryptRSAKey.hasPrivateKeyProperty(key) ||
|
||||||
|
JSEncryptRSAKey.hasPublicKeyProperty(key)) {
|
||||||
|
// Set the values for the key.
|
||||||
|
_this.parsePropertiesFrom(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Method to parse a pem encoded string containing both a public or private key.
|
||||||
|
* The method will translate the pem encoded string in a der encoded string and
|
||||||
|
* will parse private key and public key parameters. This method accepts public key
|
||||||
|
* in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
|
||||||
|
*
|
||||||
|
* @todo Check how many rsa formats use the same format of pkcs #1.
|
||||||
|
*
|
||||||
|
* The format is defined as:
|
||||||
|
* PublicKeyInfo ::= SEQUENCE {
|
||||||
|
* algorithm AlgorithmIdentifier,
|
||||||
|
* PublicKey BIT STRING
|
||||||
|
* }
|
||||||
|
* Where AlgorithmIdentifier is:
|
||||||
|
* AlgorithmIdentifier ::= SEQUENCE {
|
||||||
|
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
|
||||||
|
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
|
||||||
|
* }
|
||||||
|
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
|
||||||
|
* RSAPublicKey ::= SEQUENCE {
|
||||||
|
* modulus INTEGER, -- n
|
||||||
|
* publicExponent INTEGER -- e
|
||||||
|
* }
|
||||||
|
* it's possible to examine the structure of the keys obtained from openssl using
|
||||||
|
* an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
|
||||||
|
* @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.parseKey = function (pem) {
|
||||||
|
try {
|
||||||
|
var modulus = 0;
|
||||||
|
var public_exponent = 0;
|
||||||
|
var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
|
||||||
|
var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
|
||||||
|
var asn1 = ASN1.decode(der);
|
||||||
|
// Fixes a bug with OpenSSL 1.0+ private keys
|
||||||
|
if (asn1.sub.length === 3) {
|
||||||
|
asn1 = asn1.sub[2].sub[0];
|
||||||
|
}
|
||||||
|
if (asn1.sub.length === 9) {
|
||||||
|
// Parse the private key.
|
||||||
|
modulus = asn1.sub[1].getHexStringValue(); // bigint
|
||||||
|
this.n = parseBigInt(modulus, 16);
|
||||||
|
public_exponent = asn1.sub[2].getHexStringValue(); // int
|
||||||
|
this.e = parseInt(public_exponent, 16);
|
||||||
|
var private_exponent = asn1.sub[3].getHexStringValue(); // bigint
|
||||||
|
this.d = parseBigInt(private_exponent, 16);
|
||||||
|
var prime1 = asn1.sub[4].getHexStringValue(); // bigint
|
||||||
|
this.p = parseBigInt(prime1, 16);
|
||||||
|
var prime2 = asn1.sub[5].getHexStringValue(); // bigint
|
||||||
|
this.q = parseBigInt(prime2, 16);
|
||||||
|
var exponent1 = asn1.sub[6].getHexStringValue(); // bigint
|
||||||
|
this.dmp1 = parseBigInt(exponent1, 16);
|
||||||
|
var exponent2 = asn1.sub[7].getHexStringValue(); // bigint
|
||||||
|
this.dmq1 = parseBigInt(exponent2, 16);
|
||||||
|
var coefficient = asn1.sub[8].getHexStringValue(); // bigint
|
||||||
|
this.coeff = parseBigInt(coefficient, 16);
|
||||||
|
}
|
||||||
|
else if (asn1.sub.length === 2) {
|
||||||
|
// Parse the public key.
|
||||||
|
var bit_string = asn1.sub[1];
|
||||||
|
var sequence = bit_string.sub[0];
|
||||||
|
modulus = sequence.sub[0].getHexStringValue();
|
||||||
|
this.n = parseBigInt(modulus, 16);
|
||||||
|
public_exponent = sequence.sub[1].getHexStringValue();
|
||||||
|
this.e = parseInt(public_exponent, 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Translate rsa parameters in a hex encoded string representing the rsa key.
|
||||||
|
*
|
||||||
|
* The translation follow the ASN.1 notation :
|
||||||
|
* RSAPrivateKey ::= SEQUENCE {
|
||||||
|
* version Version,
|
||||||
|
* modulus INTEGER, -- n
|
||||||
|
* publicExponent INTEGER, -- e
|
||||||
|
* privateExponent INTEGER, -- d
|
||||||
|
* prime1 INTEGER, -- p
|
||||||
|
* prime2 INTEGER, -- q
|
||||||
|
* exponent1 INTEGER, -- d mod (p1)
|
||||||
|
* exponent2 INTEGER, -- d mod (q-1)
|
||||||
|
* coefficient INTEGER, -- (inverse of q) mod p
|
||||||
|
* }
|
||||||
|
* @returns {string} DER Encoded String representing the rsa private key
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPrivateBaseKey = function () {
|
||||||
|
var options = {
|
||||||
|
array: [
|
||||||
|
new KJUR.asn1.DERInteger({ int: 0 }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
||||||
|
new KJUR.asn1.DERInteger({ int: this.e }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.d }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.p }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.q }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.dmp1 }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.dmq1 }),
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.coeff })
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var seq = new KJUR.asn1.DERSequence(options);
|
||||||
|
return seq.getEncodedHex();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* base64 (pem) encoded version of the DER encoded representation
|
||||||
|
* @returns {string} pem encoded representation without header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPrivateBaseKeyB64 = function () {
|
||||||
|
return hex2b64(this.getPrivateBaseKey());
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Translate rsa parameters in a hex encoded string representing the rsa public key.
|
||||||
|
* The representation follow the ASN.1 notation :
|
||||||
|
* PublicKeyInfo ::= SEQUENCE {
|
||||||
|
* algorithm AlgorithmIdentifier,
|
||||||
|
* PublicKey BIT STRING
|
||||||
|
* }
|
||||||
|
* Where AlgorithmIdentifier is:
|
||||||
|
* AlgorithmIdentifier ::= SEQUENCE {
|
||||||
|
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
|
||||||
|
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
|
||||||
|
* }
|
||||||
|
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
|
||||||
|
* RSAPublicKey ::= SEQUENCE {
|
||||||
|
* modulus INTEGER, -- n
|
||||||
|
* publicExponent INTEGER -- e
|
||||||
|
* }
|
||||||
|
* @returns {string} DER Encoded String representing the rsa public key
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPublicBaseKey = function () {
|
||||||
|
var first_sequence = new KJUR.asn1.DERSequence({
|
||||||
|
array: [
|
||||||
|
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }),
|
||||||
|
new KJUR.asn1.DERNull()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
var second_sequence = new KJUR.asn1.DERSequence({
|
||||||
|
array: [
|
||||||
|
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
||||||
|
new KJUR.asn1.DERInteger({ int: this.e })
|
||||||
|
]
|
||||||
|
});
|
||||||
|
var bit_string = new KJUR.asn1.DERBitString({
|
||||||
|
hex: "00" + second_sequence.getEncodedHex()
|
||||||
|
});
|
||||||
|
var seq = new KJUR.asn1.DERSequence({
|
||||||
|
array: [
|
||||||
|
first_sequence,
|
||||||
|
bit_string
|
||||||
|
]
|
||||||
|
});
|
||||||
|
return seq.getEncodedHex();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* base64 (pem) encoded version of the DER encoded representation
|
||||||
|
* @returns {string} pem encoded representation without header and footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPublicBaseKeyB64 = function () {
|
||||||
|
return hex2b64(this.getPublicBaseKey());
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* wrap the string in block of width chars. The default value for rsa keys is 64
|
||||||
|
* characters.
|
||||||
|
* @param {string} str the pem encoded string without header and footer
|
||||||
|
* @param {Number} [width=64] - the length the string has to be wrapped at
|
||||||
|
* @returns {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.wordwrap = function (str, width) {
|
||||||
|
width = width || 64;
|
||||||
|
if (!str) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
var regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})";
|
||||||
|
return str.match(RegExp(regex, "g")).join("\n");
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Retrieve the pem encoded private key
|
||||||
|
* @returns {string} the pem encoded private key with header/footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPrivateKey = function () {
|
||||||
|
var key = "-----BEGIN RSA PRIVATE KEY-----\n";
|
||||||
|
key += JSEncryptRSAKey.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
|
||||||
|
key += "-----END RSA PRIVATE KEY-----";
|
||||||
|
return key;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Retrieve the pem encoded public key
|
||||||
|
* @returns {string} the pem encoded public key with header/footer
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.getPublicKey = function () {
|
||||||
|
var key = "-----BEGIN PUBLIC KEY-----\n";
|
||||||
|
key += JSEncryptRSAKey.wordwrap(this.getPublicBaseKeyB64()) + "\n";
|
||||||
|
key += "-----END PUBLIC KEY-----";
|
||||||
|
return key;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Check if the object contains the necessary parameters to populate the rsa modulus
|
||||||
|
* and public exponent parameters.
|
||||||
|
* @param {Object} [obj={}] - An object that may contain the two public key
|
||||||
|
* parameters
|
||||||
|
* @returns {boolean} true if the object contains both the modulus and the public exponent
|
||||||
|
* properties (n and e)
|
||||||
|
* @todo check for types of n and e. N should be a parseable bigInt object, E should
|
||||||
|
* be a parseable integer number
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.hasPublicKeyProperty = function (obj) {
|
||||||
|
obj = obj || {};
|
||||||
|
return (obj.hasOwnProperty("n") &&
|
||||||
|
obj.hasOwnProperty("e"));
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Check if the object contains ALL the parameters of an RSA key.
|
||||||
|
* @param {Object} [obj={}] - An object that may contain nine rsa key
|
||||||
|
* parameters
|
||||||
|
* @returns {boolean} true if the object contains all the parameters needed
|
||||||
|
* @todo check for types of the parameters all the parameters but the public exponent
|
||||||
|
* should be parseable bigint objects, the public exponent should be a parseable integer number
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.hasPrivateKeyProperty = function (obj) {
|
||||||
|
obj = obj || {};
|
||||||
|
return (obj.hasOwnProperty("n") &&
|
||||||
|
obj.hasOwnProperty("e") &&
|
||||||
|
obj.hasOwnProperty("d") &&
|
||||||
|
obj.hasOwnProperty("p") &&
|
||||||
|
obj.hasOwnProperty("q") &&
|
||||||
|
obj.hasOwnProperty("dmp1") &&
|
||||||
|
obj.hasOwnProperty("dmq1") &&
|
||||||
|
obj.hasOwnProperty("coeff"));
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Parse the properties of obj in the current rsa object. Obj should AT LEAST
|
||||||
|
* include the modulus and public exponent (n, e) parameters.
|
||||||
|
* @param {Object} obj - the object containing rsa parameters
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSEncryptRSAKey.prototype.parsePropertiesFrom = function (obj) {
|
||||||
|
this.n = obj.n;
|
||||||
|
this.e = obj.e;
|
||||||
|
if (obj.hasOwnProperty("d")) {
|
||||||
|
this.d = obj.d;
|
||||||
|
this.p = obj.p;
|
||||||
|
this.q = obj.q;
|
||||||
|
this.dmp1 = obj.dmp1;
|
||||||
|
this.dmq1 = obj.dmq1;
|
||||||
|
this.coeff = obj.coeff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return JSEncryptRSAKey;
|
||||||
|
}(RSAKey));
|
||||||
|
export { JSEncryptRSAKey };
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import { JSEncrypt } from './JSEncrypt';
|
||||||
|
export { JSEncrypt };
|
||||||
|
export default JSEncrypt;
|
||||||
@ -0,0 +1,565 @@
|
|||||||
|
// ASN.1 JavaScript decoder
|
||||||
|
// Copyright (c) 2008-2014 Lapo Luchini <lapo@lapo.it>
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||||
|
/*global oids */
|
||||||
|
import { Int10 } from "./int10";
|
||||||
|
var ellipsis = "\u2026";
|
||||||
|
var reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
||||||
|
var reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
||||||
|
function stringCut(str, len) {
|
||||||
|
if (str.length > len) {
|
||||||
|
str = str.substring(0, len) + ellipsis;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
var Stream = /** @class */ (function () {
|
||||||
|
function Stream(enc, pos) {
|
||||||
|
this.hexDigits = "0123456789ABCDEF";
|
||||||
|
if (enc instanceof Stream) {
|
||||||
|
this.enc = enc.enc;
|
||||||
|
this.pos = enc.pos;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// enc should be an array or a binary string
|
||||||
|
this.enc = enc;
|
||||||
|
this.pos = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Stream.prototype.get = function (pos) {
|
||||||
|
if (pos === undefined) {
|
||||||
|
pos = this.pos++;
|
||||||
|
}
|
||||||
|
if (pos >= this.enc.length) {
|
||||||
|
throw new Error("Requesting byte offset " + pos + " on a stream of length " + this.enc.length);
|
||||||
|
}
|
||||||
|
return ("string" === typeof this.enc) ? this.enc.charCodeAt(pos) : this.enc[pos];
|
||||||
|
};
|
||||||
|
Stream.prototype.hexByte = function (b) {
|
||||||
|
return this.hexDigits.charAt((b >> 4) & 0xF) + this.hexDigits.charAt(b & 0xF);
|
||||||
|
};
|
||||||
|
Stream.prototype.hexDump = function (start, end, raw) {
|
||||||
|
var s = "";
|
||||||
|
for (var i = start; i < end; ++i) {
|
||||||
|
s += this.hexByte(this.get(i));
|
||||||
|
if (raw !== true) {
|
||||||
|
switch (i & 0xF) {
|
||||||
|
case 0x7:
|
||||||
|
s += " ";
|
||||||
|
break;
|
||||||
|
case 0xF:
|
||||||
|
s += "\n";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
s += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Stream.prototype.isASCII = function (start, end) {
|
||||||
|
for (var i = start; i < end; ++i) {
|
||||||
|
var c = this.get(i);
|
||||||
|
if (c < 32 || c > 176) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseStringISO = function (start, end) {
|
||||||
|
var s = "";
|
||||||
|
for (var i = start; i < end; ++i) {
|
||||||
|
s += String.fromCharCode(this.get(i));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseStringUTF = function (start, end) {
|
||||||
|
var s = "";
|
||||||
|
for (var i = start; i < end;) {
|
||||||
|
var c = this.get(i++);
|
||||||
|
if (c < 128) {
|
||||||
|
s += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if ((c > 191) && (c < 224)) {
|
||||||
|
s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseStringBMP = function (start, end) {
|
||||||
|
var str = "";
|
||||||
|
var hi;
|
||||||
|
var lo;
|
||||||
|
for (var i = start; i < end;) {
|
||||||
|
hi = this.get(i++);
|
||||||
|
lo = this.get(i++);
|
||||||
|
str += String.fromCharCode((hi << 8) | lo);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseTime = function (start, end, shortYear) {
|
||||||
|
var s = this.parseStringISO(start, end);
|
||||||
|
var m = (shortYear ? reTimeS : reTimeL).exec(s);
|
||||||
|
if (!m) {
|
||||||
|
return "Unrecognized time: " + s;
|
||||||
|
}
|
||||||
|
if (shortYear) {
|
||||||
|
// to avoid querying the timer, use the fixed range [1970, 2069]
|
||||||
|
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
|
||||||
|
m[1] = +m[1];
|
||||||
|
m[1] += (+m[1] < 70) ? 2000 : 1900;
|
||||||
|
}
|
||||||
|
s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4];
|
||||||
|
if (m[5]) {
|
||||||
|
s += ":" + m[5];
|
||||||
|
if (m[6]) {
|
||||||
|
s += ":" + m[6];
|
||||||
|
if (m[7]) {
|
||||||
|
s += "." + m[7];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m[8]) {
|
||||||
|
s += " UTC";
|
||||||
|
if (m[8] != "Z") {
|
||||||
|
s += m[8];
|
||||||
|
if (m[9]) {
|
||||||
|
s += ":" + m[9];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseInteger = function (start, end) {
|
||||||
|
var v = this.get(start);
|
||||||
|
var neg = (v > 127);
|
||||||
|
var pad = neg ? 255 : 0;
|
||||||
|
var len;
|
||||||
|
var s = "";
|
||||||
|
// skip unuseful bits (not allowed in DER)
|
||||||
|
while (v == pad && ++start < end) {
|
||||||
|
v = this.get(start);
|
||||||
|
}
|
||||||
|
len = end - start;
|
||||||
|
if (len === 0) {
|
||||||
|
return neg ? -1 : 0;
|
||||||
|
}
|
||||||
|
// show bit length of huge integers
|
||||||
|
if (len > 4) {
|
||||||
|
s = v;
|
||||||
|
len <<= 3;
|
||||||
|
while (((+s ^ pad) & 0x80) == 0) {
|
||||||
|
s = +s << 1;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
s = "(" + len + " bit)\n";
|
||||||
|
}
|
||||||
|
// decode the integer
|
||||||
|
if (neg) {
|
||||||
|
v = v - 256;
|
||||||
|
}
|
||||||
|
var n = new Int10(v);
|
||||||
|
for (var i = start + 1; i < end; ++i) {
|
||||||
|
n.mulAdd(256, this.get(i));
|
||||||
|
}
|
||||||
|
return s + n.toString();
|
||||||
|
};
|
||||||
|
Stream.prototype.parseBitString = function (start, end, maxLength) {
|
||||||
|
var unusedBit = this.get(start);
|
||||||
|
var lenBit = ((end - start - 1) << 3) - unusedBit;
|
||||||
|
var intro = "(" + lenBit + " bit)\n";
|
||||||
|
var s = "";
|
||||||
|
for (var i = start + 1; i < end; ++i) {
|
||||||
|
var b = this.get(i);
|
||||||
|
var skip = (i == end - 1) ? unusedBit : 0;
|
||||||
|
for (var j = 7; j >= skip; --j) {
|
||||||
|
s += (b >> j) & 1 ? "1" : "0";
|
||||||
|
}
|
||||||
|
if (s.length > maxLength) {
|
||||||
|
return intro + stringCut(s, maxLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return intro + s;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseOctetString = function (start, end, maxLength) {
|
||||||
|
if (this.isASCII(start, end)) {
|
||||||
|
return stringCut(this.parseStringISO(start, end), maxLength);
|
||||||
|
}
|
||||||
|
var len = end - start;
|
||||||
|
var s = "(" + len + " byte)\n";
|
||||||
|
maxLength /= 2; // we work in bytes
|
||||||
|
if (len > maxLength) {
|
||||||
|
end = start + maxLength;
|
||||||
|
}
|
||||||
|
for (var i = start; i < end; ++i) {
|
||||||
|
s += this.hexByte(this.get(i));
|
||||||
|
}
|
||||||
|
if (len > maxLength) {
|
||||||
|
s += ellipsis;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Stream.prototype.parseOID = function (start, end, maxLength) {
|
||||||
|
var s = "";
|
||||||
|
var n = new Int10();
|
||||||
|
var bits = 0;
|
||||||
|
for (var i = start; i < end; ++i) {
|
||||||
|
var v = this.get(i);
|
||||||
|
n.mulAdd(128, v & 0x7F);
|
||||||
|
bits += 7;
|
||||||
|
if (!(v & 0x80)) { // finished
|
||||||
|
if (s === "") {
|
||||||
|
n = n.simplify();
|
||||||
|
if (n instanceof Int10) {
|
||||||
|
n.sub(80);
|
||||||
|
s = "2." + n.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var m = n < 80 ? n < 40 ? 0 : 1 : 2;
|
||||||
|
s = m + "." + (n - m * 40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s += "." + n.toString();
|
||||||
|
}
|
||||||
|
if (s.length > maxLength) {
|
||||||
|
return stringCut(s, maxLength);
|
||||||
|
}
|
||||||
|
n = new Int10();
|
||||||
|
bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bits > 0) {
|
||||||
|
s += ".incomplete";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
return Stream;
|
||||||
|
}());
|
||||||
|
export { Stream };
|
||||||
|
var ASN1 = /** @class */ (function () {
|
||||||
|
function ASN1(stream, header, length, tag, sub) {
|
||||||
|
if (!(tag instanceof ASN1Tag)) {
|
||||||
|
throw new Error("Invalid tag value.");
|
||||||
|
}
|
||||||
|
this.stream = stream;
|
||||||
|
this.header = header;
|
||||||
|
this.length = length;
|
||||||
|
this.tag = tag;
|
||||||
|
this.sub = sub;
|
||||||
|
}
|
||||||
|
ASN1.prototype.typeName = function () {
|
||||||
|
switch (this.tag.tagClass) {
|
||||||
|
case 0: // universal
|
||||||
|
switch (this.tag.tagNumber) {
|
||||||
|
case 0x00:
|
||||||
|
return "EOC";
|
||||||
|
case 0x01:
|
||||||
|
return "BOOLEAN";
|
||||||
|
case 0x02:
|
||||||
|
return "INTEGER";
|
||||||
|
case 0x03:
|
||||||
|
return "BIT_STRING";
|
||||||
|
case 0x04:
|
||||||
|
return "OCTET_STRING";
|
||||||
|
case 0x05:
|
||||||
|
return "NULL";
|
||||||
|
case 0x06:
|
||||||
|
return "OBJECT_IDENTIFIER";
|
||||||
|
case 0x07:
|
||||||
|
return "ObjectDescriptor";
|
||||||
|
case 0x08:
|
||||||
|
return "EXTERNAL";
|
||||||
|
case 0x09:
|
||||||
|
return "REAL";
|
||||||
|
case 0x0A:
|
||||||
|
return "ENUMERATED";
|
||||||
|
case 0x0B:
|
||||||
|
return "EMBEDDED_PDV";
|
||||||
|
case 0x0C:
|
||||||
|
return "UTF8String";
|
||||||
|
case 0x10:
|
||||||
|
return "SEQUENCE";
|
||||||
|
case 0x11:
|
||||||
|
return "SET";
|
||||||
|
case 0x12:
|
||||||
|
return "NumericString";
|
||||||
|
case 0x13:
|
||||||
|
return "PrintableString"; // ASCII subset
|
||||||
|
case 0x14:
|
||||||
|
return "TeletexString"; // aka T61String
|
||||||
|
case 0x15:
|
||||||
|
return "VideotexString";
|
||||||
|
case 0x16:
|
||||||
|
return "IA5String"; // ASCII
|
||||||
|
case 0x17:
|
||||||
|
return "UTCTime";
|
||||||
|
case 0x18:
|
||||||
|
return "GeneralizedTime";
|
||||||
|
case 0x19:
|
||||||
|
return "GraphicString";
|
||||||
|
case 0x1A:
|
||||||
|
return "VisibleString"; // ASCII subset
|
||||||
|
case 0x1B:
|
||||||
|
return "GeneralString";
|
||||||
|
case 0x1C:
|
||||||
|
return "UniversalString";
|
||||||
|
case 0x1E:
|
||||||
|
return "BMPString";
|
||||||
|
}
|
||||||
|
return "Universal_" + this.tag.tagNumber.toString();
|
||||||
|
case 1:
|
||||||
|
return "Application_" + this.tag.tagNumber.toString();
|
||||||
|
case 2:
|
||||||
|
return "[" + this.tag.tagNumber.toString() + "]"; // Context
|
||||||
|
case 3:
|
||||||
|
return "Private_" + this.tag.tagNumber.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ASN1.prototype.content = function (maxLength) {
|
||||||
|
if (this.tag === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (maxLength === undefined) {
|
||||||
|
maxLength = Infinity;
|
||||||
|
}
|
||||||
|
var content = this.posContent();
|
||||||
|
var len = Math.abs(this.length);
|
||||||
|
if (!this.tag.isUniversal()) {
|
||||||
|
if (this.sub !== null) {
|
||||||
|
return "(" + this.sub.length + " elem)";
|
||||||
|
}
|
||||||
|
return this.stream.parseOctetString(content, content + len, maxLength);
|
||||||
|
}
|
||||||
|
switch (this.tag.tagNumber) {
|
||||||
|
case 0x01: // BOOLEAN
|
||||||
|
return (this.stream.get(content) === 0) ? "false" : "true";
|
||||||
|
case 0x02: // INTEGER
|
||||||
|
return this.stream.parseInteger(content, content + len);
|
||||||
|
case 0x03: // BIT_STRING
|
||||||
|
return this.sub ? "(" + this.sub.length + " elem)" :
|
||||||
|
this.stream.parseBitString(content, content + len, maxLength);
|
||||||
|
case 0x04: // OCTET_STRING
|
||||||
|
return this.sub ? "(" + this.sub.length + " elem)" :
|
||||||
|
this.stream.parseOctetString(content, content + len, maxLength);
|
||||||
|
// case 0x05: // NULL
|
||||||
|
case 0x06: // OBJECT_IDENTIFIER
|
||||||
|
return this.stream.parseOID(content, content + len, maxLength);
|
||||||
|
// case 0x07: // ObjectDescriptor
|
||||||
|
// case 0x08: // EXTERNAL
|
||||||
|
// case 0x09: // REAL
|
||||||
|
// case 0x0A: // ENUMERATED
|
||||||
|
// case 0x0B: // EMBEDDED_PDV
|
||||||
|
case 0x10: // SEQUENCE
|
||||||
|
case 0x11: // SET
|
||||||
|
if (this.sub !== null) {
|
||||||
|
return "(" + this.sub.length + " elem)";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "(no elem)";
|
||||||
|
}
|
||||||
|
case 0x0C: // UTF8String
|
||||||
|
return stringCut(this.stream.parseStringUTF(content, content + len), maxLength);
|
||||||
|
case 0x12: // NumericString
|
||||||
|
case 0x13: // PrintableString
|
||||||
|
case 0x14: // TeletexString
|
||||||
|
case 0x15: // VideotexString
|
||||||
|
case 0x16: // IA5String
|
||||||
|
// case 0x19: // GraphicString
|
||||||
|
case 0x1A: // VisibleString
|
||||||
|
// case 0x1B: // GeneralString
|
||||||
|
// case 0x1C: // UniversalString
|
||||||
|
return stringCut(this.stream.parseStringISO(content, content + len), maxLength);
|
||||||
|
case 0x1E: // BMPString
|
||||||
|
return stringCut(this.stream.parseStringBMP(content, content + len), maxLength);
|
||||||
|
case 0x17: // UTCTime
|
||||||
|
case 0x18: // GeneralizedTime
|
||||||
|
return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
ASN1.prototype.toString = function () {
|
||||||
|
return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.sub === null) ? "null" : this.sub.length) + "]";
|
||||||
|
};
|
||||||
|
ASN1.prototype.toPrettyString = function (indent) {
|
||||||
|
if (indent === undefined) {
|
||||||
|
indent = "";
|
||||||
|
}
|
||||||
|
var s = indent + this.typeName() + " @" + this.stream.pos;
|
||||||
|
if (this.length >= 0) {
|
||||||
|
s += "+";
|
||||||
|
}
|
||||||
|
s += this.length;
|
||||||
|
if (this.tag.tagConstructed) {
|
||||||
|
s += " (constructed)";
|
||||||
|
}
|
||||||
|
else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.sub !== null)) {
|
||||||
|
s += " (encapsulates)";
|
||||||
|
}
|
||||||
|
s += "\n";
|
||||||
|
if (this.sub !== null) {
|
||||||
|
indent += " ";
|
||||||
|
for (var i = 0, max = this.sub.length; i < max; ++i) {
|
||||||
|
s += this.sub[i].toPrettyString(indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
ASN1.prototype.posStart = function () {
|
||||||
|
return this.stream.pos;
|
||||||
|
};
|
||||||
|
ASN1.prototype.posContent = function () {
|
||||||
|
return this.stream.pos + this.header;
|
||||||
|
};
|
||||||
|
ASN1.prototype.posEnd = function () {
|
||||||
|
return this.stream.pos + this.header + Math.abs(this.length);
|
||||||
|
};
|
||||||
|
ASN1.prototype.toHexString = function () {
|
||||||
|
return this.stream.hexDump(this.posStart(), this.posEnd(), true);
|
||||||
|
};
|
||||||
|
ASN1.decodeLength = function (stream) {
|
||||||
|
var buf = stream.get();
|
||||||
|
var len = buf & 0x7F;
|
||||||
|
if (len == buf) {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
// no reason to use Int10, as it would be a huge buffer anyways
|
||||||
|
if (len > 6) {
|
||||||
|
throw new Error("Length over 48 bits not supported at position " + (stream.pos - 1));
|
||||||
|
}
|
||||||
|
if (len === 0) {
|
||||||
|
return null;
|
||||||
|
} // undefined
|
||||||
|
buf = 0;
|
||||||
|
for (var i = 0; i < len; ++i) {
|
||||||
|
buf = (buf * 256) + stream.get();
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Retrieve the hexadecimal value (as a string) of the current ASN.1 element
|
||||||
|
* @returns {string}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
ASN1.prototype.getHexStringValue = function () {
|
||||||
|
var hexString = this.toHexString();
|
||||||
|
var offset = this.header * 2;
|
||||||
|
var length = this.length * 2;
|
||||||
|
return hexString.substr(offset, length);
|
||||||
|
};
|
||||||
|
ASN1.decode = function (str) {
|
||||||
|
var stream;
|
||||||
|
if (!(str instanceof Stream)) {
|
||||||
|
stream = new Stream(str, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream = str;
|
||||||
|
}
|
||||||
|
var streamStart = new Stream(stream);
|
||||||
|
var tag = new ASN1Tag(stream);
|
||||||
|
var len = ASN1.decodeLength(stream);
|
||||||
|
var start = stream.pos;
|
||||||
|
var header = start - streamStart.pos;
|
||||||
|
var sub = null;
|
||||||
|
var getSub = function () {
|
||||||
|
var ret = [];
|
||||||
|
if (len !== null) {
|
||||||
|
// definite length
|
||||||
|
var end = start + len;
|
||||||
|
while (stream.pos < end) {
|
||||||
|
ret[ret.length] = ASN1.decode(stream);
|
||||||
|
}
|
||||||
|
if (stream.pos != end) {
|
||||||
|
throw new Error("Content size is not correct for container starting at offset " + start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// undefined length
|
||||||
|
try {
|
||||||
|
for (;;) {
|
||||||
|
var s = ASN1.decode(stream);
|
||||||
|
if (s.tag.isEOC()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret[ret.length] = s;
|
||||||
|
}
|
||||||
|
len = start - stream.pos; // undefined lengths are represented as negative values
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error("Exception while decoding undefined length content: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
if (tag.tagConstructed) {
|
||||||
|
// must have valid content
|
||||||
|
sub = getSub();
|
||||||
|
}
|
||||||
|
else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) {
|
||||||
|
// sometimes BitString and OctetString are used to encapsulate ASN.1
|
||||||
|
try {
|
||||||
|
if (tag.tagNumber == 0x03) {
|
||||||
|
if (stream.get() != 0) {
|
||||||
|
throw new Error("BIT STRINGs with unused bits cannot encapsulate.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sub = getSub();
|
||||||
|
for (var i = 0; i < sub.length; ++i) {
|
||||||
|
if (sub[i].tag.isEOC()) {
|
||||||
|
throw new Error("EOC is not supposed to be actual content.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// but silently ignore when they don't
|
||||||
|
sub = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sub === null) {
|
||||||
|
if (len === null) {
|
||||||
|
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start);
|
||||||
|
}
|
||||||
|
stream.pos = start + Math.abs(len);
|
||||||
|
}
|
||||||
|
return new ASN1(streamStart, header, len, tag, sub);
|
||||||
|
};
|
||||||
|
return ASN1;
|
||||||
|
}());
|
||||||
|
export { ASN1 };
|
||||||
|
var ASN1Tag = /** @class */ (function () {
|
||||||
|
function ASN1Tag(stream) {
|
||||||
|
var buf = stream.get();
|
||||||
|
this.tagClass = buf >> 6;
|
||||||
|
this.tagConstructed = ((buf & 0x20) !== 0);
|
||||||
|
this.tagNumber = buf & 0x1F;
|
||||||
|
if (this.tagNumber == 0x1F) { // long tag
|
||||||
|
var n = new Int10();
|
||||||
|
do {
|
||||||
|
buf = stream.get();
|
||||||
|
n.mulAdd(128, buf & 0x7F);
|
||||||
|
} while (buf & 0x80);
|
||||||
|
this.tagNumber = n.simplify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASN1Tag.prototype.isUniversal = function () {
|
||||||
|
return this.tagClass === 0x00;
|
||||||
|
};
|
||||||
|
ASN1Tag.prototype.isEOC = function () {
|
||||||
|
return this.tagClass === 0x00 && this.tagNumber === 0x00;
|
||||||
|
};
|
||||||
|
return ASN1Tag;
|
||||||
|
}());
|
||||||
|
export { ASN1Tag };
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
// Base64 JavaScript decoder
|
||||||
|
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||||
|
var decoder;
|
||||||
|
export var Base64 = {
|
||||||
|
decode: function (a) {
|
||||||
|
var i;
|
||||||
|
if (decoder === undefined) {
|
||||||
|
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
var ignore = "= \f\n\r\t\u00A0\u2028\u2029";
|
||||||
|
decoder = Object.create(null);
|
||||||
|
for (i = 0; i < 64; ++i) {
|
||||||
|
decoder[b64.charAt(i)] = i;
|
||||||
|
}
|
||||||
|
decoder['-'] = 62; //+
|
||||||
|
decoder['_'] = 63; //-
|
||||||
|
for (i = 0; i < ignore.length; ++i) {
|
||||||
|
decoder[ignore.charAt(i)] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var out = [];
|
||||||
|
var bits = 0;
|
||||||
|
var char_count = 0;
|
||||||
|
for (i = 0; i < a.length; ++i) {
|
||||||
|
var c = a.charAt(i);
|
||||||
|
if (c == "=") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = decoder[c];
|
||||||
|
if (c == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c === undefined) {
|
||||||
|
throw new Error("Illegal character at offset " + i);
|
||||||
|
}
|
||||||
|
bits |= c;
|
||||||
|
if (++char_count >= 4) {
|
||||||
|
out[out.length] = (bits >> 16);
|
||||||
|
out[out.length] = (bits >> 8) & 0xFF;
|
||||||
|
out[out.length] = bits & 0xFF;
|
||||||
|
bits = 0;
|
||||||
|
char_count = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bits <<= 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (char_count) {
|
||||||
|
case 1:
|
||||||
|
throw new Error("Base64 encoding incomplete: at least 2 bits missing");
|
||||||
|
case 2:
|
||||||
|
out[out.length] = (bits >> 10);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
out[out.length] = (bits >> 16);
|
||||||
|
out[out.length] = (bits >> 8) & 0xFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,
|
||||||
|
unarmor: function (a) {
|
||||||
|
var m = Base64.re.exec(a);
|
||||||
|
if (m) {
|
||||||
|
if (m[1]) {
|
||||||
|
a = m[1];
|
||||||
|
}
|
||||||
|
else if (m[2]) {
|
||||||
|
a = m[2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("RegExp out of sync");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Base64.decode(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
// Hex JavaScript decoder
|
||||||
|
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||||
|
var decoder;
|
||||||
|
export var Hex = {
|
||||||
|
decode: function (a) {
|
||||||
|
var i;
|
||||||
|
if (decoder === undefined) {
|
||||||
|
var hex = "0123456789ABCDEF";
|
||||||
|
var ignore = " \f\n\r\t\u00A0\u2028\u2029";
|
||||||
|
decoder = {};
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
decoder[hex.charAt(i)] = i;
|
||||||
|
}
|
||||||
|
hex = hex.toLowerCase();
|
||||||
|
for (i = 10; i < 16; ++i) {
|
||||||
|
decoder[hex.charAt(i)] = i;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ignore.length; ++i) {
|
||||||
|
decoder[ignore.charAt(i)] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var out = [];
|
||||||
|
var bits = 0;
|
||||||
|
var char_count = 0;
|
||||||
|
for (i = 0; i < a.length; ++i) {
|
||||||
|
var c = a.charAt(i);
|
||||||
|
if (c == "=") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = decoder[c];
|
||||||
|
if (c == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c === undefined) {
|
||||||
|
throw new Error("Illegal character at offset " + i);
|
||||||
|
}
|
||||||
|
bits |= c;
|
||||||
|
if (++char_count >= 2) {
|
||||||
|
out[out.length] = bits;
|
||||||
|
bits = 0;
|
||||||
|
char_count = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bits <<= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (char_count) {
|
||||||
|
throw new Error("Hex encoding incomplete: 4 bits missing");
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
// Big integer base-10 printing library
|
||||||
|
// Copyright (c) 2014 Lapo Luchini <lapo@lapo.it>
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
||||||
|
var max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256
|
||||||
|
var Int10 = /** @class */ (function () {
|
||||||
|
function Int10(value) {
|
||||||
|
this.buf = [+value || 0];
|
||||||
|
}
|
||||||
|
Int10.prototype.mulAdd = function (m, c) {
|
||||||
|
// assert(m <= 256)
|
||||||
|
var b = this.buf;
|
||||||
|
var l = b.length;
|
||||||
|
var i;
|
||||||
|
var t;
|
||||||
|
for (i = 0; i < l; ++i) {
|
||||||
|
t = b[i] * m + c;
|
||||||
|
if (t < max) {
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = 0 | (t / max);
|
||||||
|
t -= c * max;
|
||||||
|
}
|
||||||
|
b[i] = t;
|
||||||
|
}
|
||||||
|
if (c > 0) {
|
||||||
|
b[i] = c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Int10.prototype.sub = function (c) {
|
||||||
|
// assert(m <= 256)
|
||||||
|
var b = this.buf;
|
||||||
|
var l = b.length;
|
||||||
|
var i;
|
||||||
|
var t;
|
||||||
|
for (i = 0; i < l; ++i) {
|
||||||
|
t = b[i] - c;
|
||||||
|
if (t < 0) {
|
||||||
|
t += max;
|
||||||
|
c = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
b[i] = t;
|
||||||
|
}
|
||||||
|
while (b[b.length - 1] === 0) {
|
||||||
|
b.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Int10.prototype.toString = function (base) {
|
||||||
|
if ((base || 10) != 10) {
|
||||||
|
throw new Error("only base 10 is supported");
|
||||||
|
}
|
||||||
|
var b = this.buf;
|
||||||
|
var s = b[b.length - 1].toString();
|
||||||
|
for (var i = b.length - 2; i >= 0; --i) {
|
||||||
|
s += (max + b[i]).toString().substring(1);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
Int10.prototype.valueOf = function () {
|
||||||
|
var b = this.buf;
|
||||||
|
var v = 0;
|
||||||
|
for (var i = b.length - 1; i >= 0; --i) {
|
||||||
|
v = v * max + b[i];
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
Int10.prototype.simplify = function () {
|
||||||
|
var b = this.buf;
|
||||||
|
return (b.length == 1) ? b[0] : this;
|
||||||
|
};
|
||||||
|
return Int10;
|
||||||
|
}());
|
||||||
|
export { Int10 };
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
|||||||
|
import { int2char } from "./util";
|
||||||
|
var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
var b64pad = "=";
|
||||||
|
export function hex2b64(h) {
|
||||||
|
var i;
|
||||||
|
var c;
|
||||||
|
var ret = "";
|
||||||
|
for (i = 0; i + 3 <= h.length; i += 3) {
|
||||||
|
c = parseInt(h.substring(i, i + 3), 16);
|
||||||
|
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
||||||
|
}
|
||||||
|
if (i + 1 == h.length) {
|
||||||
|
c = parseInt(h.substring(i, i + 1), 16);
|
||||||
|
ret += b64map.charAt(c << 2);
|
||||||
|
}
|
||||||
|
else if (i + 2 == h.length) {
|
||||||
|
c = parseInt(h.substring(i, i + 2), 16);
|
||||||
|
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
||||||
|
}
|
||||||
|
while ((ret.length & 3) > 0) {
|
||||||
|
ret += b64pad;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// convert a base64 string to hex
|
||||||
|
export function b64tohex(s) {
|
||||||
|
var ret = "";
|
||||||
|
var i;
|
||||||
|
var k = 0; // b64 state, 0-3
|
||||||
|
var slop = 0;
|
||||||
|
for (i = 0; i < s.length; ++i) {
|
||||||
|
if (s.charAt(i) == b64pad) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var v = b64map.indexOf(s.charAt(i));
|
||||||
|
if (v < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (k == 0) {
|
||||||
|
ret += int2char(v >> 2);
|
||||||
|
slop = v & 3;
|
||||||
|
k = 1;
|
||||||
|
}
|
||||||
|
else if (k == 1) {
|
||||||
|
ret += int2char((slop << 2) | (v >> 4));
|
||||||
|
slop = v & 0xf;
|
||||||
|
k = 2;
|
||||||
|
}
|
||||||
|
else if (k == 2) {
|
||||||
|
ret += int2char(slop);
|
||||||
|
ret += int2char(v >> 2);
|
||||||
|
slop = v & 3;
|
||||||
|
k = 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret += int2char((slop << 2) | (v >> 4));
|
||||||
|
ret += int2char(v & 0xf);
|
||||||
|
k = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (k == 1) {
|
||||||
|
ret += int2char(slop << 2);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// convert a base64 string to a byte/number array
|
||||||
|
export function b64toBA(s) {
|
||||||
|
// piggyback on b64tohex for now, optimize later
|
||||||
|
var h = b64tohex(s);
|
||||||
|
var i;
|
||||||
|
var a = [];
|
||||||
|
for (i = 0; 2 * i < h.length; ++i) {
|
||||||
|
a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@
|
|||||||
|
// prng4.js - uses Arcfour as a PRNG
|
||||||
|
var Arcfour = /** @class */ (function () {
|
||||||
|
function Arcfour() {
|
||||||
|
this.i = 0;
|
||||||
|
this.j = 0;
|
||||||
|
this.S = [];
|
||||||
|
}
|
||||||
|
// Arcfour.prototype.init = ARC4init;
|
||||||
|
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
||||||
|
Arcfour.prototype.init = function (key) {
|
||||||
|
var i;
|
||||||
|
var j;
|
||||||
|
var 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;
|
||||||
|
};
|
||||||
|
// Arcfour.prototype.next = ARC4next;
|
||||||
|
Arcfour.prototype.next = function () {
|
||||||
|
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];
|
||||||
|
};
|
||||||
|
return Arcfour;
|
||||||
|
}());
|
||||||
|
export { Arcfour };
|
||||||
|
// Plug in your RNG constructor here
|
||||||
|
export 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()
|
||||||
|
export var rng_psize = 256;
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
// Random number generator - requires a PRNG backend, e.g. prng4.js
|
||||||
|
import { prng_newstate, rng_psize } from "./prng4";
|
||||||
|
var rng_state;
|
||||||
|
var rng_pool = null;
|
||||||
|
var rng_pptr;
|
||||||
|
// Initialize the pool with junk if needed.
|
||||||
|
if (rng_pool == null) {
|
||||||
|
rng_pool = [];
|
||||||
|
rng_pptr = 0;
|
||||||
|
var t = void 0;
|
||||||
|
// Use mouse events for entropy, if we do not have enough entropy by the time
|
||||||
|
// we need it, entropy will be generated by Math.random.
|
||||||
|
var count = 0;
|
||||||
|
var onMouseMoveListener = function (ev) {
|
||||||
|
count = count || 0;
|
||||||
|
if (count >= 256 || rng_pptr >= rng_psize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var mouseCoordinates = ev.x + ev.y;
|
||||||
|
rng_pool[rng_pptr++] = mouseCoordinates & 255;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// Sometimes Firefox will deny permission to access event properties for some reason. Ignore.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function rng_get_byte() {
|
||||||
|
if (rng_state == null) {
|
||||||
|
rng_state = prng_newstate();
|
||||||
|
// At this point, we may not have collected enough entropy. If not, fall back to Math.random
|
||||||
|
while (rng_pptr < rng_psize) {
|
||||||
|
var random = Math.floor(65536 * Math.random());
|
||||||
|
rng_pool[rng_pptr++] = random & 255;
|
||||||
|
}
|
||||||
|
rng_state.init(rng_pool);
|
||||||
|
for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) {
|
||||||
|
rng_pool[rng_pptr] = 0;
|
||||||
|
}
|
||||||
|
rng_pptr = 0;
|
||||||
|
}
|
||||||
|
// TODO: allow reseeding after first request
|
||||||
|
return rng_state.next();
|
||||||
|
}
|
||||||
|
var SecureRandom = /** @class */ (function () {
|
||||||
|
function SecureRandom() {
|
||||||
|
}
|
||||||
|
SecureRandom.prototype.nextBytes = function (ba) {
|
||||||
|
for (var i = 0; i < ba.length; ++i) {
|
||||||
|
ba[i] = rng_get_byte();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return SecureRandom;
|
||||||
|
}());
|
||||||
|
export { SecureRandom };
|
||||||
@ -0,0 +1,471 @@
|
|||||||
|
// Depends on jsbn.js and rng.js
|
||||||
|
// Version 1.1: support utf-8 encoding in pkcs1pad2
|
||||||
|
// convert a (hex) string to a bignum object
|
||||||
|
import { BigInteger, nbi, parseBigInt } from "./jsbn";
|
||||||
|
import { SecureRandom } from "./rng";
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
function pkcs1pad1(s, n) {
|
||||||
|
if (n < s.length + 22) {
|
||||||
|
console.error("Message too long for RSA");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var len = n - s.length - 6;
|
||||||
|
var filler = "";
|
||||||
|
for (var f = 0; f < len; f += 2) {
|
||||||
|
filler += "ff";
|
||||||
|
}
|
||||||
|
var m = "0001" + filler + "00" + s;
|
||||||
|
return parseBigInt(m, 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
|
||||||
|
console.error("Message too long for RSA");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var ba = [];
|
||||||
|
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 = [];
|
||||||
|
while (n > 2) { // random non-zero pad
|
||||||
|
x[0] = 0;
|
||||||
|
while (x[0] == 0) {
|
||||||
|
rng.nextBytes(x);
|
||||||
|
}
|
||||||
|
ba[--n] = x[0];
|
||||||
|
}
|
||||||
|
ba[--n] = 2;
|
||||||
|
ba[--n] = 0;
|
||||||
|
return new BigInteger(ba);
|
||||||
|
}
|
||||||
|
// "empty" RSA key constructor
|
||||||
|
var RSAKey = /** @class */ (function () {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
//#region PROTECTED
|
||||||
|
// protected
|
||||||
|
// RSAKey.prototype.doPublic = RSADoPublic;
|
||||||
|
// Perform raw public operation on "x": return x^e (mod n)
|
||||||
|
RSAKey.prototype.doPublic = function (x) {
|
||||||
|
return x.modPowInt(this.e, this.n);
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.doPrivate = RSADoPrivate;
|
||||||
|
// Perform raw private operation on "x": return x^d (mod n)
|
||||||
|
RSAKey.prototype.doPrivate = function (x) {
|
||||||
|
if (this.p == null || this.q == null) {
|
||||||
|
return x.modPow(this.d, this.n);
|
||||||
|
}
|
||||||
|
// TODO: re-calculate any missing CRT params
|
||||||
|
var xp = x.mod(this.p).modPow(this.dmp1, this.p);
|
||||||
|
var xq = x.mod(this.q).modPow(this.dmq1, this.q);
|
||||||
|
while (xp.compareTo(xq) < 0) {
|
||||||
|
xp = xp.add(this.p);
|
||||||
|
}
|
||||||
|
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
|
||||||
|
};
|
||||||
|
//#endregion PROTECTED
|
||||||
|
//#region PUBLIC
|
||||||
|
// RSAKey.prototype.setPublic = RSASetPublic;
|
||||||
|
// Set the public key fields N and e from hex strings
|
||||||
|
RSAKey.prototype.setPublic = function (N, E) {
|
||||||
|
if (N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N, 16);
|
||||||
|
this.e = parseInt(E, 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("Invalid RSA public key");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.encrypt = RSAEncrypt;
|
||||||
|
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
|
||||||
|
RSAKey.prototype.encrypt = function (text) {
|
||||||
|
var maxLength = (this.n.bitLength() + 7) >> 3;
|
||||||
|
var m = pkcs1pad2(text, maxLength);
|
||||||
|
if (m == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var c = this.doPublic(m);
|
||||||
|
if (c == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var h = c.toString(16);
|
||||||
|
var length = h.length;
|
||||||
|
// fix zero before result
|
||||||
|
for (var i = 0; i < maxLength * 2 - length; i++) {
|
||||||
|
h = "0" + h;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.setPrivate = RSASetPrivate;
|
||||||
|
// Set the private key fields N, e, and d from hex strings
|
||||||
|
RSAKey.prototype.setPrivate = function (N, E, D) {
|
||||||
|
if (N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N, 16);
|
||||||
|
this.e = parseInt(E, 16);
|
||||||
|
this.d = parseBigInt(D, 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("Invalid RSA private key");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
|
||||||
|
// Set the private key fields N, e, d and CRT params from hex strings
|
||||||
|
RSAKey.prototype.setPrivateEx = function (N, E, D, P, Q, DP, DQ, C) {
|
||||||
|
if (N != null && E != null && N.length > 0 && E.length > 0) {
|
||||||
|
this.n = parseBigInt(N, 16);
|
||||||
|
this.e = parseInt(E, 16);
|
||||||
|
this.d = parseBigInt(D, 16);
|
||||||
|
this.p = parseBigInt(P, 16);
|
||||||
|
this.q = parseBigInt(Q, 16);
|
||||||
|
this.dmp1 = parseBigInt(DP, 16);
|
||||||
|
this.dmq1 = parseBigInt(DQ, 16);
|
||||||
|
this.coeff = parseBigInt(C, 16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("Invalid RSA private key");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.generate = RSAGenerate;
|
||||||
|
// Generate a new random private key B bits long, using public expt E
|
||||||
|
RSAKey.prototype.generate = function (B, E) {
|
||||||
|
var rng = new SecureRandom();
|
||||||
|
var qs = B >> 1;
|
||||||
|
this.e = parseInt(E, 16);
|
||||||
|
var ee = new BigInteger(E, 16);
|
||||||
|
for (;;) {
|
||||||
|
for (;;) {
|
||||||
|
this.p = new BigInteger(B - qs, 1, rng);
|
||||||
|
if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
this.q = new BigInteger(qs, 1, rng);
|
||||||
|
if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.p.compareTo(this.q) <= 0) {
|
||||||
|
var t = this.p;
|
||||||
|
this.p = this.q;
|
||||||
|
this.q = t;
|
||||||
|
}
|
||||||
|
var p1 = this.p.subtract(BigInteger.ONE);
|
||||||
|
var q1 = this.q.subtract(BigInteger.ONE);
|
||||||
|
var phi = p1.multiply(q1);
|
||||||
|
if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
||||||
|
this.n = this.p.multiply(this.q);
|
||||||
|
this.d = ee.modInverse(phi);
|
||||||
|
this.dmp1 = this.d.mod(p1);
|
||||||
|
this.dmq1 = this.d.mod(q1);
|
||||||
|
this.coeff = this.q.modInverse(this.p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// RSAKey.prototype.decrypt = RSADecrypt;
|
||||||
|
// Return the PKCS#1 RSA decryption of "ctext".
|
||||||
|
// "ctext" is an even-length hex string and the output is a plain string.
|
||||||
|
RSAKey.prototype.decrypt = function (ctext) {
|
||||||
|
var c = parseBigInt(ctext, 16);
|
||||||
|
var m = this.doPrivate(c);
|
||||||
|
if (m == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return pkcs1unpad2(m, (this.n.bitLength() + 7) >> 3);
|
||||||
|
};
|
||||||
|
// Generate a new random private key B bits long, using public expt E
|
||||||
|
RSAKey.prototype.generateAsync = function (B, E, callback) {
|
||||||
|
var rng = new SecureRandom();
|
||||||
|
var qs = B >> 1;
|
||||||
|
this.e = parseInt(E, 16);
|
||||||
|
var ee = new BigInteger(E, 16);
|
||||||
|
var rsa = this;
|
||||||
|
// These functions have non-descript names because they were originally for(;;) loops.
|
||||||
|
// I don't know about cryptography to give them better names than loop1-4.
|
||||||
|
var loop1 = function () {
|
||||||
|
var loop4 = function () {
|
||||||
|
if (rsa.p.compareTo(rsa.q) <= 0) {
|
||||||
|
var t = rsa.p;
|
||||||
|
rsa.p = rsa.q;
|
||||||
|
rsa.q = t;
|
||||||
|
}
|
||||||
|
var p1 = rsa.p.subtract(BigInteger.ONE);
|
||||||
|
var q1 = rsa.q.subtract(BigInteger.ONE);
|
||||||
|
var phi = p1.multiply(q1);
|
||||||
|
if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
||||||
|
rsa.n = rsa.p.multiply(rsa.q);
|
||||||
|
rsa.d = ee.modInverse(phi);
|
||||||
|
rsa.dmp1 = rsa.d.mod(p1);
|
||||||
|
rsa.dmq1 = rsa.d.mod(q1);
|
||||||
|
rsa.coeff = rsa.q.modInverse(rsa.p);
|
||||||
|
setTimeout(function () { callback(); }, 0); // escape
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTimeout(loop1, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var loop3 = function () {
|
||||||
|
rsa.q = nbi();
|
||||||
|
rsa.q.fromNumberAsync(qs, 1, rng, function () {
|
||||||
|
rsa.q.subtract(BigInteger.ONE).gcda(ee, function (r) {
|
||||||
|
if (r.compareTo(BigInteger.ONE) == 0 && rsa.q.isProbablePrime(10)) {
|
||||||
|
setTimeout(loop4, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTimeout(loop3, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var loop2 = function () {
|
||||||
|
rsa.p = nbi();
|
||||||
|
rsa.p.fromNumberAsync(B - qs, 1, rng, function () {
|
||||||
|
rsa.p.subtract(BigInteger.ONE).gcda(ee, function (r) {
|
||||||
|
if (r.compareTo(BigInteger.ONE) == 0 && rsa.p.isProbablePrime(10)) {
|
||||||
|
setTimeout(loop3, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setTimeout(loop2, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
setTimeout(loop2, 0);
|
||||||
|
};
|
||||||
|
setTimeout(loop1, 0);
|
||||||
|
};
|
||||||
|
RSAKey.prototype.sign = function (text, digestMethod, digestName) {
|
||||||
|
var header = getDigestHeader(digestName);
|
||||||
|
var digest = header + digestMethod(text).toString();
|
||||||
|
var m = pkcs1pad1(digest, this.n.bitLength() / 4);
|
||||||
|
if (m == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var c = this.doPrivate(m);
|
||||||
|
if (c == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var h = c.toString(16);
|
||||||
|
if ((h.length & 1) == 0) {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "0" + h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RSAKey.prototype.verify = function (text, signature, digestMethod) {
|
||||||
|
var c = parseBigInt(signature, 16);
|
||||||
|
var m = this.doPublic(c);
|
||||||
|
if (m == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var unpadded = m.toString(16).replace(/^1f+00/, "");
|
||||||
|
var digest = removeDigestHeader(unpadded);
|
||||||
|
return digest == digestMethod(text).toString();
|
||||||
|
};
|
||||||
|
RSAKey.prototype.encryptLong = function (text) {
|
||||||
|
var _this = this;
|
||||||
|
var res = '';
|
||||||
|
var maxLen = ((this.n.bitLength() + 7) >> 3) - 11;
|
||||||
|
var textArr = this.setSplitChn(text, maxLen);
|
||||||
|
textArr.forEach(function (v) {
|
||||||
|
res += _this.encrypt(v);
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
RSAKey.prototype.decryptLong = function (ctext) {
|
||||||
|
var res = '';
|
||||||
|
var maxLen = (this.n.bitLength() + 7) >> 3;
|
||||||
|
var splitMaxLen = maxLen * 2;
|
||||||
|
if (ctext.length > splitMaxLen) {
|
||||||
|
var ctextArr = ctext.match(new RegExp('.{1,' + splitMaxLen + '}', 'g')) || [];
|
||||||
|
var mArr = [];
|
||||||
|
for (var i = 0; i < ctextArr.length; i++) {
|
||||||
|
var c = parseBigInt(ctextArr[i], 16);
|
||||||
|
var m = this.doPrivate(c);
|
||||||
|
if (m == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
mArr.push(m);
|
||||||
|
}
|
||||||
|
res = pkcs1unpad2Long(mArr, maxLen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = this.decrypt(ctext);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
RSAKey.prototype.setSplitChn = function (str, maxLen, res) {
|
||||||
|
if (res === void 0) { res = []; }
|
||||||
|
var arr = str.split('');
|
||||||
|
var len = 0;
|
||||||
|
for (var i = 0; i < arr.length; i++) {
|
||||||
|
var charCode = arr[i].charCodeAt(0);
|
||||||
|
if (charCode <= 0x007f) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
else if (charCode <= 0x07ff) {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
else if (charCode <= 0xffff) {
|
||||||
|
len += 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len += 4;
|
||||||
|
}
|
||||||
|
if (len > maxLen) {
|
||||||
|
var currentStr = str.substring(0, i);
|
||||||
|
res.push(currentStr);
|
||||||
|
return this.setSplitChn(str.substring(i), maxLen, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.push(str);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
return RSAKey;
|
||||||
|
}());
|
||||||
|
export { RSAKey };
|
||||||
|
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
|
||||||
|
function pkcs1unpad2(d, n) {
|
||||||
|
var b = d.toByteArray();
|
||||||
|
var i = 0;
|
||||||
|
while (i < b.length && b[i] == 0) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (b.length - i != n - 1 || b[i] != 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
while (b[i] != 0) {
|
||||||
|
if (++i >= b.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ret = "";
|
||||||
|
while (++i < b.length) {
|
||||||
|
var c = b[i] & 255;
|
||||||
|
if (c < 128) { // utf-8 decode
|
||||||
|
ret += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if ((c > 191) && (c < 224)) {
|
||||||
|
ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
function pkcs1unpad2Long(dArr, n) {
|
||||||
|
var bArr = [];
|
||||||
|
for (var j = 0; j < dArr.length; j++) {
|
||||||
|
var d = dArr[j];
|
||||||
|
var b_1 = d.toByteArray();
|
||||||
|
var i_1 = 0;
|
||||||
|
while (i_1 < b_1.length && b_1[i_1] == 0) {
|
||||||
|
++i_1;
|
||||||
|
}
|
||||||
|
if (b_1.length - i_1 != n - 1 || b_1[i_1] != 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
++i_1;
|
||||||
|
while (b_1[i_1] != 0) {
|
||||||
|
if (++i_1 >= b_1.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bArr = bArr.concat(b_1.slice(i_1 + 1));
|
||||||
|
}
|
||||||
|
var b = bArr;
|
||||||
|
var i = -1;
|
||||||
|
var ret = "";
|
||||||
|
while (++i < b.length) {
|
||||||
|
var c = b[i] & 255;
|
||||||
|
if (c < 128) { // utf-8 decode
|
||||||
|
ret += String.fromCharCode(c);
|
||||||
|
}
|
||||||
|
else if ((c > 191) && (c < 224)) {
|
||||||
|
ret += String.fromCharCode(((c & 31) << 6) | (b[i + 1] & 63));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret += String.fromCharCode(((c & 15) << 12) | ((b[i + 1] & 63) << 6) | (b[i + 2] & 63));
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// https://tools.ietf.org/html/rfc3447#page-43
|
||||||
|
var DIGEST_HEADERS = {
|
||||||
|
md2: "3020300c06082a864886f70d020205000410",
|
||||||
|
md5: "3020300c06082a864886f70d020505000410",
|
||||||
|
sha1: "3021300906052b0e03021a05000414",
|
||||||
|
sha224: "302d300d06096086480165030402040500041c",
|
||||||
|
sha256: "3031300d060960864801650304020105000420",
|
||||||
|
sha384: "3041300d060960864801650304020205000430",
|
||||||
|
sha512: "3051300d060960864801650304020305000440",
|
||||||
|
ripemd160: "3021300906052b2403020105000414"
|
||||||
|
};
|
||||||
|
function getDigestHeader(name) {
|
||||||
|
return DIGEST_HEADERS[name] || "";
|
||||||
|
}
|
||||||
|
function removeDigestHeader(str) {
|
||||||
|
for (var name_1 in DIGEST_HEADERS) {
|
||||||
|
if (DIGEST_HEADERS.hasOwnProperty(name_1)) {
|
||||||
|
var header = DIGEST_HEADERS[name_1];
|
||||||
|
var len = header.length;
|
||||||
|
if (str.substr(0, len) == header) {
|
||||||
|
return str.substr(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
// public
|
||||||
|
// RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
export function int2char(n) {
|
||||||
|
return BI_RM.charAt(n);
|
||||||
|
}
|
||||||
|
//#region BIT_OPERATIONS
|
||||||
|
// (public) this & a
|
||||||
|
export function op_and(x, y) {
|
||||||
|
return x & y;
|
||||||
|
}
|
||||||
|
// (public) this | a
|
||||||
|
export function op_or(x, y) {
|
||||||
|
return x | y;
|
||||||
|
}
|
||||||
|
// (public) this ^ a
|
||||||
|
export function op_xor(x, y) {
|
||||||
|
return x ^ y;
|
||||||
|
}
|
||||||
|
// (public) this & ~a
|
||||||
|
export function op_andnot(x, y) {
|
||||||
|
return x & ~y;
|
||||||
|
}
|
||||||
|
// return index of lowest 1-bit in x, x < 2^31
|
||||||
|
export 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;
|
||||||
|
}
|
||||||
|
// return number of 1 bits in x
|
||||||
|
export function cbit(x) {
|
||||||
|
var r = 0;
|
||||||
|
while (x != 0) {
|
||||||
|
x &= x - 1;
|
||||||
|
++r;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
//#endregion BIT_OPERATIONS
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,69 @@
|
|||||||
|
/*!
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
export 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": "3.2.1"
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"usingComponents": {
|
"usingComponents": {
|
||||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||||
|
"t-toast": "tdesign-miniprogram/toast/toast"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
class simpleReq {
|
||||||
|
constructor() {
|
||||||
|
this._baseUrl = 'https://xzjl-api.windymuse.cn';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET类型的网络请求
|
||||||
|
*/
|
||||||
|
getRequest(url, data) {
|
||||||
|
return this.requestAll(url, data, 'GET')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE类型的网络请求
|
||||||
|
*/
|
||||||
|
deleteRequest(url, data) {
|
||||||
|
return this.requestAll(url, data, 'DELETE')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT类型的网络请求
|
||||||
|
*/
|
||||||
|
putRequest(url, data) {
|
||||||
|
return this.requestAll(url, data, 'PUT')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST类型的网络请求
|
||||||
|
*/
|
||||||
|
postRequest(url, data) {
|
||||||
|
return this.requestAll(url, data, 'POST')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求
|
||||||
|
*/
|
||||||
|
requestAll(url, data, method) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: this._baseUrl + url,
|
||||||
|
data: data,
|
||||||
|
method: method,
|
||||||
|
success: (res => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
//200: 服务端业务处理正常结束
|
||||||
|
resolve(res)
|
||||||
|
wx.showToast({
|
||||||
|
title:'扫描成功',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
//其它错误,提示用户错误信息
|
||||||
|
wx.showToast({
|
||||||
|
title:'扫描失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
fail: (res => {
|
||||||
|
reject(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default simpleReq
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
class request {
|
||||||
|
constructor() {
|
||||||
|
this._baseUrl = 'https://xzjl-api.windymuse.cn';
|
||||||
|
this._token = wx.getStorageSync('token');
|
||||||
|
this._header = {'Authorization': 'Bearer ' + this._token}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET类型的网络请求
|
||||||
|
*/
|
||||||
|
getRequest(url, data, header = this._header) {
|
||||||
|
return this.requestAll(url, data, header, 'GET')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE类型的网络请求
|
||||||
|
*/
|
||||||
|
deleteRequest(url, data, header = this._header) {
|
||||||
|
return this.requestAll(url, data, header, 'DELETE')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT类型的网络请求
|
||||||
|
*/
|
||||||
|
putRequest(url, data, header = this._header) {
|
||||||
|
return this.requestAll(url, data, header, 'PUT')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST类型的网络请求
|
||||||
|
*/
|
||||||
|
postRequest(url, data, header = this._header) {
|
||||||
|
return this.requestAll(url, data, header, 'POST')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求
|
||||||
|
*/
|
||||||
|
requestAll(url, data, header, method) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: this._baseUrl + url,
|
||||||
|
data: data,
|
||||||
|
header: header,
|
||||||
|
method: method,
|
||||||
|
success: (res => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
//200: 服务端业务处理正常结束
|
||||||
|
resolve(res)
|
||||||
|
} else {
|
||||||
|
//其它错误,提示用户错误信息
|
||||||
|
reject(res)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
fail: (res => {
|
||||||
|
reject(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default request
|
||||||
Loading…
Reference in new issue