{@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}
*
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}
*
*
* 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
* @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) {
var ns1 = KJUR.asn1;
var dataWA = CryptoJS.enc.Hex.parse(dataHex);
var dataB64 = CryptoJS.enc.Base64.stringify(dataWA);
var pemBody = dataB64.replace(/(.{64})/g, "$1\r\n");
pemBody = pemBody.replace(/\r\n$/, '');
return "-----BEGIN " + pemHeader + "-----\r\n" +
pemBody +
"\r\n-----END " + pemHeader + "-----\r\n";
};
/**
* 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
*
'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 ns1 = KJUR.asn1;
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:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1)
throw "undefined key: " + key;
if (key == "bool") return new ns1.DERBoolean(param[key]);
if (key == "int") return new ns1.DERInteger(param[key]);
if (key == "bitstr") return new ns1.DERBitString(param[key]);
if (key == "octstr") return new ns1.DEROctetString(param[key]);
if (key == "null") return new ns1.DERNull(param[key]);
if (key == "oid") return new ns1.DERObjectIdentifier(param[key]);
if (key == "utf8str") return new ns1.DERUTF8String(param[key]);
if (key == "numstr") return new ns1.DERNumericString(param[key]);
if (key == "prnstr") return new ns1.DERPrintableString(param[key]);
if (key == "telstr") return new ns1.DERTeletexString(param[key]);
if (key == "ia5str") return new ns1.DERIA5String(param[key]);
if (key == "utctime") return new ns1.DERUTCTime(param[key]);
if (key == "gentime") return new ns1.DERGeneralizedTime(param[key]);
if (key == "seq") {
var paramList = param[key];
var a = [];
for (var i = 0; i < paramList.length; i++) {
var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
a.push(asn1Obj);
}
return new ns1.DERSequence({'array': a});
}
if (key == "set") {
var paramList = param[key];
var a = [];
for (var i = 0; i < paramList.length; i++) {
var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
a.push(asn1Obj);
}
return new ns1.DERSet({'array': a});
}
if (key == "tag") {
var tagParam = param[key];
if (Object.prototype.toString.call(tagParam) === '[object Array]' &&
tagParam.length == 3) {
var obj = ns1.ASN1Util.newObject(tagParam[2]);
return new ns1.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 = ns1.ASN1Util.newObject(tagParam.obj);
return new ns1.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();
};
};
// ********************************************************************
// 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
*/
this.setString = function(newS) {
this.hTLV = null;
this.isModified = true;
this.s = newS;
this.hV = stohex(this.s);
};
/**
* 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;
};
this.formatDate = function(dateObject, type) {
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);
return year + month + day + hour + min + sec + '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
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERBitString = function(params) {
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.
*/
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.
*/
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 false with specified length
* @name newFalseArray
* @memberOf KJUR.asn1.DERBitString
* @function
* @param {Integer} nLength length of array to generate
* @return {array} array of boolean faluse
* @description
* This static method may be useful to initialize boolean array.
*/
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
* @see KJUR.asn1.DERAbstractString - superclass
*/
KJUR.asn1.DEROctetString = function(params) {
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)
*/
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.
*/
this.setValueName = function(oidName) {
if (typeof KJUR.asn1.x509.OID.name2oidList[oidName] != "undefined") {
var oid = KJUR.asn1.x509.OID.name2oidList[oidName];
this.setValueOidString(oid);
} else {
throw "DERObjectIdentifier oidName undefined: " + oidName;
}
};
this.getFreshValueHex = function() {
return this.hV;
};
if (typeof params != "undefined") {
if (typeof params == "string" && params.match(/^[0-2].[0-9.]+$/)) {
this.setValueOidString(params);
} else if (KJUR.asn1.x509.OID.name2oidList[params] !== undefined) {
this.setValueOidString(KJUR.asn1.x509.OID.name2oidList[params]);
} else if (typeof params['oid'] != "undefined") {
this.setValueOidString(params['oid']);
} else if (typeof params['hex'] != "undefined") {
this.setValueHex(params['hex']);
} else if (typeof params['name'] != "undefined") {
this.setValueName(params['name']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, 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
* var d1 = new KJUR.asn1.DERUTCTime();
* d1.setString('130430125959Z');
*
* var d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'});
* var d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))});
* var 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)
*/
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);
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setString(params['str']);
} else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
this.setString(params);
} else if (typeof params['hex'] != "undefined") {
this.setStringHex(params['hex']);
} else if (typeof 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'})
* @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.
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERGeneralizedTime = function(params) {
KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
this.hT = "18";
/**
* 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:
* var o = new DERUTCTime();
* var date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59
* o.setByDate(date);
*/
this.setByDate = function(dateObject) {
this.hTLV = null;
this.isModified = true;
this.date = dateObject;
this.s = this.formatDate(this.date, 'gen');
this.hV = stohex(this.s);
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setString(params['str']);
} else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
this.setString(params);
} else if (typeof params['hex'] != "undefined") {
this.setStringHex(params['hex']);
} else if (typeof params['date'] != "undefined") {
this.setByDate(params['date']);
}
}
};
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
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERSet = function(params) {
KJUR.asn1.DERSet.superclass.constructor.call(this, params);
this.hT = "31";
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());
}
a.sort();
this.hV = a.join('');
return this.hV;
};
};
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);
================================================
FILE: JavaScript/demo/js/asn1hex-1.1.js
================================================
/*! asn1hex-1.1.4.js (c) 2012-2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* asn1hex.js - Hexadecimal represented ASN.1 string library
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/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.1.4 (2013-Oct-02)
* @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
*/
var ASN1HEX = new function() {
/**
* get byte length for ASN.1 L(length) bytes
* @name getByteLengthOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return byte length for ASN.1 L(length) bytes
*/
this.getByteLengthOfL_AtObj = function(s, pos) {
if (s.substring(pos + 2, pos + 3) != '8') return 1;
var i = parseInt(s.substring(pos + 3, pos + 4));
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 getHexOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string for ASN.1 L(length) bytes
*/
this.getHexOfL_AtObj = function(s, pos) {
var len = this.getByteLengthOfL_AtObj(s, pos);
if (len < 1) return '';
return s.substring(pos + 2, pos + 2 + len * 2);
};
// 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
/**
* get integer value of ASN.1 length for ASN.1 data
* @name getIntOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return ASN.1 L(length) integer value
*/
this.getIntOfL_AtObj = function(s, pos) {
var hLength = this.getHexOfL_AtObj(s, pos);
if (hLength == '') return -1;
var bi;
if (parseInt(hLength.substring(0, 1)) < 8) {
bi = new BigInteger(hLength, 16);
} else {
bi = new BigInteger(hLength.substring(2), 16);
}
return bi.intValue();
};
/**
* get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
* @name getStartPosOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
*/
this.getStartPosOfV_AtObj = function(s, pos) {
var l_len = this.getByteLengthOfL_AtObj(s, pos);
if (l_len < 0) return l_len;
return pos + (l_len + 1) * 2;
};
/**
* get hexadecimal string of ASN.1 V(value)
* @name getHexOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 value.
*/
this.getHexOfV_AtObj = function(s, pos) {
var pos1 = this.getStartPosOfV_AtObj(s, pos);
var len = this.getIntOfL_AtObj(s, pos);
return s.substring(pos1, pos1 + len * 2);
};
/**
* get hexadecimal string of ASN.1 TLV at
* @name getHexOfTLV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 TLV.
* @since 1.1
*/
this.getHexOfTLV_AtObj = function(s, pos) {
var hT = s.substr(pos, 2);
var hL = this.getHexOfL_AtObj(s, pos);
var hV = this.getHexOfV_AtObj(s, pos);
return hT + hL + hV;
};
/**
* get next sibling starting index for ASN.1 object string
* @name getPosOfNextSibling_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return next sibling starting index for ASN.1 object string
*/
this.getPosOfNextSibling_AtObj = function(s, pos) {
var pos1 = this.getStartPosOfV_AtObj(s, pos);
var len = this.getIntOfL_AtObj(s, pos);
return pos1 + len * 2;
};
/**
* get array of indexes of child ASN.1 objects
* @name getPosArrayOfChildren_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} start string index of ASN.1 object
* @return {Array of Number} array of indexes for childen of ASN.1 objects
*/
this.getPosArrayOfChildren_AtObj = function(h, pos) {
var a = new Array();
var p0 = this.getStartPosOfV_AtObj(h, pos);
a.push(p0);
var len = this.getIntOfL_AtObj(h, pos);
var p = p0;
var k = 0;
while (1) {
var pNext = this.getPosOfNextSibling_AtObj(h, p);
if (pNext == null || (pNext - p0 >= (len * 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 getNthChildIndex_AtObj
* @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 1.1
*/
this.getNthChildIndex_AtObj = function(h, idx, nth) {
var a = this.getPosArrayOfChildren_AtObj(h, idx);
return a[nth];
};
// ========== decendant methods ==============================
/**
* get string index of nth child object of ASN.1 object refered by h, idx
* @name getDecendantIndexByNthList
* @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
* @return {Number} string index refered by nthList
* @since 1.1
* @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 - [0]
* SEQUENCE - [0, 0]
* IA5STRING 000 - [0, 0, 0]
* UTF8STRING 001 - [0, 0, 1]
* SET - [0, 1]
* IA5STRING 010 - [0, 1, 0]
* UTF8STRING 011 - [0, 1, 1]
*/
this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
if (nthList.length == 0) {
return currentIndex;
}
var firstNth = nthList.shift();
var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
};
/**
* get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
* @name getDecendantHexTLVByNthList
* @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
* @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
* @since 1.1
*/
this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
return this.getHexOfTLV_AtObj(h, idx);
};
/**
* get hexadecimal string of ASN.1 V refered by current index and nth index list.
* @name getDecendantHexVByNthList
* @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
* @return {Number} hexadecimal string of ASN.1 V refered by nthList
* @since 1.1
*/
this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
return this.getHexOfV_AtObj(h, idx);
};
};
/*
* @since asn1hex 1.1.4
*/
ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
var idx = this.getDecendantIndexByNthList(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 this.getHexOfV_AtObj(h, idx);
};
================================================
FILE: JavaScript/demo/js/asn1x509-1.0.js
================================================
/*! asn1x509-1.0.7.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* asn1x509.js - ASN.1 DER encoder classes for X.509 certificate
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name asn1x509-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.0.7 (2013-Oct-11)
* @since jsrsasign 2.1
* @license MIT License
*/
/**
* kjur's class library name space
* // already documented in asn1-1.0.js
* @name KJUR
* @namespace kjur's class library name space
*/
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
/**
* kjur's ASN.1 class library name space
* // already documented in asn1-1.0.js
* @name KJUR.asn1
* @namespace
*/
if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {};
/**
* kjur's ASN.1 class for X.509 certificate library name space
*
*
FEATURES
*
*
easily issue any kind of certificate
*
APIs are very similar to BouncyCastle library ASN.1 classes. So easy to learn.
*
*
*
PROVIDED CLASSES
*
*
{@link KJUR.asn1.x509.Certificate}
*
{@link KJUR.asn1.x509.TBSCertificate}
*
{@link KJUR.asn1.x509.Extension}
*
{@link KJUR.asn1.x509.X500Name}
*
{@link KJUR.asn1.x509.RDN}
*
{@link KJUR.asn1.x509.AttributeTypeAndValue}
*
{@link KJUR.asn1.x509.SubjectPublicKeyInfo}
*
{@link KJUR.asn1.x509.AlgorithmIdentifier}
*
{@link KJUR.asn1.x509.GeneralName}
*
{@link KJUR.asn1.x509.GeneralNames}
*
{@link KJUR.asn1.x509.DistributionPointName}
*
{@link KJUR.asn1.x509.DistributionPoint}
*
{@link KJUR.asn1.x509.CRL}
*
{@link KJUR.asn1.x509.TBSCertList}
*
{@link KJUR.asn1.x509.CRLEntry}
*
{@link KJUR.asn1.x509.OID}
*
*
SUPPORTED EXTENSIONS
*
*
{@link KJUR.asn1.x509.BasicConstraints}
*
{@link KJUR.asn1.x509.KeyUsage}
*
{@link KJUR.asn1.x509.CRLDistributionPoints}
*
{@link KJUR.asn1.x509.ExtKeyUsage}
*
* NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
* @name KJUR.asn1.x509
* @namespace
*/
if (typeof KJUR.asn1.x509 == "undefined" || !KJUR.asn1.x509) KJUR.asn1.x509 = {};
// === BEGIN Certificate ===================================================
/**
* X.509 Certificate class to sign and generate hex encoded certificate
* @name KJUR.asn1.x509.Certificate
* @class X.509 Certificate class to sign and generate hex encoded certificate
* @param {Array} params associative array of parameters (ex. {'tbscertobj': obj, 'prvkeyobj': key})
* @extends KJUR.asn1.ASN1Object
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
prvkeyobj - specify {@link RSAKey}, {@link KJUR.crypto.ECDSA} or {@link KJUR.crypto.DSA} object for CA private key to sign the certificate
*
(DEPRECATED)rsaprvkey - specify {@link RSAKey} object CA private key
*
(DEPRECATED)rsaprvpem - specify PEM string of RSA CA private key
*
* NOTE1: 'params' can be omitted.
* NOTE2: DSA/ECDSA is also supported for CA signging key from asn1x509 1.0.6.
* @example
* var caKey = KEYUTIL.getKey(caKeyPEM); // CA's private key
* var cert = new KJUR.asn1x509.Certificate({'tbscertobj': tbs, 'prvkeyobj': caKey});
* cert.sign(); // issue certificate by CA's private key
* var certPEM = cert.getPEMString();
*
* // Certificate ::= SEQUENCE {
* // tbsCertificate TBSCertificate,
* // signatureAlgorithm AlgorithmIdentifier,
* // signature BIT STRING }
*/
KJUR.asn1.x509.Certificate = function(params) {
KJUR.asn1.x509.Certificate.superclass.constructor.call(this);
var asn1TBSCert = null;
var asn1SignatureAlg = null;
var asn1Sig = null;
var hexSig = null;
var prvKey = null;
var rsaPrvKey = null; // DEPRECATED
/**
* set PKCS#5 encrypted RSA PEM private key as CA key
* @name setRsaPrvKeyByPEMandPass
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @param {String} rsaPEM string of PKCS#5 encrypted RSA PEM private key
* @param {String} passPEM passcode string to decrypt private key
* @since 1.0.1
* @description
*
*
EXAMPLES
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs});
* cert.setRsaPrvKeyByPEMandPass("-----BEGIN RSA PRIVATE..(snip)", "password");
*/
this.setRsaPrvKeyByPEMandPass = function(rsaPEM, passPEM) {
var caKeyHex = PKCS5PKEY.getDecryptedKeyHex(rsaPEM, passPEM);
var caKey = new RSAKey();
caKey.readPrivateKeyFromASN1HexString(caKeyHex);
this.prvKey = caKey;
};
/**
* sign TBSCertificate and set signature value internally
* @name sign
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @description
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
*/
this.sign = function() {
this.asn1SignatureAlg = this.asn1TBSCert.asn1SignatureAlg;
sig = new KJUR.crypto.Signature({'alg': 'SHA1withRSA'});
sig.init(this.prvKey);
sig.updateHex(this.asn1TBSCert.getEncodedHex());
this.hexSig = sig.sign();
this.asn1Sig = new KJUR.asn1.DERBitString({'hex': '00' + this.hexSig});
var seq = new KJUR.asn1.DERSequence({'array': [this.asn1TBSCert,
this.asn1SignatureAlg,
this.asn1Sig]});
this.hTLV = seq.getEncodedHex();
this.isModified = false;
};
this.getEncodedHex = function() {
if (this.isModified == false && this.hTLV != null) return this.hTLV;
throw "not signed yet";
};
/**
* get PEM formatted certificate string after signed
* @name getPEMString
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @return PEM formatted string of certificate
* @description
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
* var sPEM = cert.getPEMString();
*/
this.getPEMString = function() {
var hCert = this.getEncodedHex();
var wCert = CryptoJS.enc.Hex.parse(hCert);
var b64Cert = CryptoJS.enc.Base64.stringify(wCert);
var pemBody = b64Cert.replace(/(.{64})/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n" + pemBody + "\r\n-----END CERTIFICATE-----\r\n";
};
if (typeof params != "undefined") {
if (typeof params['tbscertobj'] != "undefined") {
this.asn1TBSCert = params['tbscertobj'];
}
if (typeof params['prvkeyobj'] != "undefined") {
this.prvKey = params['prvkeyobj'];
} else if (typeof params['rsaprvkey'] != "undefined") {
this.prvKey = params['rsaprvkey'];
} else if ((typeof params['rsaprvpem'] != "undefined") &&
(typeof params['rsaprvpas'] != "undefined")) {
this.setRsaPrvKeyByPEMandPass(params['rsaprvpem'], params['rsaprvpas']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Certificate, KJUR.asn1.ASN1Object);
/**
* ASN.1 TBSCertificate structure class
* @name KJUR.asn1.x509.TBSCertificate
* @class ASN.1 TBSCertificate structure class
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @description
*
*
EXAMPLE
* @example
* var o = new KJUR.asn1.x509.TBSCertificate();
* o.setSerialNumberByParam({'int': 4});
* o.setSignatureAlgByParam({'name': 'SHA1withRSA'});
* o.setIssuerByParam({'str': '/C=US/O=a'});
* o.setNotBeforeByParam({'str': '130504235959Z'});
* o.setNotAfterByParam({'str': '140504235959Z'});
* o.setSubjectByParam({'str': '/C=US/CN=b'});
* o.setSubjectPublicKeyByParam({'rsakey': rsaKey});
* o.appendExtension(new KJUR.asn1.x509.BasicConstraints({'cA':true}));
* o.appendExtension(new KJUR.asn1.x509.KeyUsage({'bin':'11'}));
*/
KJUR.asn1.x509.TBSCertificate = function(params) {
KJUR.asn1.x509.TBSCertificate.superclass.constructor.call(this);
this._initialize = function() {
this.asn1Array = new Array();
this.asn1Version =
new KJUR.asn1.DERTaggedObject({'obj': new KJUR.asn1.DERInteger({'int': 2})});
this.asn1SerialNumber = null;
this.asn1SignatureAlg = null;
this.asn1Issuer = null;
this.asn1NotBefore = null;
this.asn1NotAfter = null;
this.asn1Subject = null;
this.asn1SubjPKey = null;
this.extensionsArray = new Array();
};
/**
* set serial number field by parameter
* @name setSerialNumberByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} intParam DERInteger param
* @description
* @example
* tbsc.setSerialNumberByParam({'int': 3});
*/
this.setSerialNumberByParam = function(intParam) {
this.asn1SerialNumber = new KJUR.asn1.DERInteger(intParam);
};
/**
* set signature algorithm field by parameter
* @name setSignatureAlgByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} algIdParam AlgorithmIdentifier parameter
* @description
* @example
* tbsc.setSignatureAlgByParam({'name': 'SHA1withRSA'});
*/
this.setSignatureAlgByParam = function(algIdParam) {
this.asn1SignatureAlg = new KJUR.asn1.x509.AlgorithmIdentifier(algIdParam);
};
/**
* set issuer name field by parameter
* @name setIssuerByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setIssuerParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setIssuerByParam = function(x500NameParam) {
this.asn1Issuer = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* set notBefore field by parameter
* @name setNotBeforeByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNotBeforeByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNotBeforeByParam = function(timeParam) {
this.asn1NotBefore = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set notAfter field by parameter
* @name setNotAfterByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNotAfterByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNotAfterByParam = function(timeParam) {
this.asn1NotAfter = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set subject name field by parameter
* @name setSubjectByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setSubjectParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setSubjectByParam = function(x500NameParam) {
this.asn1Subject = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* (DEPRECATED) set subject public key info field by RSA key parameter
* @name setSubjectPublicKeyByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} subjPKeyParam SubjectPublicKeyInfo parameter of RSA
* @deprecated
* @description
* @example
* tbsc.setSubjectPublicKeyByParam({'rsakey': pubKey});
* @see KJUR.asn1.x509.SubjectPublicKeyInfo
*/
this.setSubjectPublicKeyByParam = function(subjPKeyParam) {
this.asn1SubjPKey = new KJUR.asn1.x509.SubjectPublicKeyInfo(subjPKeyParam);
};
/**
* set subject public key info by RSA/ECDSA/DSA key parameter
* @name setSubjectPublicKeyByGetKey
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Object} keyParam public key parameter which passed to {@link KEYUTIL.getKey} argument
* @description
* @example
* tbsc.setSubjectPublicKeyByGetKeyParam(certPEMString); // or
* tbsc.setSubjectPublicKeyByGetKeyParam(pkcs8PublicKeyPEMString); // or
* tbsc.setSubjectPublicKeyByGetKeyParam(kjurCryptoECDSAKeyObject); // et.al.
* @see KJUR.asn1.x509.SubjectPublicKeyInfo
* @see KEYUTIL.getKey
* @since asn1x509 1.0.6
*/
this.setSubjectPublicKeyByGetKey = function(keyParam) {
var keyObj = KEYUTIL.getKey(keyParam);
this.asn1SubjPKey = new KJUR.asn1.x509.SubjectPublicKeyInfo(keyObj);
};
/**
* append X.509v3 extension to this object
* @name appendExtension
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Extension} extObj X.509v3 Extension object
* @description
* @example
* tbsc.appendExtension(new KJUR.asn1.x509.BasicConstraints({'cA':true, 'critical': true}));
* tbsc.appendExtension(new KJUR.asn1.x509.KeyUsage({'bin':'11'}));
* @see KJUR.asn1.x509.Extension
*/
this.appendExtension = function(extObj) {
this.extensionsArray.push(extObj);
};
/**
* append X.509v3 extension to this object by name and parameters
* @name appendExtensionByName
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {name} name name of X.509v3 Extension object
* @param {Array} extParams parameters as argument of Extension constructor.
* @description
* @example
* tbsc.appendExtensionByName('BasicConstraints', {'cA':true, 'critical': true});
* tbsc.appendExtensionByName('KeyUsage', {'bin':'11'});
* tbsc.appendExtensionByName('CRLDistributionPoints', {uri: 'http://aaa.com/a.crl'});
* tbsc.appendExtensionByName('ExtKeyUsage', {array: [{name: 'clientAuth'}]});
* @see KJUR.asn1.x509.Extension
*/
this.appendExtensionByName = function(name, extParams) {
if (name.toLowerCase() == "basicconstraints") {
var extObj = new KJUR.asn1.x509.BasicConstraints(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "keyusage") {
var extObj = new KJUR.asn1.x509.KeyUsage(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "crldistributionpoints") {
var extObj = new KJUR.asn1.x509.CRLDistributionPoints(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "extkeyusage") {
var extObj = new KJUR.asn1.x509.ExtKeyUsage(extParams);
this.appendExtension(extObj);
} else {
throw "unsupported extension name: " + name;
}
};
this.getEncodedHex = function() {
if (this.asn1NotBefore == null || this.asn1NotAfter == null)
throw "notBefore and/or notAfter not set";
var asn1Validity =
new KJUR.asn1.DERSequence({'array':[this.asn1NotBefore, this.asn1NotAfter]});
this.asn1Array = new Array();
this.asn1Array.push(this.asn1Version);
this.asn1Array.push(this.asn1SerialNumber);
this.asn1Array.push(this.asn1SignatureAlg);
this.asn1Array.push(this.asn1Issuer);
this.asn1Array.push(asn1Validity);
this.asn1Array.push(this.asn1Subject);
this.asn1Array.push(this.asn1SubjPKey);
if (this.extensionsArray.length > 0) {
var extSeq = new KJUR.asn1.DERSequence({"array": this.extensionsArray});
var extTagObj = new KJUR.asn1.DERTaggedObject({'explicit': true,
'tag': 'a3',
'obj': extSeq});
this.asn1Array.push(extTagObj);
}
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.hTLV = o.getEncodedHex();
this.isModified = false;
return this.hTLV;
};
this._initialize();
};
YAHOO.lang.extend(KJUR.asn1.x509.TBSCertificate, KJUR.asn1.ASN1Object);
// === END TBSCertificate ===================================================
// === BEGIN X.509v3 Extensions Related =======================================
/**
* base Extension ASN.1 structure class
* @name KJUR.asn1.x509.Extension
* @class base Extension ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'critical': true})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
* // Extension ::= SEQUENCE {
* // extnID OBJECT IDENTIFIER,
* // critical BOOLEAN DEFAULT FALSE,
* // extnValue OCTET STRING }
*/
KJUR.asn1.x509.Extension = function(params) {
KJUR.asn1.x509.Extension.superclass.constructor.call(this);
var asn1ExtnValue = null;
this.getEncodedHex = function() {
var asn1Oid = new KJUR.asn1.DERObjectIdentifier({'oid': this.oid});
var asn1EncapExtnValue =
new KJUR.asn1.DEROctetString({'hex': this.getExtnValueHex()});
var asn1Array = new Array();
asn1Array.push(asn1Oid);
if (this.critical) asn1Array.push(new KJUR.asn1.DERBoolean());
asn1Array.push(asn1EncapExtnValue);
var asn1Seq = new KJUR.asn1.DERSequence({'array': asn1Array});
return asn1Seq.getEncodedHex();
};
this.critical = false;
if (typeof params != "undefined") {
if (typeof params['critical'] != "undefined") {
this.critical = params['critical'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Extension, KJUR.asn1.ASN1Object);
/**
* KeyUsage ASN.1 structure class
* @name KJUR.asn1.x509.KeyUsage
* @class KeyUsage ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'bin': '11', 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.KeyUsage = function(params) {
KJUR.asn1.x509.KeyUsage.superclass.constructor.call(this, params);
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.15";
if (typeof params != "undefined") {
if (typeof params['bin'] != "undefined") {
this.asn1ExtnValue = new KJUR.asn1.DERBitString(params);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.KeyUsage, KJUR.asn1.x509.Extension);
/**
* BasicConstraints ASN.1 structure class
* @name KJUR.asn1.x509.BasicConstraints
* @class BasicConstraints ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'cA': true, 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.BasicConstraints = function(params) {
KJUR.asn1.x509.BasicConstraints.superclass.constructor.call(this, params);
var cA = false;
var pathLen = -1;
this.getExtnValueHex = function() {
var asn1Array = new Array();
if (this.cA) asn1Array.push(new KJUR.asn1.DERBoolean());
if (this.pathLen > -1)
asn1Array.push(new KJUR.asn1.DERInteger({'int': this.pathLen}));
var asn1Seq = new KJUR.asn1.DERSequence({'array': asn1Array});
this.asn1ExtnValue = asn1Seq;
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.19";
this.cA = false;
this.pathLen = -1;
if (typeof params != "undefined") {
if (typeof params['cA'] != "undefined") {
this.cA = params['cA'];
}
if (typeof params['pathLen'] != "undefined") {
this.pathLen = params['pathLen'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.BasicConstraints, KJUR.asn1.x509.Extension);
/**
* CRLDistributionPoints ASN.1 structure class
* @name KJUR.asn1.x509.CRLDistributionPoints
* @class CRLDistributionPoints ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'uri': 'http://a.com/', 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.CRLDistributionPoints = function(params) {
KJUR.asn1.x509.CRLDistributionPoints.superclass.constructor.call(this, params);
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.setByDPArray = function(dpArray) {
this.asn1ExtnValue = new KJUR.asn1.DERSequence({'array': dpArray});
};
this.setByOneURI = function(uri) {
var gn1 = new KJUR.asn1.x509.GeneralNames([{'uri': uri}]);
var dpn1 = new KJUR.asn1.x509.DistributionPointName(gn1);
var dp1 = new KJUR.asn1.x509.DistributionPoint({'dpobj': dpn1});
this.setByDPArray([dp1]);
};
this.oid = "2.5.29.31";
if (typeof params != "undefined") {
if (typeof params['array'] != "undefined") {
this.setByDPArray(params['array']);
} else if (typeof params['uri'] != "undefined") {
this.setByOneURI(params['uri']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRLDistributionPoints, KJUR.asn1.x509.Extension);
/**
* KeyUsage ASN.1 structure class
* @name KJUR.asn1.x509.ExtKeyUsage
* @class ExtKeyUsage ASN.1 structure class
* @param {Array} params associative array of parameters
* @extends KJUR.asn1.x509.Extension
* @description
* @example
* var e1 =
* new KJUR.asn1.x509.ExtKeyUsage({'critical': true,
* 'array':
* [{'oid': '2.5.29.37.0', // anyExtendedKeyUsage
* 'name': 'clientAuth'}]});
*
* // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
* // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
* // KeyPurposeId ::= OBJECT IDENTIFIER
*/
KJUR.asn1.x509.ExtKeyUsage = function(params) {
KJUR.asn1.x509.ExtKeyUsage.superclass.constructor.call(this, params);
this.setPurposeArray = function(purposeArray) {
this.asn1ExtnValue = new KJUR.asn1.DERSequence();
for (var i = 0; i < purposeArray.length; i++) {
var o = new KJUR.asn1.DERObjectIdentifier(purposeArray[i]);
this.asn1ExtnValue.appendASN1Object(o);
}
};
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.37";
if (typeof params != "undefined") {
if (typeof params['array'] != "undefined") {
this.setPurposeArray(params['array']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.ExtKeyUsage, KJUR.asn1.x509.Extension);
// === END X.509v3 Extensions Related =======================================
// === BEGIN CRL Related ===================================================
/**
* X.509 CRL class to sign and generate hex encoded CRL
* @name KJUR.asn1.x509.CRL
* @class X.509 CRL class to sign and generate hex encoded certificate
* @param {Array} params associative array of parameters (ex. {'tbsobj': obj, 'rsaprvkey': key})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
tbsobj - specify {@link KJUR.asn1.x509.TBSCertList} object to be signed
*
rsaprvkey - specify {@link RSAKey} object CA private key
*
* NOTE: 'params' can be omitted.
*
EXAMPLE
* @example
* var prvKey = new RSAKey(); // CA's private key
* prvKey.readPrivateKeyFromASN1HexString("3080...");
* var crl = new KJUR.asn1x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* crl.sign(); // issue CRL by CA's private key
* var hCRL = crl.getEncodedHex();
*
* // CertificateList ::= SEQUENCE {
* // tbsCertList TBSCertList,
* // signatureAlgorithm AlgorithmIdentifier,
* // signatureValue BIT STRING }
*/
KJUR.asn1.x509.CRL = function(params) {
KJUR.asn1.x509.CRL.superclass.constructor.call(this);
var asn1TBSCertList = null;
var asn1SignatureAlg = null;
var asn1Sig = null;
var hexSig = null;
var rsaPrvKey = null;
/**
* set PKCS#5 encrypted RSA PEM private key as CA key
* @name setRsaPrvKeyByPEMandPass
* @memberOf KJUR.asn1.x509.CRL
* @function
* @param {String} rsaPEM string of PKCS#5 encrypted RSA PEM private key
* @param {String} passPEM passcode string to decrypt private key
* @description
*
*
EXAMPLES
* @example
*/
this.setRsaPrvKeyByPEMandPass = function(rsaPEM, passPEM) {
var caKeyHex = PKCS5PKEY.getDecryptedKeyHex(rsaPEM, passPEM);
var caKey = new RSAKey();
caKey.readPrivateKeyFromASN1HexString(caKeyHex);
this.rsaPrvKey = caKey;
};
/**
* sign TBSCertList and set signature value internally
* @name sign
* @memberOf KJUR.asn1.x509.CRL
* @function
* @description
* @example
* var cert = new KJUR.asn1.x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
*/
this.sign = function() {
this.asn1SignatureAlg = this.asn1TBSCertList.asn1SignatureAlg;
sig = new KJUR.crypto.Signature({'alg': 'SHA1withRSA', 'prov': 'cryptojs/jsrsa'});
sig.initSign(this.rsaPrvKey);
sig.updateHex(this.asn1TBSCertList.getEncodedHex());
this.hexSig = sig.sign();
this.asn1Sig = new KJUR.asn1.DERBitString({'hex': '00' + this.hexSig});
var seq = new KJUR.asn1.DERSequence({'array': [this.asn1TBSCertList,
this.asn1SignatureAlg,
this.asn1Sig]});
this.hTLV = seq.getEncodedHex();
this.isModified = false;
};
this.getEncodedHex = function() {
if (this.isModified == false && this.hTLV != null) return this.hTLV;
throw "not signed yet";
};
/**
* get PEM formatted CRL string after signed
* @name getPEMString
* @memberOf KJUR.asn1.x509.CRL
* @function
* @return PEM formatted string of certificate
* @description
* @example
* var cert = new KJUR.asn1.x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
* var sPEM = cert.getPEMString();
*/
this.getPEMString = function() {
var hCert = this.getEncodedHex();
var wCert = CryptoJS.enc.Hex.parse(hCert);
var b64Cert = CryptoJS.enc.Base64.stringify(wCert);
var pemBody = b64Cert.replace(/(.{64})/g, "$1\r\n");
return "-----BEGIN X509 CRL-----\r\n" + pemBody + "\r\n-----END X509 CRL-----\r\n";
};
if (typeof params != "undefined") {
if (typeof params['tbsobj'] != "undefined") {
this.asn1TBSCertList = params['tbsobj'];
}
if (typeof params['rsaprvkey'] != "undefined") {
this.rsaPrvKey = params['rsaprvkey'];
}
if ((typeof params['rsaprvpem'] != "undefined") &&
(typeof params['rsaprvpas'] != "undefined")) {
this.setRsaPrvKeyByPEMandPass(params['rsaprvpem'], params['rsaprvpas']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRL, KJUR.asn1.ASN1Object);
/**
* ASN.1 TBSCertList structure class for CRL
* @name KJUR.asn1.x509.TBSCertList
* @class ASN.1 TBSCertList structure class for CRL
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
*
*
EXAMPLE
* @example
* var o = new KJUR.asn1.x509.TBSCertList();
* o.setSignatureAlgByParam({'name': 'SHA1withRSA'});
* o.setIssuerByParam({'str': '/C=US/O=a'});
* o.setNotThisUpdateByParam({'str': '130504235959Z'});
* o.setNotNextUpdateByParam({'str': '140504235959Z'});
* o.addRevokedCert({'int': 4}, {'str':'130514235959Z'}));
* o.addRevokedCert({'hex': '0f34dd'}, {'str':'130514235959Z'}));
*
* // TBSCertList ::= SEQUENCE {
* // version Version OPTIONAL,
* // -- if present, MUST be v2
* // signature AlgorithmIdentifier,
* // issuer Name,
* // thisUpdate Time,
* // nextUpdate Time OPTIONAL,
* // revokedCertificates SEQUENCE OF SEQUENCE {
* // userCertificate CertificateSerialNumber,
* // revocationDate Time,
* // crlEntryExtensions Extensions OPTIONAL
* // -- if present, version MUST be v2
* // } OPTIONAL,
* // crlExtensions [0] EXPLICIT Extensions OPTIONAL
*/
KJUR.asn1.x509.TBSCertList = function(params) {
KJUR.asn1.x509.TBSCertList.superclass.constructor.call(this);
var aRevokedCert = null;
/**
* set signature algorithm field by parameter
* @name setSignatureAlgByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} algIdParam AlgorithmIdentifier parameter
* @description
* @example
* tbsc.setSignatureAlgByParam({'name': 'SHA1withRSA'});
*/
this.setSignatureAlgByParam = function(algIdParam) {
this.asn1SignatureAlg = new KJUR.asn1.x509.AlgorithmIdentifier(algIdParam);
};
/**
* set issuer name field by parameter
* @name setIssuerByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setIssuerParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setIssuerByParam = function(x500NameParam) {
this.asn1Issuer = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* set thisUpdate field by parameter
* @name setThisUpdateByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setThisUpdateByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setThisUpdateByParam = function(timeParam) {
this.asn1ThisUpdate = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set nextUpdate field by parameter
* @name setNextUpdateByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNextUpdateByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNextUpdateByParam = function(timeParam) {
this.asn1NextUpdate = new KJUR.asn1.x509.Time(timeParam);
};
/**
* add revoked certficate by parameter
* @name addRevokedCert
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} snParam DERInteger parameter for certificate serial number
* @param {Array} timeParam Time parameter for revocation date
* @description
* @example
* tbsc.addRevokedCert({'int': 3}, {'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.addRevokedCert = function(snParam, timeParam) {
var param = {};
if (snParam != undefined && snParam != null) param['sn'] = snParam;
if (timeParam != undefined && timeParam != null) param['time'] = timeParam;
var o = new KJUR.asn1.x509.CRLEntry(param);
this.aRevokedCert.push(o);
};
this.getEncodedHex = function() {
this.asn1Array = new Array();
if (this.asn1Version != null) this.asn1Array.push(this.asn1Version);
this.asn1Array.push(this.asn1SignatureAlg);
this.asn1Array.push(this.asn1Issuer);
this.asn1Array.push(this.asn1ThisUpdate);
if (this.asn1NextUpdate != null) this.asn1Array.push(this.asn1NextUpdate);
if (this.aRevokedCert.length > 0) {
var seq = new KJUR.asn1.DERSequence({'array': this.aRevokedCert});
this.asn1Array.push(seq);
}
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.hTLV = o.getEncodedHex();
this.isModified = false;
return this.hTLV;
};
this._initialize = function() {
this.asn1Version = null;
this.asn1SignatureAlg = null;
this.asn1Issuer = null;
this.asn1ThisUpdate = null;
this.asn1NextUpdate = null;
this.aRevokedCert = new Array();
};
this._initialize();
};
YAHOO.lang.extend(KJUR.asn1.x509.TBSCertList, KJUR.asn1.ASN1Object);
/**
* ASN.1 CRLEntry structure class for CRL
* @name KJUR.asn1.x509.CRLEntry
* @class ASN.1 CRLEntry structure class for CRL
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
* @example
* var e = new KJUR.asn1.x509.CRLEntry({'time': {'str': '130514235959Z'}, 'sn': {'int': 234}});
*
* // revokedCertificates SEQUENCE OF SEQUENCE {
* // userCertificate CertificateSerialNumber,
* // revocationDate Time,
* // crlEntryExtensions Extensions OPTIONAL
* // -- if present, version MUST be v2 }
*/
KJUR.asn1.x509.CRLEntry = function(params) {
KJUR.asn1.x509.CRLEntry.superclass.constructor.call(this);
var sn = null;
var time = null;
/**
* set DERInteger parameter for serial number of revoked certificate
* @name setCertSerial
* @memberOf KJUR.asn1.x509.CRLEntry
* @function
* @param {Array} intParam DERInteger parameter for certificate serial number
* @description
* @example
* entry.setCertSerial({'int': 3});
*/
this.setCertSerial = function(intParam) {
this.sn = new KJUR.asn1.DERInteger(intParam);
};
/**
* set Time parameter for revocation date
* @name setRevocationDate
* @memberOf KJUR.asn1.x509.CRLEntry
* @function
* @param {Array} timeParam Time parameter for revocation date
* @description
* @example
* entry.setRevocationDate({'str': '130508235959Z'});
*/
this.setRevocationDate = function(timeParam) {
this.time = new KJUR.asn1.x509.Time(timeParam);
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": [this.sn, this.time]});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['time'] != "undefined") {
this.setRevocationDate(params['time']);
}
if (typeof params['sn'] != "undefined") {
this.setCertSerial(params['sn']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRLEntry, KJUR.asn1.ASN1Object);
// === END CRL Related ===================================================
// === BEGIN X500Name Related =================================================
/**
* X500Name ASN.1 structure class
* @name KJUR.asn1.x509.X500Name
* @class X500Name ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': '/C=US/O=a'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.X500Name = function(params) {
KJUR.asn1.x509.X500Name.superclass.constructor.call(this);
this.asn1Array = new Array();
this.setByString = function(dnStr) {
var a = dnStr.split('/');
a.shift();
for (var i = 0; i < a.length; i++) {
this.asn1Array.push(new KJUR.asn1.x509.RDN({'str':a[i]}));
}
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.X500Name, KJUR.asn1.ASN1Object);
/**
* RDN (Relative Distinguish Name) ASN.1 structure class
* @name KJUR.asn1.x509.RDN
* @class RDN (Relative Distinguish Name) ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': 'C=US'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.RDN = function(params) {
KJUR.asn1.x509.RDN.superclass.constructor.call(this);
this.asn1Array = new Array();
this.addByString = function(rdnStr) {
this.asn1Array.push(new KJUR.asn1.x509.AttributeTypeAndValue({'str':rdnStr}));
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSet({"array": this.asn1Array});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.addByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.RDN, KJUR.asn1.ASN1Object);
/**
* AttributeTypeAndValue ASN.1 structure class
* @name KJUR.asn1.x509.AttributeTypeAndValue
* @class AttributeTypeAndValue ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': 'C=US'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.AttributeTypeAndValue = function(params) {
KJUR.asn1.x509.AttributeTypeAndValue.superclass.constructor.call(this);
var typeObj = null;
var valueObj = null;
var defaultDSType = "utf8";
this.setByString = function(attrTypeAndValueStr) {
if (attrTypeAndValueStr.match(/^([^=]+)=(.+)$/)) {
this.setByAttrTypeAndValueStr(RegExp.$1, RegExp.$2);
} else {
throw "malformed attrTypeAndValueStr: " + attrTypeAndValueStr;
}
};
this.setByAttrTypeAndValueStr = function(shortAttrType, valueStr) {
this.typeObj = KJUR.asn1.x509.OID.atype2obj(shortAttrType);
var dsType = defaultDSType;
if (shortAttrType == "C") dsType = "prn";
this.valueObj = this.getValueObj(dsType, valueStr);
};
this.getValueObj = function(dsType, valueStr) {
if (dsType == "utf8") return new KJUR.asn1.DERUTF8String({"str": valueStr});
if (dsType == "prn") return new KJUR.asn1.DERPrintableString({"str": valueStr});
if (dsType == "tel") return new KJUR.asn1.DERTeletexString({"str": valueStr});
if (dsType == "ia5") return new KJUR.asn1.DERIA5String({"str": valueStr});
throw "unsupported directory string type: type=" + dsType + " value=" + valueStr;
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": [this.typeObj, this.valueObj]});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.AttributeTypeAndValue, KJUR.asn1.ASN1Object);
// === END X500Name Related =================================================
// === BEGIN Other ASN1 structure class ======================================
/**
* SubjectPublicKeyInfo ASN.1 structure class
* @name KJUR.asn1.x509.SubjectPublicKeyInfo
* @class SubjectPublicKeyInfo ASN.1 structure class
* @param {Object} params parameter for subject public key
* @extends KJUR.asn1.ASN1Object
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
{@link RSAKey} object
*
{@link KJUR.crypto.ECDSA} object
*
{@link KJUR.crypto.DSA} object
*
(DEPRECATED)rsakey - specify {@link RSAKey} object of subject public key
*
(DEPRECATED)rsapem - specify a string of PEM public key of RSA key
*
* NOTE1: 'params' can be omitted.
* NOTE2: DSA/ECDSA key object is also supported since asn1x509 1.0.6.
*
EXAMPLE
* @example
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(RSAKey_object);
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(KJURcryptoECDSA_object);
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(KJURcryptoDSA_object);
*/
KJUR.asn1.x509.SubjectPublicKeyInfo = function(params) {
KJUR.asn1.x509.SubjectPublicKeyInfo.superclass.constructor.call(this);
var asn1AlgId = null;
var asn1SubjPKey = null;
var rsaKey = null;
/**
* (DEPRECATED) set RSAKey object as subject public key
* @name setRSAKey
* @memberOf KJUR.asn1.x509.SubjectPublicKeyInfo
* @function
* @param {RSAKey} rsaKey {@link RSAKey} object for RSA public key
* @description
* @deprecated
* @example
* spki.setRSAKey(rsaKey);
*/
this.setRSAKey = function(rsaKey) {
if (! RSAKey.prototype.isPrototypeOf(rsaKey))
throw "argument is not RSAKey instance";
this.rsaKey = rsaKey;
var asn1RsaN = new KJUR.asn1.DERInteger({'bigint': rsaKey.n});
var asn1RsaE = new KJUR.asn1.DERInteger({'int': rsaKey.e});
var asn1RsaPub = new KJUR.asn1.DERSequence({'array': [asn1RsaN, asn1RsaE]});
var rsaKeyHex = asn1RsaPub.getEncodedHex();
this.asn1AlgId = new KJUR.asn1.x509.AlgorithmIdentifier({'name':'rsaEncryption'});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex':'00'+rsaKeyHex});
};
/**
* (DEPRECATED) set a PEM formatted RSA public key string as RSA public key
* @name setRSAPEM
* @memberOf KJUR.asn1.x509.SubjectPublicKeyInfo
* @function
* @param {String} rsaPubPEM PEM formatted RSA public key string
* @deprecated
* @description
* @example
* spki.setRSAPEM(rsaPubPEM);
*/
this.setRSAPEM = function(rsaPubPEM) {
if (rsaPubPEM.match(/-----BEGIN PUBLIC KEY-----/)) {
var s = rsaPubPEM;
s = s.replace(/^-----[^-]+-----/, '');
s = s.replace(/-----[^-]+-----\s*$/, '');
var rsaB64 = s.replace(/\s+/g, '');
var rsaWA = CryptoJS.enc.Base64.parse(rsaB64);
var rsaP8Hex = CryptoJS.enc.Hex.stringify(rsaWA);
var a = _rsapem_getHexValueArrayOfChildrenFromHex(rsaP8Hex);
var hBitStrVal = a[1];
var rsaHex = hBitStrVal.substr(2);
var a3 = _rsapem_getHexValueArrayOfChildrenFromHex(rsaHex);
var rsaKey = new RSAKey();
rsaKey.setPublic(a3[0], a3[1]);
this.setRSAKey(rsaKey);
} else {
throw "key not supported";
}
};
/*
* @since asn1x509 1.0.7
*/
this.getASN1Object = function() {
if (this.asn1AlgId == null || this.asn1SubjPKey == null)
throw "algId and/or subjPubKey not set";
var o = new KJUR.asn1.DERSequence({'array':
[this.asn1AlgId, this.asn1SubjPKey]});
return o;
};
this.getEncodedHex = function() {
var o = this.getASN1Object();
this.hTLV = o.getEncodedHex();
return this.hTLV;
};
this._setRSAKey = function(key) {
var asn1RsaPub = KJUR.asn1.ASN1Util.newObject({
'seq': [{'int': {'bigint': key.n}}, {'int': {'int': key.e}}]
});
var rsaKeyHex = asn1RsaPub.getEncodedHex();
this.asn1AlgId = new KJUR.asn1.x509.AlgorithmIdentifier({'name':'rsaEncryption'});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex':'00'+rsaKeyHex});
};
this._setEC = function(key) {
var asn1Params = new KJUR.asn1.DERObjectIdentifier({'name': key.curveName});
this.asn1AlgId =
new KJUR.asn1.x509.AlgorithmIdentifier({'name': 'ecPublicKey',
'asn1params': asn1Params});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex': '00' + key.pubKeyHex});
};
this._setDSA = function(key) {
var asn1Params = new KJUR.asn1.ASN1Util.newObject({
'seq': [{'int': {'bigint': key.p}},
{'int': {'bigint': key.q}},
{'int': {'bigint': key.g}}]
});
this.asn1AlgId =
new KJUR.asn1.x509.AlgorithmIdentifier({'name': 'dsa',
'asn1params': asn1Params});
var pubInt = new KJUR.asn1.DERInteger({'bigint': key.y});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex': '00' + pubInt.getEncodedHex()});
};
if (typeof params != "undefined") {
if (typeof RSAKey != 'undefined' && params instanceof RSAKey) {
this._setRSAKey(params);
} else if (typeof KJUR.crypto.ECDSA != 'undefined' &&
params instanceof KJUR.crypto.ECDSA) {
this._setEC(params);
} else if (typeof KJUR.crypto.DSA != 'undefined' &&
params instanceof KJUR.crypto.DSA) {
this._setDSA(params);
} else if (typeof params['rsakey'] != "undefined") {
this.setRSAKey(params['rsakey']);
} else if (typeof params['rsapem'] != "undefined") {
this.setRSAPEM(params['rsapem']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.SubjectPublicKeyInfo, KJUR.asn1.ASN1Object);
/**
* Time ASN.1 structure class
* @name KJUR.asn1.x509.Time
* @class Time ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': '130508235959Z'})
* @extends KJUR.asn1.ASN1Object
* @description
*
*
EXAMPLES
* @example
* var t1 = new KJUR.asn1.x509.Time{'str': '130508235959Z'} // UTCTime by default
* var t2 = new KJUR.asn1.x509.Time{'type': 'gen', 'str': '20130508235959Z'} // GeneralizedTime
*/
KJUR.asn1.x509.Time = function(params) {
KJUR.asn1.x509.Time.superclass.constructor.call(this);
var type = null;
var timeParams = null;
this.setTimeParams = function(timeParams) {
this.timeParams = timeParams;
}
this.getEncodedHex = function() {
if (this.timeParams == null) {
throw "timeParams shall be specified. ({'str':'130403235959Z'}}";
}
var o = null;
if (this.type == "utc") {
o = new KJUR.asn1.DERUTCTime(this.timeParams);
} else {
o = new KJUR.asn1.DERGeneralizedTime(this.timeParams);
}
this.TLV = o.getEncodedHex();
return this.TLV;
};
this.type = "utc";
if (typeof params != "undefined") {
if (typeof params['type'] != "undefined") {
this.type = params['type'];
}
this.timeParams = params;
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Time, KJUR.asn1.ASN1Object);
/**
* AlgorithmIdentifier ASN.1 structure class
* @name KJUR.asn1.x509.AlgorithmIdentifier
* @class AlgorithmIdentifier ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'name': 'SHA1withRSA'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.AlgorithmIdentifier = function(params) {
KJUR.asn1.x509.AlgorithmIdentifier.superclass.constructor.call(this);
var nameAlg = null;
var asn1Alg = null;
var asn1Params = null;
var paramEmpty = false;
this.getEncodedHex = function() {
if (this.nameAlg == null && this.asn1Alg == null) {
throw "algorithm not specified";
}
if (this.nameAlg != null && this.asn1Alg == null) {
this.asn1Alg = KJUR.asn1.x509.OID.name2obj(this.nameAlg);
}
var a = [this.asn1Alg];
if (! this.paramEmpty) a.push(this.asn1Params);
var o = new KJUR.asn1.DERSequence({'array': a});
this.hTLV = o.getEncodedHex();
return this.hTLV;
};
if (typeof params != "undefined") {
if (typeof params['name'] != "undefined") {
this.nameAlg = params['name'];
}
if (typeof params['asn1params'] != "undefined") {
this.asn1Params = params['asn1params'];
}
if (typeof params['paramempty'] != "undefined") {
this.paramEmpty = params['paramempty'];
}
}
if (this.asn1Params == null) {
this.asn1Params = new KJUR.asn1.DERNull();
}
};
YAHOO.lang.extend(KJUR.asn1.x509.AlgorithmIdentifier, KJUR.asn1.ASN1Object);
/**
* GeneralName ASN.1 structure class
* @name KJUR.asn1.x509.GeneralName
* @class GeneralName ASN.1 structure class
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
rfc822 - rfc822Name[1] (ex. user1@foo.com)
*
dns - dNSName[2] (ex. foo.com)
*
uri - uniformResourceIdentifier[6] (ex. http://foo.com/)
*
* NOTE: Currently this only supports 'uniformResourceIdentifier'.
*
EXAMPLE AND ASN.1 SYNTAX
* @example
* var gn = new KJUR.asn1.x509.GeneralName({'uri': 'http://aaa.com/'});
*
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] Name,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER }
*/
KJUR.asn1.x509.GeneralName = function(params) {
KJUR.asn1.x509.GeneralName.superclass.constructor.call(this);
var asn1Obj = null;
var type = null;
var pTag = {'rfc822': '81', 'dns': '82', 'uri': '86'};
this.setByParam = function(params) {
var str = null;
var v = null;
if (typeof params['rfc822'] != "undefined") {
this.type = 'rfc822';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (typeof params['dns'] != "undefined") {
this.type = 'dns';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (typeof params['uri'] != "undefined") {
this.type = 'uri';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (this.type == null)
throw "unsupported type in params=" + params;
this.asn1Obj = new KJUR.asn1.DERTaggedObject({'explicit': false,
'tag': pTag[this.type],
'obj': v});
};
this.getEncodedHex = function() {
return this.asn1Obj.getEncodedHex();
}
if (typeof params != "undefined") {
this.setByParam(params);
}
};
YAHOO.lang.extend(KJUR.asn1.x509.GeneralName, KJUR.asn1.ASN1Object);
/**
* GeneralNames ASN.1 structure class
* @name KJUR.asn1.x509.GeneralNames
* @class GeneralNames ASN.1 structure class
* @description
*
*
EXAMPLE AND ASN.1 SYNTAX
* @example
* var gns = new KJUR.asn1.x509.GeneralNames([{'uri': 'http://aaa.com/'}, {'uri': 'http://bbb.com/'}]);
*
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
*/
KJUR.asn1.x509.GeneralNames = function(paramsArray) {
KJUR.asn1.x509.GeneralNames.superclass.constructor.call(this);
var asn1Array = null;
/**
* set a array of {@link KJUR.asn1.x509.GeneralName} parameters
* @name setByParamArray
* @memberOf KJUR.asn1.x509.GeneralNames
* @function
* @param {Array} paramsArray Array of {@link KJUR.asn1.x509.GeneralNames}
* @description
*
*
EXAMPLES
* @example
* var gns = new KJUR.asn1.x509.GeneralNames();
* gns.setByParamArray([{'uri': 'http://aaa.com/'}, {'uri': 'http://bbb.com/'}]);
*/
this.setByParamArray = function(paramsArray) {
for (var i = 0; i < paramsArray.length; i++) {
var o = new KJUR.asn1.x509.GeneralName(paramsArray[i]);
this.asn1Array.push(o);
}
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({'array': this.asn1Array});
return o.getEncodedHex();
};
this.asn1Array = new Array();
if (typeof paramsArray != "undefined") {
this.setByParamArray(paramsArray);
}
};
YAHOO.lang.extend(KJUR.asn1.x509.GeneralNames, KJUR.asn1.ASN1Object);
/**
* DistributionPointName ASN.1 structure class
* @name KJUR.asn1.x509.DistributionPointName
* @class DistributionPointName ASN.1 structure class
* @description
* @example
*/
KJUR.asn1.x509.DistributionPointName = function(gnOrRdn) {
KJUR.asn1.x509.DistributionPointName.superclass.constructor.call(this);
var asn1Obj = null;
var type = null;
var tag = null;
var asn1V = null;
this.getEncodedHex = function() {
if (this.type != "full")
throw "currently type shall be 'full': " + this.type;
this.asn1Obj = new KJUR.asn1.DERTaggedObject({'explicit': false,
'tag': this.tag,
'obj': this.asn1V});
this.hTLV = this.asn1Obj.getEncodedHex();
return this.hTLV;
};
if (typeof gnOrRdn != "undefined") {
if (KJUR.asn1.x509.GeneralNames.prototype.isPrototypeOf(gnOrRdn)) {
this.type = "full";
this.tag = "a0";
this.asn1V = gnOrRdn;
} else {
throw "This class supports GeneralNames only as argument";
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.DistributionPointName, KJUR.asn1.ASN1Object);
/**
* DistributionPoint ASN.1 structure class
* @name KJUR.asn1.x509.DistributionPoint
* @class DistributionPoint ASN.1 structure class
* @description
* @example
*/
KJUR.asn1.x509.DistributionPoint = function(params) {
KJUR.asn1.x509.DistributionPoint.superclass.constructor.call(this);
var asn1DP = null;
this.getEncodedHex = function() {
var seq = new KJUR.asn1.DERSequence();
if (this.asn1DP != null) {
var o1 = new KJUR.asn1.DERTaggedObject({'explicit': true,
'tag': 'a0',
'obj': this.asn1DP});
seq.appendASN1Object(o1);
}
this.hTLV = seq.getEncodedHex();
return this.hTLV;
};
if (typeof params != "undefined") {
if (typeof params['dpobj'] != "undefined") {
this.asn1DP = params['dpobj'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.DistributionPoint, KJUR.asn1.ASN1Object);
/**
* static object for OID
* @name KJUR.asn1.x509.OID
* @class static object for OID
* @property {Assoc Array} atype2oidList for short attribyte type name and oid (i.e. 'C' and '2.5.4.6')
* @property {Assoc Array} name2oidList for oid name and oid (i.e. 'keyUsage' and '2.5.29.15')
* @property {Assoc Array} objCache for caching name and DERObjectIdentifier object
* @description
*
*
atype2oidList
*
currently supports 'C', 'O', 'OU', 'ST', 'L' and 'CN' only.
*
name2oidList
*
currently supports 'SHA1withRSA', 'rsaEncryption' and some extension OIDs
*
* @example
*/
KJUR.asn1.x509.OID = new function(params) {
this.atype2oidList = {
'C': '2.5.4.6',
'O': '2.5.4.10',
'OU': '2.5.4.11',
'ST': '2.5.4.8',
'L': '2.5.4.7',
'CN': '2.5.4.3',
};
this.name2oidList = {
'sha384': '2.16.840.1.101.3.4.2.2',
'sha224': '2.16.840.1.101.3.4.2.4',
'MD2withRSA': '1.2.840.113549.1.1.2',
'MD4withRSA': '1.2.840.113549.1.1.3',
'MD5withRSA': '1.2.840.113549.1.1.4',
'SHA1withRSA': '1.2.840.113549.1.1.5',
'SHA224withRSA': '1.2.840.113549.1.1.14',
'SHA256withRSA': '1.2.840.113549.1.1.11',
'SHA384withRSA': '1.2.840.113549.1.1.12',
'SHA512withRSA': '1.2.840.113549.1.1.13',
'SHA1withECDSA': '1.2.840.10045.4.1',
'SHA224withECDSA': '1.2.840.10045.4.3.1',
'SHA256withECDSA': '1.2.840.10045.4.3.2',
'SHA384withECDSA': '1.2.840.10045.4.3.3',
'SHA512withECDSA': '1.2.840.10045.4.3.4',
'dsa': '1.2.840.10040.4.1',
'SHA1withDSA': '1.2.840.10040.4.3',
'SHA224withDSA': '2.16.840.1.101.3.4.3.1',
'SHA256withDSA': '2.16.840.1.101.3.4.3.2',
'rsaEncryption': '1.2.840.113549.1.1.1',
'subjectKeyIdentifier': '2.5.29.14',
'countryName': '2.5.4.6',
'organization': '2.5.4.10',
'organizationalUnit': '2.5.4.11',
'stateOrProvinceName': '2.5.4.8',
'locality': '2.5.4.7',
'commonName': '2.5.4.3',
'keyUsage': '2.5.29.15',
'basicConstraints': '2.5.29.19',
'cRLDistributionPoints': '2.5.29.31',
'certificatePolicies': '2.5.29.32',
'authorityKeyIdentifier': '2.5.29.35',
'extKeyUsage': '2.5.29.37',
'anyExtendedKeyUsage': '2.5.29.37.0',
'serverAuth': '1.3.6.1.5.5.7.3.1',
'clientAuth': '1.3.6.1.5.5.7.3.2',
'codeSigning': '1.3.6.1.5.5.7.3.3',
'emailProtection': '1.3.6.1.5.5.7.3.4',
'timeStamping': '1.3.6.1.5.5.7.3.8',
'ocspSigning': '1.3.6.1.5.5.7.3.9',
'ecPublicKey': '1.2.840.10045.2.1',
'secp256r1': '1.2.840.10045.3.1.7',
'secp256k1': '1.3.132.0.10',
'secp384r1': '1.3.132.0.34',
'pkcs5PBES2': '1.2.840.113549.1.5.13',
'pkcs5PBKDF2': '1.2.840.113549.1.5.12',
'des-EDE3-CBC': '1.2.840.113549.3.7',
};
this.objCache = {};
/**
* get DERObjectIdentifier by registered OID name
* @name name2obj
* @memberOf KJUR.asn1.x509.OID
* @function
* @param {String} name OID
* @description
* @example
* var asn1ObjOID = OID.name2obj('SHA1withRSA');
*/
this.name2obj = function(name) {
if (typeof this.objCache[name] != "undefined")
return this.objCache[name];
if (typeof this.name2oidList[name] == "undefined")
throw "Name of ObjectIdentifier not defined: " + name;
var oid = this.name2oidList[name];
var obj = new KJUR.asn1.DERObjectIdentifier({'oid': oid});
this.objCache[name] = obj;
return obj;
};
/**
* get DERObjectIdentifier by registered attribyte type name such like 'C' or 'CN'
* @name atype2obj
* @memberOf KJUR.asn1.x509.OID
* @function
* @param {String} atype short attribute type name such like 'C' or 'CN'
* @description
* @example
* var asn1ObjOID = OID.atype2obj('CN');
*/
this.atype2obj = function(atype) {
if (typeof this.objCache[atype] != "undefined")
return this.objCache[atype];
if (typeof this.atype2oidList[atype] == "undefined")
throw "AttributeType name undefined: " + atype;
var oid = this.atype2oidList[atype];
var obj = new KJUR.asn1.DERObjectIdentifier({'oid': oid});
this.objCache[atype] = obj;
return obj;
};
};
/**
* X.509 certificate and CRL utilities class
* @name KJUR.asn1.x509.X509Util
* @class X.509 certificate and CRL utilities class
*/
KJUR.asn1.x509.X509Util = new function() {
/**
* get PKCS#8 PEM public key string from RSAKey object
* @name getPKCS8PubKeyPEMfromRSAKey
* @memberOf KJUR.asn1.x509.X509Util
* @function
* @param {RSAKey} rsaKey RSA public key of {@link RSAKey} object
* @description
* @example
* var pem = KJUR.asn1.x509.X509Util.getPKCS8PubKeyPEMfromRSAKey(pubKey);
*/
this.getPKCS8PubKeyPEMfromRSAKey = function(rsaKey) {
var pem = null;
var hN = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(rsaKey.n);
var hE = KJUR.asn1.ASN1Util.integerToByteHex(rsaKey.e);
var iN = new KJUR.asn1.DERInteger({hex: hN});
var iE = new KJUR.asn1.DERInteger({hex: hE});
var asn1PubKey = new KJUR.asn1.DERSequence({array: [iN, iE]});
var hPubKey = asn1PubKey.getEncodedHex();
var o1 = new KJUR.asn1.x509.AlgorithmIdentifier({name: 'rsaEncryption'});
var o2 = new KJUR.asn1.DERBitString({hex: '00' + hPubKey});
var seq = new KJUR.asn1.DERSequence({array: [o1, o2]});
var hP8 = seq.getEncodedHex();
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(hP8, "PUBLIC KEY");
return pem;
};
};
/**
* issue a certificate in PEM format
* @name newCertPEM
* @memberOf KJUR.asn1.x509.X509Util
* @function
* @param {Array} param parameter to issue a certificate
* @since asn1x509 1.0.6
* @description
* This method can issue a certificate by a simple
* JSON object.
* NOTE: When using DSA or ECDSA CA signing key,
* use 'paramempty' in 'sigalg' to ommit parameter field
* of AlgorithmIdentifer. In case of RSA, parameter
* NULL will be specified by default.
* @example
* var certPEM = KJUR.asn1.x509.X509Util.newCertPEM(
* { serial: {int: 4},
* sigalg: {name: 'SHA1withECDSA', paramempty: true},
* issuer: {str: '/C=US/O=a'},
* notbefore: {'str': '130504235959Z'},
* notafter: {'str': '140504235959Z'},
* subject: {str: '/C=US/O=b'},
* sbjpubkey: pubKeyPEM,
* ext: [
* {basicConstraints: {cA: true, critical: true}},
* {keyUsage: {bin: '11'}},
* ],
* cakey: [prvkey, pass]}
* );
*/
KJUR.asn1.x509.X509Util.newCertPEM = function(param) {
var ns1 = KJUR.asn1.x509;
var o = new ns1.TBSCertificate();
if (param.serial !== undefined)
o.setSerialNumberByParam(param.serial);
else
throw "serial number undefined.";
if (typeof param.sigalg.name == 'string')
o.setSignatureAlgByParam(param.sigalg);
else
throw "unproper signature algorithm name";
if (param.issuer !== undefined)
o.setIssuerByParam(param.issuer);
else
throw "issuer name undefined.";
if (param.notbefore !== undefined)
o.setNotBeforeByParam(param.notbefore);
else
throw "notbefore undefined.";
if (param.notafter !== undefined)
o.setNotAfterByParam(param.notafter);
else
throw "notafter undefined.";
if (param.subject !== undefined)
o.setSubjectByParam(param.subject);
else
throw "subject name undefined.";
if (param.sbjpubkey !== undefined)
o.setSubjectPublicKeyByGetKey(param.sbjpubkey);
else
throw "subject public key undefined.";
if (param.ext.length !== undefined) {
for (var i = 0; i < param.ext.length; i++) {
for (key in param.ext[i]) {
o.appendExtensionByName(key, param.ext[i][key]);
}
}
}
var caKey = null;
if (param.cakey)
caKey = KEYUTIL.getKey.apply(null, param.cakey);
else
throw "ca key undefined";
var cert = new ns1.Certificate({'tbscertobj': o, 'prvkeyobj': caKey});
cert.sign();
return cert.getPEMString();
};
/*
org.bouncycastle.asn1.x500
AttributeTypeAndValue
DirectoryString
RDN
X500Name
X500NameBuilder
org.bouncycastleasn1.x509
TBSCertificate
*/
================================================
FILE: JavaScript/demo/js/base64.js
================================================
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
*/
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad="=";
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);
}
if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
return ret;
}
// convert a base64 string to hex
function b64tohex(s) {
var ret = ""
var i;
var k = 0; // b64 state, 0-3
var slop;
var v;
for(i = 0; i < s.length; ++i) {
if(s.charAt(i) == b64pad) break;
v = b64map.indexOf(s.charAt(i));
if(v < 0) continue;
if(k == 0) {
ret += int2char(v >> 2);
slop = v & 3;
k = 1;
}
else if(k == 1) {
ret += int2char((slop << 2) | (v >> 4));
slop = v & 0xf;
k = 2;
}
else if(k == 2) {
ret += int2char(slop);
ret += int2char(v >> 2);
slop = v & 3;
k = 3;
}
else {
ret += int2char((slop << 2) | (v >> 4));
ret += int2char(v & 0xf);
k = 0;
}
}
if(k == 1)
ret += int2char(slop << 2);
return ret;
}
// convert a base64 string to a byte/number array
function b64toBA(s) {
//piggyback on b64tohex for now, optimize later
var h = b64tohex(s);
var i;
var a = new Array();
for(i = 0; 2*i < h.length; ++i) {
a[i] = parseInt(h.substring(2*i,2*i+2),16);
}
return a;
}
================================================
FILE: JavaScript/demo/js/cipher-core.js
================================================
/*
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
*/
/**
* Cipher core components.
*/
CryptoJS.lib.Cipher || (function (undefined) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var Base = C_lib.Base;
var WordArray = C_lib.WordArray;
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
var C_enc = C.enc;
var Utf8 = C_enc.Utf8;
var Base64 = C_enc.Base64;
var C_algo = C.algo;
var EvpKDF = C_algo.EvpKDF;
/**
* Abstract base cipher template.
*
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
*/
var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*
* @property {WordArray} iv The IV to use for this operation.
*/
cfg: Base.extend(),
/**
* Creates this cipher in encryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
*/
createEncryptor: function (key, cfg) {
return this.create(this._ENC_XFORM_MODE, key, cfg);
},
/**
* Creates this cipher in decryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
*/
createDecryptor: function (key, cfg) {
return this.create(this._DEC_XFORM_MODE, key, cfg);
},
/**
* Initializes a newly created cipher.
*
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @example
*
* var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
*/
init: function (xformMode, key, cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Store transform mode and key
this._xformMode = xformMode;
this._key = key;
// Set initial values
this.reset();
},
/**
* Resets this cipher to its initial state.
*
* @example
*
* cipher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-cipher logic
this._doReset();
},
/**
* Adds data to be encrypted or decrypted.
*
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
*
* @return {WordArray} The data after processing.
*
* @example
*
* var encrypted = cipher.process('data');
* var encrypted = cipher.process(wordArray);
*/
process: function (dataUpdate) {
// Append
this._append(dataUpdate);
// Process available blocks
return this._process();
},
/**
* Finalizes the encryption or decryption process.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
*
* @return {WordArray} The data after final processing.
*
* @example
*
* var encrypted = cipher.finalize();
* var encrypted = cipher.finalize('data');
* var encrypted = cipher.finalize(wordArray);
*/
finalize: function (dataUpdate) {
// Final data update
if (dataUpdate) {
this._append(dataUpdate);
}
// Perform concrete-cipher logic
var finalProcessedData = this._doFinalize();
return finalProcessedData;
},
keySize: 128/32,
ivSize: 128/32,
_ENC_XFORM_MODE: 1,
_DEC_XFORM_MODE: 2,
/**
* Creates shortcut functions to a cipher's object interface.
*
* @param {Cipher} cipher The cipher to create a helper for.
*
* @return {Object} An object with encrypt and decrypt shortcut functions.
*
* @static
*
* @example
*
* var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
*/
_createHelper: (function () {
function selectCipherStrategy(key) {
if (typeof key == 'string') {
return PasswordBasedCipher;
} else {
return SerializableCipher;
}
}
return function (cipher) {
return {
encrypt: function (message, key, cfg) {
return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
},
decrypt: function (ciphertext, key, cfg) {
return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
}
};
};
}())
});
/**
* Abstract base stream cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
*/
var StreamCipher = C_lib.StreamCipher = Cipher.extend({
_doFinalize: function () {
// Process partial blocks
var finalProcessedBlocks = this._process(!!'flush');
return finalProcessedBlocks;
},
blockSize: 1
});
/**
* Mode namespace.
*/
var C_mode = C.mode = {};
/**
* Abstract base block cipher mode template.
*/
var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
/**
* Creates this mode for encryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
*/
createEncryptor: function (cipher, iv) {
return this.Encryptor.create(cipher, iv);
},
/**
* Creates this mode for decryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
*/
createDecryptor: function (cipher, iv) {
return this.Decryptor.create(cipher, iv);
},
/**
* Initializes a newly created mode.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @example
*
* var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
*/
init: function (cipher, iv) {
this._cipher = cipher;
this._iv = iv;
}
});
/**
* Cipher Block Chaining mode.
*/
var CBC = C_mode.CBC = (function () {
/**
* Abstract base CBC mode.
*/
var CBC = BlockCipherMode.extend();
/**
* CBC encryptor.
*/
CBC.Encryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// XOR and encrypt
xorBlock.call(this, words, offset, blockSize);
cipher.encryptBlock(words, offset);
// Remember this block to use with next block
this._prevBlock = words.slice(offset, offset + blockSize);
}
});
/**
* CBC decryptor.
*/
CBC.Decryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// Remember this block to use with next block
var thisBlock = words.slice(offset, offset + blockSize);
// Decrypt and XOR
cipher.decryptBlock(words, offset);
xorBlock.call(this, words, offset, blockSize);
// This block becomes the previous block
this._prevBlock = thisBlock;
}
});
function xorBlock(words, offset, blockSize) {
// Shortcut
var iv = this._iv;
// Choose mixing block
if (iv) {
var block = iv;
// Remove IV for subsequent blocks
this._iv = undefined;
} else {
var block = this._prevBlock;
}
// XOR blocks
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= block[i];
}
}
return CBC;
}());
/**
* Padding namespace.
*/
var C_pad = C.pad = {};
/**
* PKCS #5/7 padding strategy.
*/
var Pkcs7 = C_pad.Pkcs7 = {
/**
* Pads data using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to pad.
* @param {number} blockSize The multiple that the data should be padded to.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.pad(wordArray, 4);
*/
pad: function (data, blockSize) {
// Shortcut
var blockSizeBytes = blockSize * 4;
// Count padding bytes
var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
// Create padding word
var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
// Create padding
var paddingWords = [];
for (var i = 0; i < nPaddingBytes; i += 4) {
paddingWords.push(paddingWord);
}
var padding = WordArray.create(paddingWords, nPaddingBytes);
// Add padding
data.concat(padding);
},
/**
* Unpads data that had been padded using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to unpad.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.unpad(wordArray);
*/
unpad: function (data) {
// Get number of padding bytes from last byte
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
// Remove padding
data.sigBytes -= nPaddingBytes;
}
};
/**
* Abstract base block cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
*/
var BlockCipher = C_lib.BlockCipher = Cipher.extend({
/**
* Configuration options.
*
* @property {Mode} mode The block mode to use. Default: CBC
* @property {Padding} padding The padding strategy to use. Default: Pkcs7
*/
cfg: Cipher.cfg.extend({
mode: CBC,
padding: Pkcs7
}),
reset: function () {
// Reset cipher
Cipher.reset.call(this);
// Shortcuts
var cfg = this.cfg;
var iv = cfg.iv;
var mode = cfg.mode;
// Reset block mode
if (this._xformMode == this._ENC_XFORM_MODE) {
var modeCreator = mode.createEncryptor;
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
var modeCreator = mode.createDecryptor;
// Keep at least one block in the buffer for unpadding
this._minBufferSize = 1;
}
this._mode = modeCreator.call(mode, this, iv && iv.words);
},
_doProcessBlock: function (words, offset) {
this._mode.processBlock(words, offset);
},
_doFinalize: function () {
// Shortcut
var padding = this.cfg.padding;
// Finalize
if (this._xformMode == this._ENC_XFORM_MODE) {
// Pad data
padding.pad(this._data, this.blockSize);
// Process final blocks
var finalProcessedBlocks = this._process(!!'flush');
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
// Process final blocks
var finalProcessedBlocks = this._process(!!'flush');
// Unpad data
padding.unpad(finalProcessedBlocks);
}
return finalProcessedBlocks;
},
blockSize: 128/32
});
/**
* A collection of cipher parameters.
*
* @property {WordArray} ciphertext The raw ciphertext.
* @property {WordArray} key The key to this ciphertext.
* @property {WordArray} iv The IV used in the ciphering operation.
* @property {WordArray} salt The salt used with a key derivation function.
* @property {Cipher} algorithm The cipher algorithm.
* @property {Mode} mode The block mode used in the ciphering operation.
* @property {Padding} padding The padding scheme used in the ciphering operation.
* @property {number} blockSize The block size of the cipher.
* @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
*/
var CipherParams = C_lib.CipherParams = Base.extend({
/**
* Initializes a newly created cipher params object.
*
* @param {Object} cipherParams An object with any of the possible cipher parameters.
*
* @example
*
* var cipherParams = CryptoJS.lib.CipherParams.create({
* ciphertext: ciphertextWordArray,
* key: keyWordArray,
* iv: ivWordArray,
* salt: saltWordArray,
* algorithm: CryptoJS.algo.AES,
* mode: CryptoJS.mode.CBC,
* padding: CryptoJS.pad.PKCS7,
* blockSize: 4,
* formatter: CryptoJS.format.OpenSSL
* });
*/
init: function (cipherParams) {
this.mixIn(cipherParams);
},
/**
* Converts this cipher params object to a string.
*
* @param {Format} formatter (Optional) The formatting strategy to use.
*
* @return {string} The stringified cipher params.
*
* @throws Error If neither the formatter nor the default formatter is set.
*
* @example
*
* var string = cipherParams + '';
* var string = cipherParams.toString();
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
*/
toString: function (formatter) {
return (formatter || this.formatter).stringify(this);
}
});
/**
* Format namespace.
*/
var C_format = C.format = {};
/**
* OpenSSL formatting strategy.
*/
var OpenSSLFormatter = C_format.OpenSSL = {
/**
* Converts a cipher params object to an OpenSSL-compatible string.
*
* @param {CipherParams} cipherParams The cipher params object.
*
* @return {string} The OpenSSL-compatible string.
*
* @static
*
* @example
*
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
*/
stringify: function (cipherParams) {
// Shortcuts
var ciphertext = cipherParams.ciphertext;
var salt = cipherParams.salt;
// Format
if (salt) {
var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
} else {
var wordArray = ciphertext;
}
return wordArray.toString(Base64);
},
/**
* Converts an OpenSSL-compatible string to a cipher params object.
*
* @param {string} openSSLStr The OpenSSL-compatible string.
*
* @return {CipherParams} The cipher params object.
*
* @static
*
* @example
*
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
*/
parse: function (openSSLStr) {
// Parse base64
var ciphertext = Base64.parse(openSSLStr);
// Shortcut
var ciphertextWords = ciphertext.words;
// Test for salt
if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
// Extract salt
var salt = WordArray.create(ciphertextWords.slice(2, 4));
// Remove salt from ciphertext
ciphertextWords.splice(0, 4);
ciphertext.sigBytes -= 16;
}
return CipherParams.create({ ciphertext: ciphertext, salt: salt });
}
};
/**
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
*/
var SerializableCipher = C_lib.SerializableCipher = Base.extend({
/**
* Configuration options.
*
* @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
*/
cfg: Base.extend({
format: OpenSSLFormatter
}),
/**
* Encrypts a message.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Encrypt
var encryptor = cipher.createEncryptor(key, cfg);
var ciphertext = encryptor.finalize(message);
// Shortcut
var cipherCfg = encryptor.cfg;
// Create and return serializable cipher params
return CipherParams.create({
ciphertext: ciphertext,
key: key,
iv: cipherCfg.iv,
algorithm: cipher,
mode: cipherCfg.mode,
padding: cipherCfg.padding,
blockSize: cipher.blockSize,
formatter: cfg.format
});
},
/**
* Decrypts serialized ciphertext.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Decrypt
var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
return plaintext;
},
/**
* Converts serialized ciphertext to CipherParams,
* else assumed CipherParams already and returns ciphertext unchanged.
*
* @param {CipherParams|string} ciphertext The ciphertext.
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
*
* @return {CipherParams} The unserialized ciphertext.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
*/
_parse: function (ciphertext, format) {
if (typeof ciphertext == 'string') {
return format.parse(ciphertext, this);
} else {
return ciphertext;
}
}
});
/**
* Key derivation function namespace.
*/
var C_kdf = C.kdf = {};
/**
* OpenSSL key derivation function.
*/
var OpenSSLKdf = C_kdf.OpenSSL = {
/**
* Derives a key and IV from a password.
*
* @param {string} password The password to derive from.
* @param {number} keySize The size in words of the key to generate.
* @param {number} ivSize The size in words of the IV to generate.
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
*
* @return {CipherParams} A cipher params object with the key, IV, and salt.
*
* @static
*
* @example
*
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
*/
execute: function (password, keySize, ivSize, salt) {
// Generate random salt
if (!salt) {
salt = WordArray.random(64/8);
}
// Derive key and IV
var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
// Separate key and IV
var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
key.sigBytes = keySize * 4;
// Return params
return CipherParams.create({ key: key, iv: iv, salt: salt });
}
};
/**
* A serializable cipher wrapper that derives the key from a password,
* and returns ciphertext as a serializable cipher params object.
*/
var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
/**
* Configuration options.
*
* @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
*/
cfg: SerializableCipher.cfg.extend({
kdf: OpenSSLKdf
}),
/**
* Encrypts a message using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
// Add IV to config
cfg.iv = derivedParams.iv;
// Encrypt
var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
// Mix in derived params
ciphertext.mixIn(derivedParams);
return ciphertext;
},
/**
* Decrypts serialized ciphertext using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
// Add IV to config
cfg.iv = derivedParams.iv;
// Decrypt
var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
return plaintext;
}
});
}());
================================================
FILE: JavaScript/demo/js/core.js
================================================
/*
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
*/
/**
* 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 if (thatWords.length > 0xffff) {
// Copy one word at a time
for (var i = 0; i < thatSigBytes; i += 4) {
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
}
} else {
// Copy all words at once
thisWords.push.apply(thisWords, thatWords);
}
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));
================================================
FILE: JavaScript/demo/js/crypto-1.1.js
================================================
/*! crypto-1.1.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* crypto.js - Cryptographic Algorithm Provider class
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/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.1.5 (2013-Oct-06)
* @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.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',
'sm3': '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',
'sm3': 'CryptoJS.algo.SM3'
};
/**
* 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
*/
this.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
*/
this.ripemd160 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
return md.digestString(s);
};
/*
* @since 1.1.2
*/
this.getCryptoJSMDByName = function(s) {
};
};
/**
* 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
* @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
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core.js"></script>
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/sha1.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
* md.updateString('aaa')
* var mdHex = md.digest()
*
* // SJCL(Stanford JavaScript Crypto Library) provider sample
* <script src="http://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
* md.updateString('aaa')
* var mdHex = md.digest()
*/
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
* @example
* // for SHA1
* md.setAlgAndProvider('sha1', 'cryptojs');
* // for RIPEMD160
* md.setAlgAndProvider('ripemd160', 'cryptojs');
*/
this.setAlgAndProvider = function(alg, prov) {
if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
// for cryptojs
if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:sm3:'.indexOf(alg) != -1 &&
prov == 'cryptojs') {
try {
this.md = eval(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);
}
}
};
/**
* 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.
* @example
* var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", prov: "cryptojs", "pass": "pass"});
* mac.updateString('aaa')
* var macHex = md.doFinal()
*/
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) {
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 = eval(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
* md.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
* md.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
* md.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
* md.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
* md.digestHex('0f2abd')
*/
this.doFinalHex = function(hex) {
throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
};
if (params !== undefined) {
if (params['pass'] !== undefined) {
this.pass = 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 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() {
if (this.algName.match(/^(.+)with(.+)$/)) {
this.mdAlgName = RegExp.$1.toLowerCase();
this.pubkeyAlgName = RegExp.$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:sm3:'.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.initSign = function(params) {
if (typeof params['ecprvhex'] == 'string' &&
typeof params['eccurvename'] == 'string') {
this.ecprvhex = params['ecprvhex'];
this.eccurvename = params['eccurvename'];
} else {
this.prvKey = params;
}
this.state = "SIGN";
};
this.initVerifyByPublicKey = function(params) {
if (typeof params['ecpubhex'] == 'string' &&
typeof params['eccurvename'] == 'string') {
this.ecpubhex = params['ecpubhex'];
this.eccurvename = params['eccurvename'];
} else if (params instanceof KJUR.crypto.ECDSA) {
this.pubKey = params;
} else if (params instanceof RSAKey) {
this.pubKey = params;
}
this.state = "VERIFY";
};
this.initVerifyByCertificatePEM = function(certPEM) {
var x509 = new X509();
x509.readCertPEM(certPEM);
this.pubKey = x509.subjectPublicKeyRSA;
this.state = "VERIFY";
};
this.updateString = function(str) {
this.md.updateString(str);
};
this.updateHex = function(hex) {
this.md.updateHex(hex);
};
this.sign = function() {
if(this.eccurvename != "sm2") {
this.sHashHex = this.md.digest();
}
if (typeof this.ecprvhex != "undefined" &&
typeof this.eccurvename != "undefined") {
if(this.eccurvename == "sm2")
{
var ec = new KJUR.crypto.SM3withSM2({curve: this.eccurvename});
var G = ec.ecparams['G'];
var Q = G.multiply(new BigInteger(this.ecprvhex, 16));
var pubKeyHex = Q.getX().toBigInteger().toRadix(16) + Q.getY().toBigInteger().toRadix(16);
var smDigest = new SM3Digest();
var z = new SM3Digest().GetZ(G, pubKeyHex);
var zValue = smDigest.GetWords(smDigest.GetHex(z).toString());
var rawData = CryptoJS.enc.Utf8.stringify(this.md.md._data);
rawData = CryptoJS.enc.Utf8.parse(rawData).toString();
rawData = smDigest.GetWords(rawData);
var smHash = new Array(smDigest.GetDigestSize());
smDigest.BlockUpdate(zValue, 0, zValue.length);
smDigest.BlockUpdate(rawData, 0, rawData.length);
smDigest.DoFinal(smHash, 0);
var hashHex = smDigest.GetHex(smHash).toString();
this.sHashHex = hashHex;
this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
}else {
var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
}
} else if (this.pubkeyAlgName == "rsaandmgf1") {
this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
this.mdAlgName,
this.pssSaltLen);
} else if (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 public key alg: " + this.pubkeyAlgName;
}
return this.hSign;
};
this.signString = function(str) {
this.updateString(str);
this.sign();
};
this.signHex = function(hex) {
this.updateHex(hex);
this.sign();
};
this.verify = function(hSigVal) {
if(this.eccurvename != "sm2") {
this.sHashHex = this.md.digest();
}
if (typeof this.ecpubhex != "undefined" &&
typeof this.eccurvename != "undefined") {
if(this.eccurvename == "sm2")
{
var ec = new KJUR.crypto.SM3withSM2({curve: this.eccurvename});
var G = ec.ecparams['G'];
var pubKeyHex = this.ecpubhex.substr(2, 128);
var smDigest = new SM3Digest();
var z = new SM3Digest().GetZ(G, pubKeyHex);
var zValue = smDigest.GetWords(smDigest.GetHex(z).toString());
var rawData = CryptoJS.enc.Utf8.stringify(this.md.md._data);
rawData = CryptoJS.enc.Utf8.parse(rawData).toString();
rawData = smDigest.GetWords(rawData);
var smHash = new Array(smDigest.GetDigestSize());
smDigest.BlockUpdate(zValue, 0, zValue.length);
smDigest.BlockUpdate(rawData, 0, rawData.length);
smDigest.DoFinal(smHash, 0);
var hashHex = smDigest.GetHex(smHash).toString();
this.sHashHex = hashHex;
return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
}else {
var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
}
} else if (this.pubkeyAlgName == "rsaandmgf1") {
return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal,
this.mdAlgName,
this.pssSaltLen);
} else if (this.pubkeyAlgName == "rsa") {
return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
} else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
} else if (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:
*
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;
};
/**
* Initialize this object for verifying with a public key
* @name initVerifyByPublicKey
* @memberOf KJUR.crypto.Signature
* @function
* @param {Object} param RSAKey object of public key or associative array for ECDSA
* @since 1.0.2
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* Public key information will be provided as 'param' parameter and the value will be
* following:
*
* @example
* sig.initVerifyByPublicKey(rsaPrvKey)
*/
this.initVerifyByPublicKey = function(rsaPubKey) {
throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
this.algProvName;
};
/**
* Initialize this object for verifying with a certficate
* @name initVerifyByCertificatePEM
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} certPEM PEM formatted string of certificate
* @since 1.0.2
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* @example
* sig.initVerifyByCertificatePEM(certPEM)
*/
this.initVerifyByCertificatePEM = function(certPEM) {
throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
this.algProvName;
};
/**
* Initialize this object for signing
* @name initSign
* @memberOf KJUR.crypto.Signature
* @function
* @param {Object} param RSAKey object of public key or associative array for ECDSA
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* Private key information will be provided as 'param' parameter and the value will be
* following:
*
* @example
* sig.initSign(prvKey)
*/
this.initSign = function(prvKey) {
throw "initSign(prvKey) 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 = new RSAKey();
prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
this.initSign(prvKey);
} catch (ex) {
throw "fatal error to load pem private key: " + ex;
}
}
}
}
};
/**
* 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
};
};
================================================
FILE: JavaScript/demo/js/ec-patch.js
================================================
/*! (c) Stefan Thomas | https://github.com/bitcoinjs/bitcoinjs-lib
*/
/*
* splitted from bitcoin-lib/ecdsa.js
*
* version 1.0.0 is the original of bitcoin-lib/ecdsa.js
*/
ECFieldElementFp.prototype.getByteLength = function () {
return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
};
ECPointFp.prototype.getEncoded = function (compressed) {
var integerToBytes = function(i, len) {
var bytes = i.toByteArrayUnsigned();
if (len < bytes.length) {
bytes = bytes.slice(bytes.length-len);
} else while (len > bytes.length) {
bytes.unshift(0);
}
return bytes;
};
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
// Get value as a 32-byte Buffer
// Fixed length based on a patch by bitaddress.org and Casascius
var enc = integerToBytes(x, 32);
if (compressed) {
if (y.isEven()) {
// Compressed even pubkey
// M = 02 || X
enc.unshift(0x02);
} else {
// Compressed uneven pubkey
// M = 03 || X
enc.unshift(0x03);
}
} else {
// Uncompressed pubkey
// M = 04 || X || Y
enc.unshift(0x04);
enc = enc.concat(integerToBytes(y, 32));
}
return enc;
};
ECPointFp.decodeFrom = function (curve, enc) {
var type = enc[0];
var dataLen = enc.length-1;
// Extract x and y as byte arrays
var xBa = enc.slice(1, 1 + dataLen/2);
var yBa = enc.slice(1 + dataLen/2, 1 + dataLen);
// Prepend zero byte to prevent interpretation as negative integer
xBa.unshift(0);
yBa.unshift(0);
// Convert to BigIntegers
var x = new BigInteger(xBa);
var y = new BigInteger(yBa);
// Return point
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
};
/*
* @since ec-patch.js 1.0.1
*/
ECPointFp.decodeFromHex = function (curve, encHex) {
var type = encHex.substr(0, 2); // shall be "04"
var dataLen = encHex.length - 2;
// Extract x and y as byte arrays
var xHex = encHex.substr(2, dataLen / 2);
var yHex = encHex.substr(2 + dataLen / 2, dataLen / 2);
// Convert to BigIntegers
var x = new BigInteger(xHex, 16);
var y = new BigInteger(yHex, 16);
// Return point
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
};
ECPointFp.prototype.add2D = function (b) {
if(this.isInfinity()) return b;
if(b.isInfinity()) return this;
if (this.x.equals(b.x)) {
if (this.y.equals(b.y)) {
// this = b, i.e. this must be doubled
return this.twice();
}
// this = -b, i.e. the result is the point at infinity
return this.curve.getInfinity();
}
var x_x = b.x.subtract(this.x);
var y_y = b.y.subtract(this.y);
var gamma = y_y.divide(x_x);
var x3 = gamma.square().subtract(this.x).subtract(b.x);
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
return new ECPointFp(this.curve, x3, y3);
};
ECPointFp.prototype.twice2D = function () {
if (this.isInfinity()) return this;
if (this.y.toBigInteger().signum() == 0) {
// if y1 == 0, then (x1, y1) == (x1, -y1)
// and hence this = -this and thus 2(x1, y1) == infinity
return this.curve.getInfinity();
}
var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO));
var x3 = gamma.square().subtract(this.x.multiply(TWO));
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
return new ECPointFp(this.curve, x3, y3);
};
ECPointFp.prototype.multiply2D = function (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.add2D(hBit ? this : neg);
}
}
return R;
};
ECPointFp.prototype.isOnCurve = function () {
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
var a = this.curve.getA().toBigInteger();
var b = this.curve.getB().toBigInteger();
var n = this.curve.getQ();
var lhs = y.multiply(y).mod(n);
var rhs = x.multiply(x).multiply(x)
.add(a.multiply(x)).add(b).mod(n);
return lhs.equals(rhs);
};
ECPointFp.prototype.toString = function () {
return '('+this.getX().toBigInteger().toString()+','+
this.getY().toBigInteger().toString()+')';
};
/**
* Validate an elliptic curve point.
*
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
*/
ECPointFp.prototype.validate = function () {
var n = this.curve.getQ();
// Check Q != O
if (this.isInfinity()) {
throw new Error("Point is at infinity.");
}
// Check coordinate bounds
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
if (x.compareTo(BigInteger.ONE) < 0 ||
x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
throw new Error('x coordinate out of bounds');
}
if (y.compareTo(BigInteger.ONE) < 0 ||
y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
throw new Error('y coordinate out of bounds');
}
// Check y^2 = x^3 + ax + b (mod n)
if (!this.isOnCurve()) {
throw new Error("Point is not on the curve.");
}
// Check nQ = 0 (Q is a scalar multiple of G)
if (this.multiply(n).isInfinity()) {
// TODO: This check doesn't work - fix.
throw new Error("Point is not a scalar multiple of G.");
}
return true;
};
================================================
FILE: JavaScript/demo/js/ec.js
================================================
/*! (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;
================================================
FILE: JavaScript/demo/js/ecdsa-modified-1.0.js
================================================
/*! ecdsa-modified-1.0.4.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
*/
/*
* ecdsa-modified.js - modified Bitcoin.ECDSA class
*
* Copyright (c) 2013 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 1.0.4 (2013-Oct-06)
* @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";
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;
}
/**
* 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 = KJUR.crypto.ECDSA({'curve': 'secp256r1'});
* var keypair = ec.generateKeyPairHex();
* var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
* var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
*/
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 = 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 = 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};
};
/*
* 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 = 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 = 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) {
// 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 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV1);
var hS = ASN1HEX.getHexOfV_AtObj(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;
if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8)
hR = hR.substr(2);
if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8)
hS = hS.substr(2);
if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
throw "unknown ECDSA sig r length error";
if ((((hS.length / 2) * 8) % (16 * 8)) != 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 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();
};
================================================
FILE: JavaScript/demo/js/ecparam-1.0.js
================================================
/*! 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.
* http://kjur.github.com/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
KJUR.crypto.ECParameterDB.regist(
"sm2", // name
256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", // p
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", // a
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", // b
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", // n
"1", // h
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", // gx
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", // gy
["sm2", "SM2"]); // alias
================================================
FILE: JavaScript/demo/js/enc-base64.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64 encoding strategy.
*/
var Base64 = C_enc.Base64 = {
/**
* Converts a word array to a Base64 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Base64 string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64 string to a word array.
*
* @param {string} base64Str The Base64 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
*/
parse: function (base64Str) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = this._map;
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex != -1) {
base64StrLength = paddingIndex;
}
}
// Convert
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2);
var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2);
words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
};
}());
================================================
FILE: JavaScript/demo/js/fingerprint.js
================================================
/*
* fingerprintJS 0.5.4 - Fast browser fingerprint library
* https://github.com/Valve/fingerprintjs
* Copyright (c) 2013 Valentin Vasilyev (valentin.vasilyev@outlook.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
;(function (name, context, definition) {
if (typeof module !== 'undefined' && module.exports) { module.exports = definition(); }
else if (typeof define === 'function' && define.amd) { define(definition); }
else { context[name] = definition(); }
})('Fingerprint', this, function () {
'use strict';
var Fingerprint = function (options) {
var nativeForEach, nativeMap;
nativeForEach = Array.prototype.forEach;
nativeMap = Array.prototype.map;
this.each = function (obj, iterator, context) {
if (obj === null) {
return;
}
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
if (iterator.call(context, obj[i], i, obj) === {}) return;
}
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (iterator.call(context, obj[key], key, obj) === {}) return;
}
}
}
};
this.map = function(obj, iterator, context) {
var results = [];
// Not using strict equality so that this acts as a
// shortcut to checking for `null` and `undefined`.
if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
this.each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list);
});
return results;
};
if (typeof options == 'object'){
this.hasher = options.hasher;
this.screen_resolution = options.screen_resolution;
this.screen_orientation = options.screen_orientation;
this.canvas = options.canvas;
this.ie_activex = options.ie_activex;
} else if(typeof options == 'function'){
this.hasher = options;
}
};
Fingerprint.prototype = {
get: function(){
var keys = [];
keys.push(navigator.userAgent);
keys.push(navigator.language);
keys.push(screen.colorDepth);
if (this.screen_resolution) {
var resolution = this.getScreenResolution();
if (typeof resolution !== 'undefined'){ // headless browsers, such as phantomjs
keys.push(resolution.join('x'));
}
}
keys.push(new Date().getTimezoneOffset());
keys.push(this.hasSessionStorage());
keys.push(this.hasLocalStorage());
keys.push(!!window.indexedDB);
//body might not be defined at this point or removed programmatically
if(document.body){
keys.push(typeof(document.body.addBehavior));
} else {
keys.push(typeof undefined);
}
keys.push(typeof(window.openDatabase));
keys.push(navigator.cpuClass);
keys.push(navigator.platform);
keys.push(navigator.doNotTrack);
keys.push(this.getPluginsString());
if(this.canvas && this.isCanvasSupported()){
keys.push(this.getCanvasFingerprint());
}
if(this.hasher){
return this.hasher(keys.join('###'), 31);
} else {
return this.murmurhash3_32_gc(keys.join('###'), 31);
}
},
/**
* JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
*
* @author Gary Court
* @see http://github.com/garycourt/murmurhash-js
* @author Austin Appleby
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} key ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
murmurhash3_32_gc: function(key, seed) {
var remainder, bytes, h1, h1b, c1, c2, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
},
// https://bugzilla.mozilla.org/show_bug.cgi?id=781447
hasLocalStorage: function () {
try{
return !!window.localStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
hasSessionStorage: function () {
try{
return !!window.sessionStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
isCanvasSupported: function () {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
},
isIE: function () {
if(navigator.appName === 'Microsoft Internet Explorer') {
return true;
} else if(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)){// IE 11
return true;
}
return false;
},
getPluginsString: function () {
if(this.isIE() && this.ie_activex){
return this.getIEPluginsString();
} else {
return this.getRegularPluginsString();
}
},
getRegularPluginsString: function () {
return this.map(navigator.plugins, function (p) {
var mimeTypes = this.map(p, function(mt){
return [mt.type, mt.suffixes].join('~');
}).join(',');
return [p.name, p.description, mimeTypes].join('::');
}, this).join(';');
},
getIEPluginsString: function () {
if(window.ActiveXObject){
var names = ['ShockwaveFlash.ShockwaveFlash',//flash plugin
'AcroPDF.PDF', // Adobe PDF reader 7+
'PDF.PdfCtrl', // Adobe PDF reader 6 and earlier, brrr
'QuickTime.QuickTime', // QuickTime
// 5 versions of real players
'rmocx.RealPlayer G2 Control',
'rmocx.RealPlayer G2 Control.1',
'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
'RealPlayer',
'SWCtl.SWCtl', // ShockWave player
'WMPlayer.OCX', // Windows media player
'AgControl.AgControl', // Silverlight
'Skype.Detection'];
// starting to detect plugins in IE
return this.map(names, function(name){
try{
new ActiveXObject(name);
return name;
} catch(e){
return null;
}
}).join(';');
} else {
return ""; // behavior prior version 0.5.0, not breaking backwards compat.
}
},
getScreenResolution: function () {
var resolution;
if(this.screen_orientation){
resolution = (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height];
}else{
resolution = [screen.height, screen.width];
}
return resolution;
},
getCanvasFingerprint: function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// https://www.browserleaks.com/canvas#how-does-it-work
var txt = 'http://valve.github.io';
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
ctx.fillText(txt, 4, 17);
return canvas.toDataURL();
}
};
return Fingerprint;
});
================================================
FILE: JavaScript/demo/js/fingerprint2.js
================================================
/*
* Fingerprintjs2 1.4.2 - Modern & flexible browser fingerprint library v2
* https://github.com/Valve/fingerprintjs2
* Copyright (c) 2015 Valentin Vasilyev (valentin.vasilyev@outlook.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VALENTIN VASILYEV BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function (name, context, definition) {
"use strict";
if (typeof define === "function" && define.amd) { define(definition); }
else if (typeof module !== "undefined" && module.exports) { module.exports = definition(); }
else if (context.exports) { context.exports = definition(); }
else { context[name] = definition(); }
})("Fingerprint2", this, function() {
"use strict";
// This will only be polyfilled for IE8 and older
// Taken from Mozilla MDC
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(searchElement, fromIndex) {
var k;
if (this == null) {
throw new TypeError("'this' is null or undefined");
}
var O = Object(this);
var len = O.length >>> 0;
if (len === 0) {
return -1;
}
var n = +fromIndex || 0;
if (Math.abs(n) === Infinity) {
n = 0;
}
if (n >= len) {
return -1;
}
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
while (k < len) {
if (k in O && O[k] === searchElement) {
return k;
}
k++;
}
return -1;
};
}
var Fingerprint2 = function(options) {
if (!(this instanceof Fingerprint2)) {
return new Fingerprint2(options);
}
var defaultOptions = {
swfContainerId: "fingerprintjs2",
swfPath: "flash/compiled/FontList.swf",
detectScreenOrientation: true,
sortPluginsFor: [/palemoon/i],
userDefinedFonts: []
};
this.options = this.extend(options, defaultOptions);
this.nativeForEach = Array.prototype.forEach;
this.nativeMap = Array.prototype.map;
};
Fingerprint2.prototype = {
extend: function(source, target) {
if (source == null) { return target; }
for (var k in source) {
if(source[k] != null && target[k] !== source[k]) {
target[k] = source[k];
}
}
return target;
},
log: function(msg){
if(window.console){
console.log(msg);
}
},
get: function(done){
var keys = [];
keys = this.userAgentKey(keys);
keys = this.languageKey(keys);
keys = this.colorDepthKey(keys);
keys = this.pixelRatioKey(keys);
keys = this.screenResolutionKey(keys);
keys = this.availableScreenResolutionKey(keys);
keys = this.timezoneOffsetKey(keys);
keys = this.sessionStorageKey(keys);
keys = this.localStorageKey(keys);
keys = this.indexedDbKey(keys);
keys = this.addBehaviorKey(keys);
keys = this.openDatabaseKey(keys);
keys = this.cpuClassKey(keys);
keys = this.platformKey(keys);
keys = this.doNotTrackKey(keys);
keys = this.pluginsKey(keys);
keys = this.canvasKey(keys);
keys = this.webglKey(keys);
keys = this.adBlockKey(keys);
keys = this.hasLiedLanguagesKey(keys);
keys = this.hasLiedResolutionKey(keys);
keys = this.hasLiedOsKey(keys);
keys = this.hasLiedBrowserKey(keys);
keys = this.touchSupportKey(keys);
var that = this;
this.fontsKey(keys, function(newKeys){
var values = [];
that.each(newKeys, function(pair) {
var value = pair.value;
if (typeof pair.value.join !== "undefined") {
value = pair.value.join(";");
}
values.push(value);
});
var murmur = that.x64hash128(values.join("~~~"), 31);
return done(murmur, newKeys);
});
},
userAgentKey: function(keys) {
if(!this.options.excludeUserAgent) {
keys.push({key: "user_agent", value: this.getUserAgent()});
}
return keys;
},
// for tests
getUserAgent: function(){
return navigator.userAgent;
},
languageKey: function(keys) {
if(!this.options.excludeLanguage) {
// IE 9,10 on Windows 10 does not have the `navigator.language` property any longer
keys.push({ key: "language", value: navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage || "" });
}
return keys;
},
colorDepthKey: function(keys) {
if(!this.options.excludeColorDepth) {
keys.push({key: "color_depth", value: screen.colorDepth || -1});
}
return keys;
},
pixelRatioKey: function(keys) {
if(!this.options.excludePixelRatio) {
keys.push({key: "pixel_ratio", value: this.getPixelRatio()});
}
return keys;
},
getPixelRatio: function() {
return window.devicePixelRatio || "";
},
screenResolutionKey: function(keys) {
if(!this.options.excludeScreenResolution) {
return this.getScreenResolution(keys);
}
return keys;
},
getScreenResolution: function(keys) {
var resolution;
if(this.options.detectScreenOrientation) {
resolution = (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height];
} else {
resolution = [screen.width, screen.height];
}
if(typeof resolution !== "undefined") { // headless browsers
keys.push({key: "resolution", value: resolution});
}
return keys;
},
availableScreenResolutionKey: function(keys) {
if (!this.options.excludeAvailableScreenResolution) {
return this.getAvailableScreenResolution(keys);
}
return keys;
},
getAvailableScreenResolution: function(keys) {
var available;
if(screen.availWidth && screen.availHeight) {
if(this.options.detectScreenOrientation) {
available = (screen.availHeight > screen.availWidth) ? [screen.availHeight, screen.availWidth] : [screen.availWidth, screen.availHeight];
} else {
available = [screen.availHeight, screen.availWidth];
}
}
if(typeof available !== "undefined") { // headless browsers
keys.push({key: "available_resolution", value: available});
}
return keys;
},
timezoneOffsetKey: function(keys) {
if(!this.options.excludeTimezoneOffset) {
keys.push({key: "timezone_offset", value: new Date().getTimezoneOffset()});
}
return keys;
},
sessionStorageKey: function(keys) {
if(!this.options.excludeSessionStorage && this.hasSessionStorage()) {
keys.push({key: "session_storage", value: 1});
}
return keys;
},
localStorageKey: function(keys) {
if(!this.options.excludeSessionStorage && this.hasLocalStorage()) {
keys.push({key: "local_storage", value: 1});
}
return keys;
},
indexedDbKey: function(keys) {
if(!this.options.excludeIndexedDB && this.hasIndexedDB()) {
keys.push({key: "indexed_db", value: 1});
}
return keys;
},
addBehaviorKey: function(keys) {
//body might not be defined at this point or removed programmatically
if(document.body && !this.options.excludeAddBehavior && document.body.addBehavior) {
keys.push({key: "add_behavior", value: 1});
}
return keys;
},
openDatabaseKey: function(keys) {
if(!this.options.excludeOpenDatabase && window.openDatabase) {
keys.push({key: "open_database", value: 1});
}
return keys;
},
cpuClassKey: function(keys) {
if(!this.options.excludeCpuClass) {
keys.push({key: "cpu_class", value: this.getNavigatorCpuClass()});
}
return keys;
},
platformKey: function(keys) {
if(!this.options.excludePlatform) {
keys.push({key: "navigator_platform", value: this.getNavigatorPlatform()});
}
return keys;
},
doNotTrackKey: function(keys) {
if(!this.options.excludeDoNotTrack) {
keys.push({key: "do_not_track", value: this.getDoNotTrack()});
}
return keys;
},
canvasKey: function(keys) {
if(!this.options.excludeCanvas && this.isCanvasSupported()) {
keys.push({key: "canvas", value: this.getCanvasFp()});
}
return keys;
},
webglKey: function(keys) {
if(this.options.excludeWebGL) {
if(typeof NODEBUG === "undefined"){
this.log("Skipping WebGL fingerprinting per excludeWebGL configuration option");
}
return keys;
}
if(!this.isWebGlSupported()) {
if(typeof NODEBUG === "undefined"){
this.log("Skipping WebGL fingerprinting because it is not supported in this browser");
}
return keys;
}
keys.push({key: "webgl", value: this.getWebglFp()});
return keys;
},
adBlockKey: function(keys){
if(!this.options.excludeAdBlock) {
keys.push({key: "adblock", value: this.getAdBlock()});
}
return keys;
},
hasLiedLanguagesKey: function(keys){
if(!this.options.excludeHasLiedLanguages){
keys.push({key: "has_lied_languages", value: this.getHasLiedLanguages()});
}
return keys;
},
hasLiedResolutionKey: function(keys){
if(!this.options.excludeHasLiedResolution){
keys.push({key: "has_lied_resolution", value: this.getHasLiedResolution()});
}
return keys;
},
hasLiedOsKey: function(keys){
if(!this.options.excludeHasLiedOs){
keys.push({key: "has_lied_os", value: this.getHasLiedOs()});
}
return keys;
},
hasLiedBrowserKey: function(keys){
if(!this.options.excludeHasLiedBrowser){
keys.push({key: "has_lied_browser", value: this.getHasLiedBrowser()});
}
return keys;
},
fontsKey: function(keys, done) {
if (this.options.excludeJsFonts) {
return this.flashFontsKey(keys, done);
}
return this.jsFontsKey(keys, done);
},
// flash fonts (will increase fingerprinting time 20X to ~ 130-150ms)
flashFontsKey: function(keys, done) {
if(this.options.excludeFlashFonts) {
if(typeof NODEBUG === "undefined"){
this.log("Skipping flash fonts detection per excludeFlashFonts configuration option");
}
return done(keys);
}
// we do flash if swfobject is loaded
if(!this.hasSwfObjectLoaded()){
if(typeof NODEBUG === "undefined"){
this.log("Swfobject is not detected, Flash fonts enumeration is skipped");
}
return done(keys);
}
if(!this.hasMinFlashInstalled()){
if(typeof NODEBUG === "undefined"){
this.log("Flash is not installed, skipping Flash fonts enumeration");
}
return done(keys);
}
if(typeof this.options.swfPath === "undefined"){
if(typeof NODEBUG === "undefined"){
this.log("To use Flash fonts detection, you must pass a valid swfPath option, skipping Flash fonts enumeration");
}
return done(keys);
}
this.loadSwfAndDetectFonts(function(fonts){
keys.push({key: "swf_fonts", value: fonts.join(";")});
done(keys);
});
},
// kudos to http://www.lalit.org/lab/javascript-css-font-detect/
jsFontsKey: function(keys, done) {
var that = this;
// doing js fonts detection in a pseudo-async fashion
return setTimeout(function(){
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ["monospace", "sans-serif", "serif"];
var fontList = [
"Andale Mono", "Arial", "Arial Black", "Arial Hebrew", "Arial MT", "Arial Narrow", "Arial Rounded MT Bold", "Arial Unicode MS",
"Bitstream Vera Sans Mono", "Book Antiqua", "Bookman Old Style",
"Calibri", "Cambria", "Cambria Math", "Century", "Century Gothic", "Century Schoolbook", "Comic Sans", "Comic Sans MS", "Consolas", "Courier", "Courier New",
"Garamond", "Geneva", "Georgia",
"Helvetica", "Helvetica Neue",
"Impact",
"Lucida Bright", "Lucida Calligraphy", "Lucida Console", "Lucida Fax", "LUCIDA GRANDE", "Lucida Handwriting", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode",
"Microsoft Sans Serif", "Monaco", "Monotype Corsiva", "MS Gothic", "MS Outlook", "MS PGothic", "MS Reference Sans Serif", "MS Sans Serif", "MS Serif", "MYRIAD", "MYRIAD PRO",
"Palatino", "Palatino Linotype",
"Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Symbol",
"Tahoma", "Times", "Times New Roman", "Times New Roman PS", "Trebuchet MS",
"Verdana", "Wingdings", "Wingdings 2", "Wingdings 3"
];
var extendedFontList = [
"Abadi MT Condensed Light", "Academy Engraved LET", "ADOBE CASLON PRO", "Adobe Garamond", "ADOBE GARAMOND PRO", "Agency FB", "Aharoni", "Albertus Extra Bold", "Albertus Medium", "Algerian", "Amazone BT", "American Typewriter",
"American Typewriter Condensed", "AmerType Md BT", "Andalus", "Angsana New", "AngsanaUPC", "Antique Olive", "Aparajita", "Apple Chancery", "Apple Color Emoji", "Apple SD Gothic Neo", "Arabic Typesetting", "ARCHER",
"ARNO PRO", "Arrus BT", "Aurora Cn BT", "AvantGarde Bk BT", "AvantGarde Md BT", "AVENIR", "Ayuthaya", "Bandy", "Bangla Sangam MN", "Bank Gothic", "BankGothic Md BT", "Baskerville",
"Baskerville Old Face", "Batang", "BatangChe", "Bauer Bodoni", "Bauhaus 93", "Bazooka", "Bell MT", "Bembo", "Benguiat Bk BT", "Berlin Sans FB", "Berlin Sans FB Demi", "Bernard MT Condensed", "BernhardFashion BT", "BernhardMod BT", "Big Caslon", "BinnerD",
"Blackadder ITC", "BlairMdITC TT", "Bodoni 72", "Bodoni 72 Oldstyle", "Bodoni 72 Smallcaps", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed",
"Bookshelf Symbol 7", "Boulder", "Bradley Hand", "Bradley Hand ITC", "Bremen Bd BT", "Britannic Bold", "Broadway", "Browallia New", "BrowalliaUPC", "Brush Script MT", "Californian FB", "Calisto MT", "Calligrapher", "Candara",
"CaslonOpnface BT", "Castellar", "Centaur", "Cezanne", "CG Omega", "CG Times", "Chalkboard", "Chalkboard SE", "Chalkduster", "Charlesworth", "Charter Bd BT", "Charter BT", "Chaucer",
"ChelthmITC Bk BT", "Chiller", "Clarendon", "Clarendon Condensed", "CloisterBlack BT", "Cochin", "Colonna MT", "Constantia", "Cooper Black", "Copperplate", "Copperplate Gothic", "Copperplate Gothic Bold",
"Copperplate Gothic Light", "CopperplGoth Bd BT", "Corbel", "Cordia New", "CordiaUPC", "Cornerstone", "Coronet", "Cuckoo", "Curlz MT", "DaunPenh", "Dauphin", "David", "DB LCD Temp", "DELICIOUS", "Denmark",
"DFKai-SB", "Didot", "DilleniaUPC", "DIN", "DokChampa", "Dotum", "DotumChe", "Ebrima", "Edwardian Script ITC", "Elephant", "English 111 Vivace BT", "Engravers MT", "EngraversGothic BT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC",
"EucrosiaUPC", "Euphemia", "Euphemia UCAS", "EUROSTILE", "Exotc350 Bd BT", "FangSong", "Felix Titling", "Fixedsys", "FONTIN", "Footlight MT Light", "Forte",
"FrankRuehl", "Fransiscan", "Freefrm721 Blk BT", "FreesiaUPC", "Freestyle Script", "French Script MT", "FrnkGothITC Bk BT", "Fruitger", "FRUTIGER",
"Futura", "Futura Bk BT", "Futura Lt BT", "Futura Md BT", "Futura ZBlk BT", "FuturaBlack BT", "Gabriola", "Galliard BT", "Gautami", "Geeza Pro", "Geometr231 BT", "Geometr231 Hv BT", "Geometr231 Lt BT", "GeoSlab 703 Lt BT",
"GeoSlab 703 XBd BT", "Gigi", "Gill Sans", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed", "Gisha", "Gloucester MT Extra Condensed", "GOTHAM", "GOTHAM BOLD",
"Goudy Old Style", "Goudy Stout", "GoudyHandtooled BT", "GoudyOLSt BT", "Gujarati Sangam MN", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "Gurmukhi MN", "Haettenschweiler", "Harlow Solid Italic", "Harrington", "Heather", "Heiti SC", "Heiti TC", "HELV",
"Herald", "High Tower Text", "Hiragino Kaku Gothic ProN", "Hiragino Mincho ProN", "Hoefler Text", "Humanst 521 Cn BT", "Humanst521 BT", "Humanst521 Lt BT", "Imprint MT Shadow", "Incised901 Bd BT", "Incised901 BT",
"Incised901 Lt BT", "INCONSOLATA", "Informal Roman", "Informal011 BT", "INTERSTATE", "IrisUPC", "Iskoola Pota", "JasmineUPC", "Jazz LET", "Jenson", "Jester", "Jokerman", "Juice ITC", "Kabel Bk BT", "Kabel Ult BT", "Kailasa", "KaiTi", "Kalinga", "Kannada Sangam MN",
"Kartika", "Kaufmann Bd BT", "Kaufmann BT", "Khmer UI", "KodchiangUPC", "Kokila", "Korinna BT", "Kristen ITC", "Krungthep", "Kunstler Script", "Lao UI", "Latha", "Leelawadee", "Letter Gothic", "Levenim MT", "LilyUPC", "Lithograph", "Lithograph Light", "Long Island",
"Lydian BT", "Magneto", "Maiandra GD", "Malayalam Sangam MN", "Malgun Gothic",
"Mangal", "Marigold", "Marion", "Marker Felt", "Market", "Marlett", "Matisse ITC", "Matura MT Script Capitals", "Meiryo", "Meiryo UI", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le",
"Microsoft Uighur", "Microsoft YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU_HKSCS", "MingLiU_HKSCS-ExtB", "MingLiU-ExtB", "Minion", "Minion Pro", "Miriam", "Miriam Fixed", "Mistral", "Modern", "Modern No. 20", "Mona Lisa Solid ITC TT", "Mongolian Baiti",
"MONO", "MoolBoran", "Mrs Eaves", "MS LineDraw", "MS Mincho", "MS PMincho", "MS Reference Specialty", "MS UI Gothic", "MT Extra", "MUSEO", "MV Boli",
"Nadeem", "Narkisim", "NEVIS", "News Gothic", "News GothicMT", "NewsGoth BT", "Niagara Engraved", "Niagara Solid", "Noteworthy", "NSimSun", "Nyala", "OCR A Extended", "Old Century", "Old English Text MT", "Onyx", "Onyx BT", "OPTIMA", "Oriya Sangam MN",
"OSAKA", "OzHandicraft BT", "Palace Script MT", "Papyrus", "Parchment", "Party LET", "Pegasus", "Perpetua", "Perpetua Titling MT", "PetitaBold", "Pickwick", "Plantagenet Cherokee", "Playbill", "PMingLiU", "PMingLiU-ExtB",
"Poor Richard", "Poster", "PosterBodoni BT", "PRINCETOWN LET", "Pristina", "PTBarnum BT", "Pythagoras", "Raavi", "Rage Italic", "Ravie", "Ribbon131 Bd BT", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Rod", "Roman", "Sakkal Majalla",
"Santa Fe LET", "Savoye LET", "Sceptre", "Script", "Script MT Bold", "SCRIPTINA", "Serifa", "Serifa BT", "Serifa Th BT", "ShelleyVolante BT", "Sherwood",
"Shonar Bangla", "Showcard Gothic", "Shruti", "Signboard", "SILKSCREEN", "SimHei", "Simplified Arabic", "Simplified Arabic Fixed", "SimSun", "SimSun-ExtB", "Sinhala Sangam MN", "Sketch Rockwell", "Skia", "Small Fonts", "Snap ITC", "Snell Roundhand", "Socket",
"Souvenir Lt BT", "Staccato222 BT", "Steamer", "Stencil", "Storybook", "Styllo", "Subway", "Swis721 BlkEx BT", "Swiss911 XCm BT", "Sylfaen", "Synchro LET", "System", "Tamil Sangam MN", "Technical", "Teletype", "Telugu Sangam MN", "Tempus Sans ITC",
"Terminal", "Thonburi", "Traditional Arabic", "Trajan", "TRAJAN PRO", "Tristan", "Tubular", "Tunga", "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold",
"TypoUpright BT", "Unicorn", "Univers", "Univers CE 55 Medium", "Univers Condensed", "Utsaah", "Vagabond", "Vani", "Vijaya", "Viner Hand ITC", "VisualUI", "Vivaldi", "Vladimir Script", "Vrinda", "Westminster", "WHITNEY", "Wide Latin",
"ZapfEllipt BT", "ZapfHumnst BT", "ZapfHumnst Dm BT", "Zapfino", "Zurich BlkEx BT", "Zurich Ex BT", "ZWAdobeF"];
if(that.options.extendedJsFonts) {
fontList = fontList.concat(extendedFontList);
}
fontList = fontList.concat(that.options.userDefinedFonts);
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = "72px";
var h = document.getElementsByTagName("body")[0];
// div to load spans for the base fonts
var baseFontsDiv = document.createElement("div");
// div to load spans for the fonts to detect
var fontsDiv = document.createElement("div");
var defaultWidth = {};
var defaultHeight = {};
// creates a span where the fonts will be loaded
var createSpan = function() {
var s = document.createElement("span");
/*
* We need this css as in some weird browser this
* span elements shows up for a microSec which creates a
* bad user experience
*/
s.style.position = "absolute";
s.style.left = "-9999px";
s.style.fontSize = testSize;
s.style.lineHeight = "normal";
s.innerHTML = testString;
return s;
};
// creates a span and load the font to detect and a base font for fallback
var createSpanWithFonts = function(fontToDetect, baseFont) {
var s = createSpan();
s.style.fontFamily = "'" + fontToDetect + "'," + baseFont;
return s;
};
// creates spans for the base fonts and adds them to baseFontsDiv
var initializeBaseFontsSpans = function() {
var spans = [];
for (var index = 0, length = baseFonts.length; index < length; index++) {
var s = createSpan();
s.style.fontFamily = baseFonts[index];
baseFontsDiv.appendChild(s);
spans.push(s);
}
return spans;
};
// creates spans for the fonts to detect and adds them to fontsDiv
var initializeFontsSpans = function() {
var spans = {};
for(var i = 0, l = fontList.length; i < l; i++) {
var fontSpans = [];
for(var j = 0, numDefaultFonts = baseFonts.length; j < numDefaultFonts; j++) {
var s = createSpanWithFonts(fontList[i], baseFonts[j]);
fontsDiv.appendChild(s);
fontSpans.push(s);
}
spans[fontList[i]] = fontSpans; // Stores {fontName : [spans for that font]}
}
return spans;
};
// checks if a font is available
var isFontAvailable = function(fontSpans) {
var detected = false;
for(var i = 0; i < baseFonts.length; i++) {
detected = (fontSpans[i].offsetWidth !== defaultWidth[baseFonts[i]] || fontSpans[i].offsetHeight !== defaultHeight[baseFonts[i]]);
if(detected) {
return detected;
}
}
return detected;
};
// create spans for base fonts
var baseFontsSpans = initializeBaseFontsSpans();
// add the spans to the DOM
h.appendChild(baseFontsDiv);
// get the default width for the three base fonts
for (var index = 0, length = baseFonts.length; index < length; index++) {
defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font
defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font
}
// create spans for fonts to detect
var fontsSpans = initializeFontsSpans();
// add all the spans to the DOM
h.appendChild(fontsDiv);
// check available fonts
var available = [];
for(var i = 0, l = fontList.length; i < l; i++) {
if(isFontAvailable(fontsSpans[fontList[i]])) {
available.push(fontList[i]);
}
}
// remove spans from DOM
h.removeChild(fontsDiv);
h.removeChild(baseFontsDiv);
keys.push({key: "js_fonts", value: available});
done(keys);
}, 1);
},
pluginsKey: function(keys) {
if(!this.options.excludePlugins){
if(this.isIE()){
if(!this.options.excludeIEPlugins) {
keys.push({key: "ie_plugins", value: this.getIEPlugins()});
}
} else {
keys.push({key: "regular_plugins", value: this.getRegularPlugins()});
}
}
return keys;
},
getRegularPlugins: function () {
var plugins = [];
for(var i = 0, l = navigator.plugins.length; i < l; i++) {
plugins.push(navigator.plugins[i]);
}
// sorting plugins only for those user agents, that we know randomize the plugins
// every time we try to enumerate them
if(this.pluginsShouldBeSorted()) {
plugins = plugins.sort(function(a, b) {
if(a.name > b.name){ return 1; }
if(a.name < b.name){ return -1; }
return 0;
});
}
return this.map(plugins, function (p) {
var mimeTypes = this.map(p, function(mt){
return [mt.type, mt.suffixes].join("~");
}).join(",");
return [p.name, p.description, mimeTypes].join("::");
}, this);
},
getIEPlugins: function () {
var result = [];
if((Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(window, "ActiveXObject")) || ("ActiveXObject" in window)) {
var names = [
"AcroPDF.PDF", // Adobe PDF reader 7+
"Adodb.Stream",
"AgControl.AgControl", // Silverlight
"DevalVRXCtrl.DevalVRXCtrl.1",
"MacromediaFlashPaper.MacromediaFlashPaper",
"Msxml2.DOMDocument",
"Msxml2.XMLHTTP",
"PDF.PdfCtrl", // Adobe PDF reader 6 and earlier, brrr
"QuickTime.QuickTime", // QuickTime
"QuickTimeCheckObject.QuickTimeCheck.1",
"RealPlayer",
"RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)",
"RealVideo.RealVideo(tm) ActiveX Control (32-bit)",
"Scripting.Dictionary",
"SWCtl.SWCtl", // ShockWave player
"Shell.UIHelper",
"ShockwaveFlash.ShockwaveFlash", //flash plugin
"Skype.Detection",
"TDCCtl.TDCCtl",
"WMPlayer.OCX", // Windows media player
"rmocx.RealPlayer G2 Control",
"rmocx.RealPlayer G2 Control.1"
];
// starting to detect plugins in IE
result = this.map(names, function(name) {
try {
new ActiveXObject(name); // eslint-disable-no-new
return name;
} catch(e) {
return null;
}
});
}
if(navigator.plugins) {
result = result.concat(this.getRegularPlugins());
}
return result;
},
pluginsShouldBeSorted: function () {
var should = false;
for(var i = 0, l = this.options.sortPluginsFor.length; i < l; i++) {
var re = this.options.sortPluginsFor[i];
if(navigator.userAgent.match(re)) {
should = true;
break;
}
}
return should;
},
touchSupportKey: function (keys) {
if(!this.options.excludeTouchSupport){
keys.push({key: "touch_support", value: this.getTouchSupport()});
}
return keys;
},
hasSessionStorage: function () {
try {
return !!window.sessionStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
// https://bugzilla.mozilla.org/show_bug.cgi?id=781447
hasLocalStorage: function () {
try {
return !!window.localStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
hasIndexedDB: function (){
return !!window.indexedDB;
},
getNavigatorCpuClass: function () {
if(navigator.cpuClass){
return navigator.cpuClass;
} else {
return "unknown";
}
},
getNavigatorPlatform: function () {
if(navigator.platform) {
return navigator.platform;
} else {
return "unknown";
}
},
getDoNotTrack: function () {
if(navigator.doNotTrack) {
return navigator.doNotTrack;
} else if (navigator.msDoNotTrack) {
return navigator.msDoNotTrack;
} else if (window.doNotTrack) {
return window.doNotTrack;
} else {
return "unknown";
}
},
// This is a crude and primitive touch screen detection.
// It's not possible to currently reliably detect the availability of a touch screen
// with a JS, without actually subscribing to a touch event.
// http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
// https://github.com/Modernizr/Modernizr/issues/548
// method returns an array of 3 values:
// maxTouchPoints, the success or failure of creating a TouchEvent,
// and the availability of the 'ontouchstart' property
getTouchSupport: function () {
var maxTouchPoints = 0;
var touchEvent = false;
if(typeof navigator.maxTouchPoints !== "undefined") {
maxTouchPoints = navigator.maxTouchPoints;
} else if (typeof navigator.msMaxTouchPoints !== "undefined") {
maxTouchPoints = navigator.msMaxTouchPoints;
}
try {
document.createEvent("TouchEvent");
touchEvent = true;
} catch(_) { /* squelch */ }
var touchStart = "ontouchstart" in window;
return [maxTouchPoints, touchEvent, touchStart];
},
// https://www.browserleaks.com/canvas#how-does-it-work
getCanvasFp: function() {
var result = [];
// Very simple now, need to make it more complex (geo shapes etc)
var canvas = document.createElement("canvas");
canvas.width = 2000;
canvas.height = 200;
canvas.style.display = "inline";
var ctx = canvas.getContext("2d");
// detect browser support of canvas winding
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/canvas/winding.js
ctx.rect(0, 0, 10, 10);
ctx.rect(2, 2, 6, 6);
result.push("canvas winding:" + ((ctx.isPointInPath(5, 5, "evenodd") === false) ? "yes" : "no"));
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = "#069";
// https://github.com/Valve/fingerprintjs2/issues/66
if(this.options.dontUseFakeFontInCanvas) {
ctx.font = "11pt Arial";
} else {
ctx.font = "11pt no-real-font-123";
}
ctx.fillText("Cwm fjordbank glyphs vext quiz, \ud83d\ude03", 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.2)";
ctx.font = "18pt Arial";
ctx.fillText("Cwm fjordbank glyphs vext quiz, \ud83d\ude03", 4, 45);
// canvas blending
// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
// http://jsfiddle.net/NDYV8/16/
ctx.globalCompositeOperation = "multiply";
ctx.fillStyle = "rgb(255,0,255)";
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "rgb(0,255,255)";
ctx.beginPath();
ctx.arc(100, 50, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "rgb(255,255,0)";
ctx.beginPath();
ctx.arc(75, 100, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "rgb(255,0,255)";
// canvas winding
// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/
// http://jsfiddle.net/NDYV8/19/
ctx.arc(75, 75, 75, 0, Math.PI * 2, true);
ctx.arc(75, 75, 25, 0, Math.PI * 2, true);
ctx.fill("evenodd");
result.push("canvas fp:" + canvas.toDataURL());
return result.join("~");
},
getWebglFp: function() {
var gl;
var fa2s = function(fa) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
return "[" + fa[0] + ", " + fa[1] + "]";
};
var maxAnisotropy = function(gl) {
var anisotropy, ext = gl.getExtension("EXT_texture_filter_anisotropic") || gl.getExtension("WEBKIT_EXT_texture_filter_anisotropic") || gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
return ext ? (anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT), 0 === anisotropy && (anisotropy = 2), anisotropy) : null;
};
gl = this.getWebglCanvas();
if(!gl) { return null; }
// WebGL fingerprinting is a combination of techniques, found in MaxMind antifraud script & Augur fingerprinting.
// First it draws a gradient object with shaders and convers the image to the Base64 string.
// Then it enumerates all WebGL extensions & capabilities and appends them to the Base64 string, resulting in a huge WebGL string, potentially very unique on each device
// Since iOS supports webgl starting from version 8.1 and 8.1 runs on several graphics chips, the results may be different across ios devices, but we need to verify it.
var result = [];
var vShaderTemplate = "attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}";
var fShaderTemplate = "precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}";
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
var vertices = new Float32Array([-.2, -.9, 0, .4, -.26, 0, 0, .732134444, 0]);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
vertexPosBuffer.itemSize = 3;
vertexPosBuffer.numItems = 3;
var program = gl.createProgram(), vshader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vshader, vShaderTemplate);
gl.compileShader(vshader);
var fshader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fshader, fShaderTemplate);
gl.compileShader(fshader);
gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
gl.useProgram(program);
program.vertexPosAttrib = gl.getAttribLocation(program, "attrVertex");
program.offsetUniform = gl.getUniformLocation(program, "uniformOffset");
gl.enableVertexAttribArray(program.vertexPosArray);
gl.vertexAttribPointer(program.vertexPosAttrib, vertexPosBuffer.itemSize, gl.FLOAT, !1, 0, 0);
gl.uniform2f(program.offsetUniform, 1, 1);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexPosBuffer.numItems);
if (gl.canvas != null) { result.push(gl.canvas.toDataURL()); }
result.push("extensions:" + gl.getSupportedExtensions().join(";"));
result.push("webgl aliased line width range:" + fa2s(gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE)));
result.push("webgl aliased point size range:" + fa2s(gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE)));
result.push("webgl alpha bits:" + gl.getParameter(gl.ALPHA_BITS));
result.push("webgl antialiasing:" + (gl.getContextAttributes().antialias ? "yes" : "no"));
result.push("webgl blue bits:" + gl.getParameter(gl.BLUE_BITS));
result.push("webgl depth bits:" + gl.getParameter(gl.DEPTH_BITS));
result.push("webgl green bits:" + gl.getParameter(gl.GREEN_BITS));
result.push("webgl max anisotropy:" + maxAnisotropy(gl));
result.push("webgl max combined texture image units:" + gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS));
result.push("webgl max cube map texture size:" + gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE));
result.push("webgl max fragment uniform vectors:" + gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS));
result.push("webgl max render buffer size:" + gl.getParameter(gl.MAX_RENDERBUFFER_SIZE));
result.push("webgl max texture image units:" + gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
result.push("webgl max texture size:" + gl.getParameter(gl.MAX_TEXTURE_SIZE));
result.push("webgl max varying vectors:" + gl.getParameter(gl.MAX_VARYING_VECTORS));
result.push("webgl max vertex attribs:" + gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
result.push("webgl max vertex texture image units:" + gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS));
result.push("webgl max vertex uniform vectors:" + gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS));
result.push("webgl max viewport dims:" + fa2s(gl.getParameter(gl.MAX_VIEWPORT_DIMS)));
result.push("webgl red bits:" + gl.getParameter(gl.RED_BITS));
result.push("webgl renderer:" + gl.getParameter(gl.RENDERER));
result.push("webgl shading language version:" + gl.getParameter(gl.SHADING_LANGUAGE_VERSION));
result.push("webgl stencil bits:" + gl.getParameter(gl.STENCIL_BITS));
result.push("webgl vendor:" + gl.getParameter(gl.VENDOR));
result.push("webgl version:" + gl.getParameter(gl.VERSION));
if (!gl.getShaderPrecisionFormat) {
if (typeof NODEBUG === "undefined") {
this.log("WebGL fingerprinting is incomplete, because your browser does not support getShaderPrecisionFormat");
}
return result.join("~");
}
result.push("webgl vertex shader high float precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision);
result.push("webgl vertex shader high float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT ).rangeMin);
result.push("webgl vertex shader high float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT ).rangeMax);
result.push("webgl vertex shader medium float precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision);
result.push("webgl vertex shader medium float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).rangeMin);
result.push("webgl vertex shader medium float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).rangeMax);
result.push("webgl vertex shader low float precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT ).precision);
result.push("webgl vertex shader low float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT ).rangeMin);
result.push("webgl vertex shader low float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT ).rangeMax);
result.push("webgl fragment shader high float precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision);
result.push("webgl fragment shader high float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).rangeMin);
result.push("webgl fragment shader high float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).rangeMax);
result.push("webgl fragment shader medium float precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision);
result.push("webgl fragment shader medium float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).rangeMin);
result.push("webgl fragment shader medium float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).rangeMax);
result.push("webgl fragment shader low float precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT ).precision);
result.push("webgl fragment shader low float precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT ).rangeMin);
result.push("webgl fragment shader low float precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT ).rangeMax);
result.push("webgl vertex shader high int precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT ).precision);
result.push("webgl vertex shader high int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT ).rangeMin);
result.push("webgl vertex shader high int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT ).rangeMax);
result.push("webgl vertex shader medium int precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT ).precision);
result.push("webgl vertex shader medium int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT ).rangeMin);
result.push("webgl vertex shader medium int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT ).rangeMax);
result.push("webgl vertex shader low int precision:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT ).precision);
result.push("webgl vertex shader low int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT ).rangeMin);
result.push("webgl vertex shader low int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT ).rangeMax);
result.push("webgl fragment shader high int precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT ).precision);
result.push("webgl fragment shader high int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT ).rangeMin);
result.push("webgl fragment shader high int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT ).rangeMax);
result.push("webgl fragment shader medium int precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT ).precision);
result.push("webgl fragment shader medium int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT ).rangeMin);
result.push("webgl fragment shader medium int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT ).rangeMax);
result.push("webgl fragment shader low int precision:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT ).precision);
result.push("webgl fragment shader low int precision rangeMin:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT ).rangeMin);
result.push("webgl fragment shader low int precision rangeMax:" + gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT ).rangeMax);
return result.join("~");
},
getAdBlock: function(){
var ads = document.createElement("div");
ads.innerHTML = " ";
ads.className = "adsbox";
var result = false;
try {
// body may not exist, that's why we need try/catch
document.body.appendChild(ads);
result = document.getElementsByClassName("adsbox")[0].offsetHeight === 0;
document.body.removeChild(ads);
} catch (e) {
result = false;
}
return result;
},
getHasLiedLanguages: function(){
//We check if navigator.language is equal to the first language of navigator.languages
if(typeof navigator.languages !== "undefined"){
try {
var firstLanguages = navigator.languages[0].substr(0, 2);
if(firstLanguages !== navigator.language.substr(0, 2)){
return true;
}
} catch(err) {
return true;
}
}
return false;
},
getHasLiedResolution: function(){
if(screen.width < screen.availWidth){
return true;
}
if(screen.height < screen.availHeight){
return true;
}
return false;
},
getHasLiedOs: function(){
var userAgent = navigator.userAgent.toLowerCase();
var oscpu = navigator.oscpu;
var platform = navigator.platform.toLowerCase();
var os;
//We extract the OS from the user agent (respect the order of the if else if statement)
if(userAgent.indexOf("windows phone") >= 0){
os = "Windows Phone";
} else if(userAgent.indexOf("win") >= 0){
os = "Windows";
} else if(userAgent.indexOf("android") >= 0){
os = "Android";
} else if(userAgent.indexOf("linux") >= 0){
os = "Linux";
} else if(userAgent.indexOf("iphone") >= 0 || userAgent.indexOf("ipad") >= 0 ){
os = "iOS";
} else if(userAgent.indexOf("mac") >= 0){
os = "Mac";
} else{
os = "Other";
}
// We detect if the person uses a mobile device
var mobileDevice;
if (("ontouchstart" in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0)) {
mobileDevice = true;
} else{
mobileDevice = false;
}
if(mobileDevice && os !== "Windows Phone" && os !== "Android" && os !== "iOS" && os !== "Other"){
return true;
}
// We compare oscpu with the OS extracted from the UA
if(typeof oscpu !== "undefined"){
oscpu = oscpu.toLowerCase();
if(oscpu.indexOf("win") >= 0 && os !== "Windows" && os !== "Windows Phone"){
return true;
} else if(oscpu.indexOf("linux") >= 0 && os !== "Linux" && os !== "Android"){
return true;
} else if(oscpu.indexOf("mac") >= 0 && os !== "Mac" && os !== "iOS"){
return true;
} else if(oscpu.indexOf("win") === 0 && oscpu.indexOf("linux") === 0 && oscpu.indexOf("mac") >= 0 && os !== "other"){
return true;
}
}
//We compare platform with the OS extracted from the UA
if(platform.indexOf("win") >= 0 && os !== "Windows" && os !== "Windows Phone"){
return true;
} else if((platform.indexOf("linux") >= 0 || platform.indexOf("android") >= 0 || platform.indexOf("pike") >= 0) && os !== "Linux" && os !== "Android"){
return true;
} else if((platform.indexOf("mac") >= 0 || platform.indexOf("ipad") >= 0 || platform.indexOf("ipod") >= 0 || platform.indexOf("iphone") >= 0) && os !== "Mac" && os !== "iOS"){
return true;
} else if(platform.indexOf("win") === 0 && platform.indexOf("linux") === 0 && platform.indexOf("mac") >= 0 && os !== "other"){
return true;
}
if(typeof navigator.plugins === "undefined" && os !== "Windows" && os !== "Windows Phone"){
//We are are in the case where the person uses ie, therefore we can infer that it's windows
return true;
}
return false;
},
getHasLiedBrowser: function () {
var userAgent = navigator.userAgent.toLowerCase();
var productSub = navigator.productSub;
//we extract the browser from the user agent (respect the order of the tests)
var browser;
if(userAgent.indexOf("firefox") >= 0){
browser = "Firefox";
} else if(userAgent.indexOf("opera") >= 0 || userAgent.indexOf("opr") >= 0){
browser = "Opera";
} else if(userAgent.indexOf("chrome") >= 0){
browser = "Chrome";
} else if(userAgent.indexOf("safari") >= 0){
browser = "Safari";
} else if(userAgent.indexOf("trident") >= 0){
browser = "Internet Explorer";
} else{
browser = "Other";
}
if((browser === "Chrome" || browser === "Safari" || browser === "Opera") && productSub !== "20030107"){
return true;
}
var tempRes = eval.toString().length;
if(tempRes === 37 && browser !== "Safari" && browser !== "Firefox" && browser !== "Other"){
return true;
} else if(tempRes === 39 && browser !== "Internet Explorer" && browser !== "Other"){
return true;
} else if(tempRes === 33 && browser !== "Chrome" && browser !== "Opera" && browser !== "Other"){
return true;
}
//We create an error to see how it is handled
var errFirefox;
try {
throw "a";
} catch(err){
try{
err.toSource();
errFirefox = true;
} catch(errOfErr){
errFirefox = false;
}
}
if(errFirefox && browser !== "Firefox" && browser !== "Other"){
return true;
}
return false;
},
isCanvasSupported: function () {
var elem = document.createElement("canvas");
return !!(elem.getContext && elem.getContext("2d"));
},
isWebGlSupported: function() {
// code taken from Modernizr
if (!this.isCanvasSupported()) {
return false;
}
var canvas = document.createElement("canvas"),
glContext;
try {
glContext = canvas.getContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl"));
} catch(e) {
glContext = false;
}
return !!window.WebGLRenderingContext && !!glContext;
},
isIE: function () {
if(navigator.appName === "Microsoft Internet Explorer") {
return true;
} else if(navigator.appName === "Netscape" && /Trident/.test(navigator.userAgent)) { // IE 11
return true;
}
return false;
},
hasSwfObjectLoaded: function(){
return typeof window.swfobject !== "undefined";
},
hasMinFlashInstalled: function () {
return swfobject.hasFlashPlayerVersion("9.0.0");
},
addFlashDivNode: function() {
var node = document.createElement("div");
node.setAttribute("id", this.options.swfContainerId);
document.body.appendChild(node);
},
loadSwfAndDetectFonts: function(done) {
var hiddenCallback = "___fp_swf_loaded";
window[hiddenCallback] = function(fonts) {
done(fonts);
};
var id = this.options.swfContainerId;
this.addFlashDivNode();
var flashvars = { onReady: hiddenCallback};
var flashparams = { allowScriptAccess: "always", menu: "false" };
swfobject.embedSWF(this.options.swfPath, id, "1", "1", "9.0.0", false, flashvars, flashparams, {});
},
getWebglCanvas: function() {
var canvas = document.createElement("canvas");
var gl = null;
try {
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
} catch(e) { /* squelch */ }
if (!gl) { gl = null; }
return gl;
},
each: function (obj, iterator, context) {
if (obj === null) {
return;
}
if (this.nativeForEach && obj.forEach === this.nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
if (iterator.call(context, obj[i], i, obj) === {}) { return; }
}
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (iterator.call(context, obj[key], key, obj) === {}) { return; }
}
}
}
},
map: function(obj, iterator, context) {
var results = [];
// Not using strict equality so that this acts as a
// shortcut to checking for `null` and `undefined`.
if (obj == null) { return results; }
if (this.nativeMap && obj.map === this.nativeMap) { return obj.map(iterator, context); }
this.each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list);
});
return results;
},
/// MurmurHash3 related functions
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// added together as a 64bit int (as an array of two 32bit ints).
//
x64Add: function(m, n) {
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
var o = [0, 0, 0, 0];
o[3] += m[3] + n[3];
o[2] += o[3] >>> 16;
o[3] &= 0xffff;
o[2] += m[2] + n[2];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[1] += m[1] + n[1];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[0] += m[0] + n[0];
o[0] &= 0xffff;
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
},
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// multiplied together as a 64bit int (as an array of two 32bit ints).
//
x64Multiply: function(m, n) {
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff];
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff];
var o = [0, 0, 0, 0];
o[3] += m[3] * n[3];
o[2] += o[3] >>> 16;
o[3] &= 0xffff;
o[2] += m[2] * n[3];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[2] += m[3] * n[2];
o[1] += o[2] >>> 16;
o[2] &= 0xffff;
o[1] += m[1] * n[3];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[1] += m[2] * n[2];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[1] += m[3] * n[1];
o[0] += o[1] >>> 16;
o[1] &= 0xffff;
o[0] += (m[0] * n[3]) + (m[1] * n[2]) + (m[2] * n[1]) + (m[3] * n[0]);
o[0] &= 0xffff;
return [(o[0] << 16) | o[1], (o[2] << 16) | o[3]];
},
//
// Given a 64bit int (as an array of two 32bit ints) and an int
// representing a number of bit positions, returns the 64bit int (as an
// array of two 32bit ints) rotated left by that number of positions.
//
x64Rotl: function(m, n) {
n %= 64;
if (n === 32) {
return [m[1], m[0]];
}
else if (n < 32) {
return [(m[0] << n) | (m[1] >>> (32 - n)), (m[1] << n) | (m[0] >>> (32 - n))];
}
else {
n -= 32;
return [(m[1] << n) | (m[0] >>> (32 - n)), (m[0] << n) | (m[1] >>> (32 - n))];
}
},
//
// Given a 64bit int (as an array of two 32bit ints) and an int
// representing a number of bit positions, returns the 64bit int (as an
// array of two 32bit ints) shifted left by that number of positions.
//
x64LeftShift: function(m, n) {
n %= 64;
if (n === 0) {
return m;
}
else if (n < 32) {
return [(m[0] << n) | (m[1] >>> (32 - n)), m[1] << n];
}
else {
return [m[1] << (n - 32), 0];
}
},
//
// Given two 64bit ints (as an array of two 32bit ints) returns the two
// xored together as a 64bit int (as an array of two 32bit ints).
//
x64Xor: function(m, n) {
return [m[0] ^ n[0], m[1] ^ n[1]];
},
//
// Given a block, returns murmurHash3's final x64 mix of that block.
// (`[0, h[0] >>> 1]` is a 33 bit unsigned right shift. This is the
// only place where we need to right shift 64bit ints.)
//
x64Fmix: function(h) {
h = this.x64Xor(h, [0, h[0] >>> 1]);
h = this.x64Multiply(h, [0xff51afd7, 0xed558ccd]);
h = this.x64Xor(h, [0, h[0] >>> 1]);
h = this.x64Multiply(h, [0xc4ceb9fe, 0x1a85ec53]);
h = this.x64Xor(h, [0, h[0] >>> 1]);
return h;
},
//
// Given a string and an optional seed as an int, returns a 128 bit
// hash using the x64 flavor of MurmurHash3, as an unsigned hex.
//
x64hash128: function (key, seed) {
key = key || "";
seed = seed || 0;
var remainder = key.length % 16;
var bytes = key.length - remainder;
var h1 = [0, seed];
var h2 = [0, seed];
var k1 = [0, 0];
var k2 = [0, 0];
var c1 = [0x87c37b91, 0x114253d5];
var c2 = [0x4cf5ad43, 0x2745937f];
for (var i = 0; i < bytes; i = i + 16) {
k1 = [((key.charCodeAt(i + 4) & 0xff)) | ((key.charCodeAt(i + 5) & 0xff) << 8) | ((key.charCodeAt(i + 6) & 0xff) << 16) | ((key.charCodeAt(i + 7) & 0xff) << 24), ((key.charCodeAt(i) & 0xff)) | ((key.charCodeAt(i + 1) & 0xff) << 8) | ((key.charCodeAt(i + 2) & 0xff) << 16) | ((key.charCodeAt(i + 3) & 0xff) << 24)];
k2 = [((key.charCodeAt(i + 12) & 0xff)) | ((key.charCodeAt(i + 13) & 0xff) << 8) | ((key.charCodeAt(i + 14) & 0xff) << 16) | ((key.charCodeAt(i + 15) & 0xff) << 24), ((key.charCodeAt(i + 8) & 0xff)) | ((key.charCodeAt(i + 9) & 0xff) << 8) | ((key.charCodeAt(i + 10) & 0xff) << 16) | ((key.charCodeAt(i + 11) & 0xff) << 24)];
k1 = this.x64Multiply(k1, c1);
k1 = this.x64Rotl(k1, 31);
k1 = this.x64Multiply(k1, c2);
h1 = this.x64Xor(h1, k1);
h1 = this.x64Rotl(h1, 27);
h1 = this.x64Add(h1, h2);
h1 = this.x64Add(this.x64Multiply(h1, [0, 5]), [0, 0x52dce729]);
k2 = this.x64Multiply(k2, c2);
k2 = this.x64Rotl(k2, 33);
k2 = this.x64Multiply(k2, c1);
h2 = this.x64Xor(h2, k2);
h2 = this.x64Rotl(h2, 31);
h2 = this.x64Add(h2, h1);
h2 = this.x64Add(this.x64Multiply(h2, [0, 5]), [0, 0x38495ab5]);
}
k1 = [0, 0];
k2 = [0, 0];
switch(remainder) {
case 15:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 14)], 48));
case 14:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 13)], 40));
case 13:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 12)], 32));
case 12:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 11)], 24));
case 11:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 10)], 16));
case 10:
k2 = this.x64Xor(k2, this.x64LeftShift([0, key.charCodeAt(i + 9)], 8));
case 9:
k2 = this.x64Xor(k2, [0, key.charCodeAt(i + 8)]);
k2 = this.x64Multiply(k2, c2);
k2 = this.x64Rotl(k2, 33);
k2 = this.x64Multiply(k2, c1);
h2 = this.x64Xor(h2, k2);
case 8:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 7)], 56));
case 7:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 6)], 48));
case 6:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 5)], 40));
case 5:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 4)], 32));
case 4:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 3)], 24));
case 3:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 2)], 16));
case 2:
k1 = this.x64Xor(k1, this.x64LeftShift([0, key.charCodeAt(i + 1)], 8));
case 1:
k1 = this.x64Xor(k1, [0, key.charCodeAt(i)]);
k1 = this.x64Multiply(k1, c1);
k1 = this.x64Rotl(k1, 31);
k1 = this.x64Multiply(k1, c2);
h1 = this.x64Xor(h1, k1);
}
h1 = this.x64Xor(h1, [0, key.length]);
h2 = this.x64Xor(h2, [0, key.length]);
h1 = this.x64Add(h1, h2);
h2 = this.x64Add(h2, h1);
h1 = this.x64Fmix(h1);
h2 = this.x64Fmix(h2);
h1 = this.x64Add(h1, h2);
h2 = this.x64Add(h2, h1);
return ("00000000" + (h1[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h1[1] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[1] >>> 0).toString(16)).slice(-8);
}
};
Fingerprint2.VERSION = "1.4.2";
return Fingerprint2;
});
================================================
FILE: JavaScript/demo/js/jsbn.js
================================================
/*! (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);
================================================
FILE: JavaScript/demo/js/jsbn2.js
================================================
/*! (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)
================================================
FILE: JavaScript/demo/js/md5.js
================================================
/*
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;
// Constants table
var T = [];
// Compute constants
(function () {
for (var i = 0; i < 64; i++) {
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
}
}());
/**
* MD5 hash algorithm.
*/
var MD5 = C_algo.MD5 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476
]);
},
_doProcessBlock: function (M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
);
}
// Shortcuts
var H = this._hash.words;
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Computation
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
a = II(a, b, c, d, M_offset_0, 6, T[48]);
d = II(d, a, b, c, M_offset_7, 10, T[49]);
c = II(c, d, a, b, M_offset_14, 15, T[50]);
b = II(b, c, d, a, M_offset_5, 21, T[51]);
a = II(a, b, c, d, M_offset_12, 6, T[52]);
d = II(d, a, b, c, M_offset_3, 10, T[53]);
c = II(c, d, a, b, M_offset_10, 15, T[54]);
b = II(b, c, d, a, M_offset_1, 21, T[55]);
a = II(a, b, c, d, M_offset_8, 6, T[56]);
d = II(d, a, b, c, M_offset_15, 10, T[57]);
c = II(c, d, a, b, M_offset_6, 15, T[58]);
b = II(b, c, d, a, M_offset_13, 21, T[59]);
a = II(a, b, c, d, M_offset_4, 6, T[60]);
d = II(d, a, b, c, M_offset_11, 10, T[61]);
c = II(c, d, a, b, M_offset_2, 15, T[62]);
b = II(b, c, d, a, M_offset_9, 21, T[63]);
// 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;
},
_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);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
);
data.sigBytes = (dataWords.length + 1) * 4;
// Hash final blocks
this._process();
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
// Return final computed hash
return hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
function FF(a, b, c, d, x, s, t) {
var n = a + ((b & c) | (~b & d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function GG(a, b, c, d, x, s, t) {
var n = a + ((b & d) | (c & ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function HH(a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function II(a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
/**
* 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.MD5('message');
* var hash = CryptoJS.MD5(wordArray);
*/
C.MD5 = Hasher._createHelper(MD5);
/**
* 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.HmacMD5(message, key);
*/
C.HmacMD5 = Hasher._createHmacHelper(MD5);
}(Math));
================================================
FILE: JavaScript/demo/js/pkcs5pkey-1.0.js
================================================
/*! pkcs5pkey-1.0.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* pkcs5pkey.js - reading passcode protected PKCS#5 PEM formatted RSA private key
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name pkcs5pkey-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version pkcs5pkey 1.0.5 (2013-Aug-20)
* @since jsrsasign 2.0.0
* @license MIT License
*/
/**
* @name PKCS5PKEY
* @class class for PKCS#5 and PKCS#8 private key
* @deprecated Since jsrsasign 4.1.3. Please use KEYUTIL class.
* @description
*
* {@link PKCS5PKEY} class has following features:
*
*
read and parse PEM formatted encrypted PKCS#5 private key
*
*/
parsePrivateRawECKeyHexAtObj: function(pkcs8PrvHex, info) {
var keyIdx = info.keyidx;
// 1. sequence
if (pkcs8PrvHex.substr(keyIdx, 2) != "30")
throw "malformed ECC private key(code:001)"; // not sequence
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PrvHex, keyIdx);
if (a1.length != 3)
throw "malformed ECC private key(code:002)"; // not sequence
// 2. EC private key
if (pkcs8PrvHex.substr(a1[1], 2) != "04")
throw "malformed ECC private key(code:003)"; // not octetstring
info.key = ASN1HEX.getHexOfV_AtObj(pkcs8PrvHex, a1[1]);
},
/**
* parse hexadecimal string of PKCS#8 public key
* @name parsePublicPKCS8Hex
* @memberOf PKCS5PKEY
* @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 or null
*
key - hexadecimal string of public key
*
*/
parsePublicPKCS8Hex: function(pkcs8PubHex) {
var result = {};
result.algparam = null;
// 1. AlgID and Key bit string
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[0]);
// 2.2. AlgID param
if (pkcs8PubHex.substr(a2[1], 2) == "06") {
result.algparam = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[1]);
}
// 3. Key
if (pkcs8PubHex.substr(a1[1], 2) != "03")
throw "malformed PKCS8 public key(code:004)"; // Key is not bit string
result.key = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a1[1]).substr(2);
// 4. return result assoc array
return result;
},
/**
* provide hexadecimal string of unencrypted PKCS#8 private key and returns RSAKey object
* @name getRSAKeyFromPublicPKCS8Hex
* @memberOf PKCS5PKEY
* @function
* @param {String} pkcs8PubHex hexadecimal string of unencrypted PKCS#8 public key
* @return {RSAKey} loaded RSAKey object of RSA public key
* @since pkcs5pkey 1.0.4
*/
getRSAKeyFromPublicPKCS8Hex: function(pkcs8PubHex) {
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PubHex, 0);
if (a1.length != 2)
throw "outer DERSequence shall have 2 elements: " + a1.length;
var algIdTLV =ASN1HEX.getHexOfTLV_AtObj(pkcs8PubHex, a1[0]);
if (algIdTLV != "300d06092a864886f70d0101010500") // AlgId rsaEncryption
throw "PKCS8 AlgorithmId is not rsaEncryption";
if (pkcs8PubHex.substr(a1[1], 2) != "03")
throw "PKCS8 Public Key is not BITSTRING encapslated.";
var idxPub = ASN1HEX.getStartPosOfV_AtObj(pkcs8PubHex, a1[1]) + 2; // 2 for unused bit
if (pkcs8PubHex.substr(idxPub, 2) != "30")
throw "PKCS8 Public Key is not SEQUENCE.";
var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PubHex, idxPub);
if (a2.length != 2)
throw "inner DERSequence shall have 2 elements: " + a2.length;
if (pkcs8PubHex.substr(a2[0], 2) != "02")
throw "N is not ASN.1 INTEGER";
if (pkcs8PubHex.substr(a2[1], 2) != "02")
throw "E is not ASN.1 INTEGER";
var hN = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[0]);
var hE = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[1]);
var pubKey = new RSAKey();
pubKey.setPublic(hN, hE);
return pubKey;
},
//addAlgorithm: function(functionObject, algName, keyLen, ivLen) {
//}
};
}();
================================================
FILE: JavaScript/demo/js/prng4.js
================================================
/*! (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;
================================================
FILE: JavaScript/demo/js/rng.js
================================================
/*! (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(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
// Extract entropy (256 bits) from NS4 RNG if available
var z = window.crypto.random(32);
for(t = 0; t < z.length; ++t)
rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
}
while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
t = Math.floor(65536 * Math.random());
rng_pool[rng_pptr++] = t >>> 8;
rng_pool[rng_pptr++] = t & 255;
}
rng_pptr = 0;
rng_seed_time();
//rng_seed_int(window.screenX);
//rng_seed_int(window.screenY);
}
function rng_get_byte() {
if(rng_state == null) {
rng_seed_time();
rng_state = prng_newstate();
rng_state.init(rng_pool);
for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
rng_pool[rng_pptr] = 0;
rng_pptr = 0;
//rng_pool = null;
}
// TODO: allow reseeding after first request
return rng_state.next();
}
function rng_get_bytes(ba) {
var i;
for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
}
function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;
================================================
FILE: JavaScript/demo/js/rsa.js
================================================
/*! (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
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
// 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;
}
var SHA1_SIZE = 20;
// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
function oaep_pad(s, n, hash)
{
if (s.length + 2 * SHA1_SIZE + 2 > n)
{
throw "Message too long for RSA";
}
var PS = '', i;
for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
{
PS += '\x00';
}
var DB = rstr_sha1('') + PS + '\x01' + s;
var seed = new Array(SHA1_SIZE);
new SecureRandom().nextBytes(seed);
var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
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, rstr_sha1);
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;
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
alert("Invalid RSA public key");
}
// Perform raw public operation on "x": return x^e (mod n)
function RSADoPublic(x) {
return x.modPowInt(this.e, this.n);
}
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
function RSAEncrypt(text) {
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
function RSAEncryptOAEP(text, hash) {
var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
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";
================================================
FILE: JavaScript/demo/js/rsa2.js
================================================
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
*/
// Depends on rsa.js and jsbn2.js
// Version 1.1: support utf-8 decoding in pkcs1unpad2
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
function pkcs1unpad2(d,n) {
var b = d.toByteArray();
var i = 0;
while(i < b.length && b[i] == 0) ++i;
if(b.length-i != n-1 || b[i] != 2)
return null;
++i;
while(b[i] != 0)
if(++i >= b.length) return null;
var ret = "";
while(++i < b.length) {
var c = b[i] & 255;
if(c < 128) { // utf-8 decode
ret += String.fromCharCode(c);
}
else if((c > 191) && (c < 224)) {
ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
++i;
}
else {
ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
i += 2;
}
}
return ret;
}
// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_str(seed, len, hash)
{
var mask = '', i = 0;
while (mask.length < len)
{
mask += hash(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]));
i += 1;
}
return mask;
}
var SHA1_SIZE = 20;
// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
function oaep_unpad(d, n, hash)
{
d = d.toByteArray();
var i;
for (i = 0; i < d.length; i += 1)
{
d[i] &= 0xff;
}
while (d.length < n)
{
d.unshift(0);
}
d = String.fromCharCode.apply(String, d);
if (d.length < 2 * SHA1_SIZE + 2)
{
throw "Cipher too short";
}
var maskedSeed = d.substr(1, SHA1_SIZE)
var maskedDB = d.substr(SHA1_SIZE + 1);
var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
var seed = [], i;
for (i = 0; i < maskedSeed.length; i += 1)
{
seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
}
var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
d.length - SHA1_SIZE, rstr_sha1);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1)
{
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB = String.fromCharCode.apply(String, DB);
if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
{
throw "Hash mismatch";
}
DB = DB.substr(SHA1_SIZE);
var first_one = DB.indexOf('\x01');
var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;
if (last_zero + 1 != first_one)
{
throw "Malformed data";
}
return DB.substr(first_one + 1);
}
// Set the private key fields N, e, and d from hex strings
function RSASetPrivate(N,E,D) {
this.isPrivate = true;
if (typeof N !== "string")
{
this.n = N;
this.e = E;
this.d = D;
}
else if(N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
}
else
alert("Invalid RSA private key");
}
// Set the private key fields N, e, d and CRT params from hex strings
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
this.isPrivate = true;
if (N == null) throw "RSASetPrivateEx N == null";
if (E == null) throw "RSASetPrivateEx E == null";
if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
if (E.length == 0) throw "RSASetPrivateEx E.length == 0";
if (N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
this.p = parseBigInt(P,16);
this.q = parseBigInt(Q,16);
this.dmp1 = parseBigInt(DP,16);
this.dmq1 = parseBigInt(DQ,16);
this.coeff = parseBigInt(C,16);
} else {
alert("Invalid RSA private key in RSASetPrivateEx");
}
}
// Generate a new random private key B bits long, using public expt E
function RSAGenerate(B,E) {
var rng = new SecureRandom();
var qs = B>>1;
this.e = parseInt(E,16);
var ee = new BigInteger(E,16);
for(;;) {
for(;;) {
this.p = new BigInteger(B-qs,1,rng);
if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
}
for(;;) {
this.q = new BigInteger(qs,1,rng);
if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
}
if(this.p.compareTo(this.q) <= 0) {
var t = this.p;
this.p = this.q;
this.q = t;
}
var p1 = this.p.subtract(BigInteger.ONE); // p1 = p - 1
var q1 = this.q.subtract(BigInteger.ONE); // q1 = q - 1
var phi = p1.multiply(q1);
if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
this.n = this.p.multiply(this.q); // this.n = p * q
this.d = ee.modInverse(phi); // this.d =
this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1)
this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1)
this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p
break;
}
}
}
// Perform raw private operation on "x": return x^d (mod n)
function RSADoPrivate(x) {
if(this.p == null || this.q == null)
return x.modPow(this.d, this.n);
// TODO: re-calculate any missing CRT params
var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?
while(xp.compareTo(xq) < 0)
xp = xp.add(this.p);
// NOTE:
// xp.subtract(xq) => cp -cq
// xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
// xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecrypt(ctext) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
}
// Return the PKCS#1 OAEP RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecryptOAEP(ctext, hash) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is a Base64-encoded string and the output is a plain string.
//function RSAB64Decrypt(ctext) {
// var h = b64tohex(ctext);
// if(h) return this.decrypt(h); else return null;
//}
// protected
RSAKey.prototype.doPrivate = RSADoPrivate;
// public
RSAKey.prototype.setPrivate = RSASetPrivate;
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
RSAKey.prototype.generate = RSAGenerate;
RSAKey.prototype.decrypt = RSADecrypt;
RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
================================================
FILE: JavaScript/demo/js/rsapem-1.1.js
================================================
/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
//
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
// to RSAKey class.
//
// version: 1.1.1 (2013-Apr-12)
//
// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
//
// This software is licensed under the terms of the MIT License.
// http://kjur.github.com/jsrsasign/license/
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
//
// Depends on:
//
//
//
// _RSApem_pemToBase64(sPEM)
//
// removing PEM header, PEM footer and space characters including
// new lines from PEM formatted RSA private key string.
//
/**
* @fileOverview
* @name rsapem-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.1
* @license MIT License
*/
function _rsapem_pemToBase64(sPEMPrivateKey) {
var s = sPEMPrivateKey;
s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
s = s.replace("-----END RSA PRIVATE KEY-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
}
function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
var a = new Array();
var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
return a;
}
function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
var v = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
var n = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
var e = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
var d = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
var p = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
var q = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
var a = new Array();
a.push(v, n, e, d, p, q, dp, dq, co);
return a;
}
/**
* read RSA private key from a ASN.1 hexadecimal string
* @name readPrivateKeyFromASN1HexString
* @memberOf RSAKey#
* @function
* @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
* @since 1.1.1
*/
function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
/**
* read PKCS#1 private key from a string
* @name readPrivateKeyFromPEMString
* @memberOf RSAKey#
* @function
* @param {String} keyPEM string of PKCS#1 private key.
*/
function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
var keyB64 = _rsapem_pemToBase64(keyPEM);
var keyHex = b64tohex(keyB64) // depends base64.js
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;
================================================
FILE: JavaScript/demo/js/rsasign-1.2.js
================================================
/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* rsa-sign.js - adding signing functions to RSAKey class.
*
* version: 1.2.7 (2013 Aug 25)
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license/
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name rsasign-1.2.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version rsasign 1.2.7
* @license MIT License
*/
var _RE_HEXDECONLY = new RegExp("");
_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
// ========================================================================
// Signature Generation
// ========================================================================
function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
var sHashHex = hashFunc(s);
return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
}
function _zeroPaddingOfSignature(hex, bitLength) {
var s = "";
var nZero = bitLength / 4 - hex.length;
for (var i = 0; i < nZero; i++) {
s = s + "0";
}
return s + hex;
}
/**
* sign for a message string with RSA private key.
* @name signString
* @memberOf RSAKey
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signString(s, hashAlg) {
var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
var sHashHex = hashFunc(s);
return this.signWithMessageHash(sHashHex, hashAlg);
}
/**
* sign hash value of message to be signed with RSA private key.
* @name signWithMessageHash
* @memberOf RSAKey
* @function
* @param {String} sHashHex hexadecimal string of hash value of message to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @return returns hexadecimal string of signature value.
* @since rsasign 1.2.6
*/
function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
}
function _rsasign_signStringWithSHA1(s) {
return _rsasign_signString.call(this, s, 'sha1');
}
function _rsasign_signStringWithSHA256(s) {
return _rsasign_signString.call(this, s, 'sha256');
}
// PKCS#1 (PSS) mask generation function
function pss_mgf1_str(seed, len, hash) {
var mask = '', i = 0;
while (mask.length < len) {
mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]))));
i += 1;
}
return mask;
}
/**
* sign for a message string with RSA private key by PKCS#1 PSS signing.
* @name signStringPSS
* @memberOf RSAKey
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signStringPSS(s, hashAlg, sLen) {
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
var hHash = hashFunc(rstrtohex(s));
if (sLen === undefined) sLen = -1;
return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
}
/**
* sign hash value of message with RSA private key by PKCS#1 PSS signing.
* @name signWithMessageHashPSS
* @memberOf RSAKey
* @function
* @param {String} hHash hexadecimal hash value of message to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns hexadecimal string of signature value.
* @since rsasign 1.2.6
*/
function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
var mHash = hextorstr(hHash);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
if (sLen === -1 || sLen === undefined) {
sLen = hLen; // same as hash length
} else if (sLen === -2) {
sLen = emLen - hLen - 2; // maximum
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var salt = '';
if (sLen > 0) {
salt = new Array(sLen);
new SecureRandom().nextBytes(salt);
salt = String.fromCharCode.apply(String, salt);
}
var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
var PS = [];
for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
PS[i] = 0x00;
}
var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
var maskedDB = [];
for (i = 0; i < DB.length; i += 1) {
maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
maskedDB[0] &= ~mask;
for (i = 0; i < hLen; i++) {
maskedDB.push(H.charCodeAt(i));
}
maskedDB.push(0xbc);
return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
this.n.bitLength());
}
// ========================================================================
// Signature Verification
// ========================================================================
function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
var rsa = new RSAKey();
rsa.setPublic(hN, hE);
var biDecryptedSig = rsa.doPublic(biSig);
return biDecryptedSig;
}
function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
return hDigestInfo;
}
function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
var len = head.length;
if (hDigestInfo.substring(0, len) == head) {
var a = [algName, hDigestInfo.substring(len)];
return a;
}
}
return [];
}
function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
var biSig = parseBigInt(hSig, 16);
var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
this.n.toString(16),
this.e.toString(16));
return result;
}
/**
* verifies a sigature for a message string with RSA public key.
* @name verifyString
* @memberOf RSAKey#
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of siganture.
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
*/
function _rsasign_verifyString(sMsg, hSig) {
hSig = hSig.replace(_RE_HEXDECONLY, '');
hSig = hSig.replace(/[ \n]+/g, "");
var biSig = parseBigInt(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) return 0;
var biDecryptedSig = this.doPublic(biSig);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
/**
* verifies a sigature for a message string with RSA public key.
* @name verifyWithMessageHash
* @memberOf RSAKey
* @function
* @param {String} sHashHex hexadecimal hash value of message to be verified.
* @param {String} hSig hexadecimal string of siganture.
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
* @since rsasign 1.2.6
*/
function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
hSig = hSig.replace(_RE_HEXDECONLY, '');
hSig = hSig.replace(/[ \n]+/g, "");
var biSig = parseBigInt(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) return 0;
var biDecryptedSig = this.doPublic(biSig);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
return (diHashValue == sHashHex);
}
/**
* verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.
* @name verifyStringPSS
* @memberOf RSAKey
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of signature value
* @param {String} hashAlg hash algorithm name
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns true if valid, otherwise false
*/
function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
var hHash = hashFunc(rstrtohex(sMsg));
if (sLen === undefined) sLen = -1;
return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
}
/**
* verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.
* @name verifyWithMessageHashPSS
* @memberOf RSAKey
* @function
* @param {String} hHash hexadecimal hash value of message string to be verified.
* @param {String} hSig hexadecimal string of signature value
* @param {String} hashAlg hash algorithm name
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
* @return returns true if valid, otherwise false
* @since rsasign 1.2.6
*/
function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
var biSig = new BigInteger(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) {
return false;
}
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
var mHash = hextorstr(hHash);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
if (sLen === -1 || sLen === undefined) {
sLen = hLen; // same as hash length
} else if (sLen === -2) {
sLen = emLen - hLen - 2; // recover
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var em = this.doPublic(biSig).toByteArray();
for (i = 0; i < em.length; i += 1) {
em[i] &= 0xff;
}
while (em.length < emLen) {
em.unshift(0);
}
if (em[emLen -1] !== 0xbc) {
throw "encoded message does not end in 0xbc";
}
em = String.fromCharCode.apply(String, em);
var maskedDB = em.substr(0, emLen - hLen - 1);
var H = em.substr(maskedDB.length, hLen);
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
if ((maskedDB.charCodeAt(0) & mask) !== 0) {
throw "bits beyond keysize not zero";
}
var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1) {
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB[0] &= ~mask;
var checkLen = emLen - hLen - sLen - 2;
for (i = 0; i < checkLen; i += 1) {
if (DB[i] !== 0x00) {
throw "leftmost octets not zero";
}
}
if (DB[checkLen] !== 0x01) {
throw "0x01 marker not found";
}
return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
String.fromCharCode.apply(String, DB.slice(-sLen)))));
}
RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
RSAKey.prototype.signString = _rsasign_signString;
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.sign = _rsasign_signString;
RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
RSAKey.prototype.signPSS = _rsasign_signStringPSS;
RSAKey.SALT_LEN_HLEN = -1;
RSAKey.SALT_LEN_MAX = -2;
RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verify = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
RSAKey.SALT_LEN_RECOVER = -2;
/**
* @name RSAKey
* @class key of RSA public key algorithm
* @description Tom Wu's RSA Key class and extension
*/
================================================
FILE: JavaScript/demo/js/sha1.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Reusable object
var W = [];
/**
* SHA-1 hash algorithm.
*/
var SHA1 = C_algo.SHA1 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476,
0xc3d2e1f0
]);
},
_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];
// Computation
for (var i = 0; i < 80; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = (n << 1) | (n >>> 31);
}
var t = ((a << 5) | (a >>> 27)) + e + W[i];
if (i < 20) {
t += ((b & c) | (~b & d)) + 0x5a827999;
} else if (i < 40) {
t += (b ^ c ^ d) + 0x6ed9eba1;
} else if (i < 60) {
t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
} else /* if (i < 80) */ {
t += (b ^ c ^ d) - 0x359d3e2a;
}
e = d;
d = c;
c = (b << 30) | (b >>> 2);
b = a;
a = t;
}
// 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;
},
_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.SHA1('message');
* var hash = CryptoJS.SHA1(wordArray);
*/
C.SHA1 = Hasher._createHelper(SHA1);
/**
* 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.HmacSHA1(message, key);
*/
C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
}());
================================================
FILE: JavaScript/demo/js/sha256.js
================================================
/*
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));
================================================
FILE: JavaScript/demo/js/sm2-guomi.js
================================================
function SM2Cipher(cipherMode) {
this.ct = 1;
this.p2 = null;
this.sm3keybase = null;
this.sm3c3 = null;
this.key = new Array(32);
this.keyOff = 0;
if (typeof(cipherMode) != 'undefined') {
this.cipherMode = cipherMode
} else {
this.cipherMode = SM2CipherMode.C1C3C2
}
}
SM2Cipher.prototype = {
Reset: function() {
this.sm3keybase = new SM3Digest();
this.sm3c3 = new SM3Digest();
var xWords = this.GetWords(this.p2.getX().toBigInteger().toRadix(16));
var yWords = this.GetWords(this.p2.getY().toBigInteger().toRadix(16));
this.sm3keybase.BlockUpdate(xWords, 0, xWords.length);
this.sm3c3.BlockUpdate(xWords, 0, xWords.length);
this.sm3keybase.BlockUpdate(yWords, 0, yWords.length);
this.ct = 1;
this.NextKey()
},
NextKey: function() {
var sm3keycur = new SM3Digest(this.sm3keybase);
sm3keycur.Update((this.ct >> 24 & 0x00ff));
sm3keycur.Update((this.ct >> 16 & 0x00ff));
sm3keycur.Update((this.ct >> 8 & 0x00ff));
sm3keycur.Update((this.ct & 0x00ff));
sm3keycur.DoFinal(this.key, 0);
this.keyOff = 0;
this.ct++
},
InitEncipher: function(userKey) {
var k = null;
var c1 = null;
var ec = new KJUR.crypto.ECDSA({
"curve": "sm2"
});
var keypair = ec.generateKeyPairHex();
k = new BigInteger(keypair.ecprvhex, 16);
var pubkeyHex = keypair.ecpubhex;
c1 = ECPointFp.decodeFromHex(ec.ecparams['curve'], pubkeyHex);
this.p2 = userKey.multiply(k);
this.Reset();
return c1
},
EncryptBlock: function(data) {
this.sm3c3.BlockUpdate(data, 0, data.length);
for (var i = 0; i < data.length; i++) {
if (this.keyOff == this.key.length) {
this.NextKey()
}
data[i] ^= this.key[this.keyOff++]
}
},
InitDecipher: function(userD, c1) {
this.p2 = c1.multiply(userD);
this.Reset()
},
DecryptBlock: function(data) {
for (var i = 0; i < data.length; i++) {
if (this.keyOff == this.key.length) {
this.NextKey()
}
data[i] ^= this.key[this.keyOff++]
}
this.sm3c3.BlockUpdate(data, 0, data.length)
},
Dofinal: function(c3) {
var yWords = this.GetWords(this.p2.getY().toBigInteger().toRadix(16));
this.sm3c3.BlockUpdate(yWords, 0, yWords.length);
this.sm3c3.DoFinal(c3, 0);
this.Reset()
},
Encrypt: function(pubKey, plaintext) {
var data = new Array(plaintext.length);
Array.Copy(plaintext, 0, data, 0, plaintext.length);
var c1 = this.InitEncipher(pubKey);
this.EncryptBlock(data);
var c3 = new Array(32);
this.Dofinal(c3);
var hexString = c1.getX().toBigInteger().toRadix(16) + c1.getY().toBigInteger().toRadix(16) + this.GetHex(data).toString() + this.GetHex(c3).toString();
if (this.cipherMode == SM2CipherMode.C1C3C2) {
hexString = c1.getX().toBigInteger().toRadix(16) + c1.getY().toBigInteger().toRadix(16) + this.GetHex(c3).toString() + this.GetHex(data).toString()
}
return hexString
},
GetWords: function(hexStr) {
var words = [];
var hexStrLength = hexStr.length;
for (var i = 0; i < hexStrLength; i += 2) {
words[words.length] = parseInt(hexStr.substr(i, 2), 16)
}
return words
},
GetHex: function(arr) {
var words = [];
var j = 0;
for (var i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j]) << (24 - (i % 8) * 4);
j++
}
var wordArray = new CryptoJS.lib.WordArray.init(words, arr.length);
return wordArray
},
Decrypt: function(privateKey, ciphertext) {
var hexString = ciphertext;
var c1X = hexString.substr(0, 64);
var c1Y = hexString.substr(0 + c1X.length, 64);
var encrypData = hexString.substr(c1X.length + c1Y.length, hexString.length - c1X.length - c1Y.length - 64);
var c3 = hexString.substr(hexString.length - 64);
if (this.cipherMode == SM2CipherMode.C1C3C2) {
c3 = hexString.substr(c1X.length + c1Y.length, 64);
encrypData = hexString.substr(c1X.length + c1Y.length + 64)
}
var data = this.GetWords(encrypData);
var c1 = this.CreatePoint(c1X, c1Y);
this.InitDecipher(privateKey, c1);
this.DecryptBlock(data);
var c3_ = new Array(32);
this.Dofinal(c3_);
var isDecrypt = this.GetHex(c3_).toString() == c3;
if (isDecrypt) {
var wordArray = this.GetHex(data);
var decryptData = CryptoJS.enc.Utf8.stringify(wordArray);
return decryptData
} else {
return ''
}
},
CreatePoint: function(x, y) {
var ec = new KJUR.crypto.ECDSA({
"curve": "sm2"
});
var ecc_curve = ec.ecparams['curve'];
var pubkeyHex = '04' + x + y;
var point = ECPointFp.decodeFromHex(ec.ecparams['curve'], pubkeyHex);
return point
}
};
window.SM2CipherMode = {
C1C2C3: '0',
C1C3C2: '1'
};
================================================
FILE: JavaScript/demo/js/sm2.js
================================================
function SM2Cipher(cipherMode){this.ct=1;this.p2=null;this.sm3keybase=null;this.sm3c3=null;this.key=new Array(32);this.keyOff=0;if(typeof(cipherMode)!='undefined'){this.cipherMode=cipherMode}else{this.cipherMode=SM2CipherMode.C1C3C2}}SM2Cipher.prototype={Reset:function(){this.sm3keybase=new SM3Digest();this.sm3c3=new SM3Digest();var xWords=this.GetWords(this.p2.getX().toBigInteger().toRadix(16));var yWords=this.GetWords(this.p2.getY().toBigInteger().toRadix(16));this.sm3keybase.BlockUpdate(xWords,0,xWords.length);this.sm3c3.BlockUpdate(xWords,0,xWords.length);this.sm3keybase.BlockUpdate(yWords,0,yWords.length);this.ct=1;this.NextKey()},NextKey:function(){var sm3keycur=new SM3Digest(this.sm3keybase);sm3keycur.Update((this.ct>>24&0x00ff));sm3keycur.Update((this.ct>>16&0x00ff));sm3keycur.Update((this.ct>>8&0x00ff));sm3keycur.Update((this.ct&0x00ff));sm3keycur.DoFinal(this.key,0);this.keyOff=0;this.ct++},InitEncipher:function(userKey){var k=null;var c1=null;var ec=new KJUR.crypto.ECDSA({"curve":"sm2"});var keypair=ec.generateKeyPairHex();k=new BigInteger(keypair.ecprvhex,16);var pubkeyHex=keypair.ecpubhex;c1=ECPointFp.decodeFromHex(ec.ecparams['curve'],pubkeyHex);this.p2=userKey.multiply(k);this.Reset();return c1},EncryptBlock:function(data){this.sm3c3.BlockUpdate(data,0,data.length);for(var i=0;i>>3]|=parseInt(arr[j])<<(24-(i%8)*4);j++}var wordArray=new CryptoJS.lib.WordArray.init(words,arr.length);return wordArray},Decrypt:function(privateKey,ciphertext){var hexString=ciphertext;var c1X=hexString.substr(0,64);var c1Y=hexString.substr(0+c1X.length,64);var encrypData=hexString.substr(c1X.length+c1Y.length,hexString.length-c1X.length-c1Y.length-64);var c3=hexString.substr(hexString.length-64);if(this.cipherMode==SM2CipherMode.C1C3C2){c3=hexString.substr(c1X.length+c1Y.length,64);encrypData=hexString.substr(c1X.length+c1Y.length+64)}var data=this.GetWords(encrypData);var c1=this.CreatePoint(c1X,c1Y);this.InitDecipher(privateKey,c1);this.DecryptBlock(data);var c3_=new Array(32);this.Dofinal(c3_);var isDecrypt=this.GetHex(c3_).toString()==c3;if(isDecrypt){var wordArray=this.GetHex(data);var decryptData=CryptoJS.enc.Utf8.stringify(wordArray);return decryptData}else{return''}},CreatePoint:function(x,y){var ec=new KJUR.crypto.ECDSA({"curve":"sm2"});var ecc_curve=ec.ecparams['curve'];var pubkeyHex='04'+x+y;var point=ECPointFp.decodeFromHex(ec.ecparams['curve'],pubkeyHex);return point}};window.SM2CipherMode={C1C2C3:'0',C1C3C2:'1'};
================================================
FILE: JavaScript/demo/js/sm3-guomi.js
================================================
(function() {
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
var W = [];
var SM3 = C_algo.SM3 = Hasher.extend({
_doReset: function() {
this._hash = new WordArray.init([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
},
_doProcessBlock: function(M, offset) {
var H = this._hash.words;
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
for (var i = 0; i < 80; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0
} else {
var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = (n << 1) | (n >>> 31)
}
var t = ((a << 5) | (a >>> 27)) + e + W[i];
if (i < 20) {
t += ((b & c) | (~b & d)) + 0x5a827999
} else if (i < 40) {
t += (b ^ c ^ d) + 0x6ed9eba1
} else if (i < 60) {
t += ((b & c) | (b & d) | (c & d)) - 0x70e44324
} else {
t += (b ^ c ^ d) - 0x359d3e2a
}
e = d;
d = c;
c = (b << 30) | (b >>> 2);
b = a;
a = t
}
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
},
_doFinalize: function() {
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
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;
this._process();
return this._hash
},
clone: function() {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone
}
});
C.SM3 = Hasher._createHelper(SM3);
C.HmacSM3 = Hasher._createHmacHelper(SM3)
}());
function SM3Digest() {
this.BYTE_LENGTH = 64;
this.xBuf = new Array();
this.xBufOff = 0;
this.byteCount = 0;
this.DIGEST_LENGTH = 32;
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e];
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, -628488704, -1452330820, 0x163138aa, -477237683, -1325724082];
this.v = new Array(8);
this.v_ = new Array(8);
this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
this.X = new Array(68);
this.xOff = 0;
this.T_00_15 = 0x79cc4519;
this.T_16_63 = 0x7a879d8a;
if (arguments.length > 0) {
this.InitDigest(arguments[0])
} else {
this.Init()
}
}
SM3Digest.prototype = {
Init: function() {
this.xBuf = new Array(4);
this.Reset()
},
InitDigest: function(t) {
this.xBuf = new Array(t.xBuf.length);
Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
this.xBufOff = t.xBufOff;
this.byteCount = t.byteCount;
Array.Copy(t.X, 0, this.X, 0, t.X.length);
this.xOff = t.xOff;
Array.Copy(t.v, 0, this.v, 0, t.v.length)
},
GetDigestSize: function() {
return this.DIGEST_LENGTH
},
Reset: function() {
this.byteCount = 0;
this.xBufOff = 0;
Array.Clear(this.xBuf, 0, this.xBuf.length);
Array.Copy(this.v0, 0, this.v, 0, this.v0.length);
this.xOff = 0;
Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
},
GetByteLength: function() {
return this.BYTE_LENGTH
},
ProcessBlock: function() {
var i;
var ww = this.X;
var ww_ = new Array(64);
for (i = 16; i < 68; i++) {
ww[i] = this.P1(ww[i - 16] ^ ww[i - 9] ^ (this.ROTATE(ww[i - 3], 15))) ^ (this.ROTATE(ww[i - 13], 7)) ^ ww[i - 6]
}
for (i = 0; i < 64; i++) {
ww_[i] = ww[i] ^ ww[i + 4]
}
var vv = this.v;
var vv_ = this.v_;
Array.Copy(vv, 0, vv_, 0, this.v0.length);
var SS1, SS2, TT1, TT2, aaa;
for (i = 0; i < 16; i++) {
aaa = this.ROTATE(vv_[0], 12);
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_00_15, i));
SS1 = this.ROTATE(SS1, 7);
SS2 = SS1 ^ aaa;
TT1 = Int32.parse(Int32.parse(this.FF_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
TT2 = Int32.parse(Int32.parse(this.GG_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
vv_[3] = vv_[2];
vv_[2] = this.ROTATE(vv_[1], 9);
vv_[1] = vv_[0];
vv_[0] = TT1;
vv_[7] = vv_[6];
vv_[6] = this.ROTATE(vv_[5], 19);
vv_[5] = vv_[4];
vv_[4] = this.P0(TT2)
}
for (i = 16; i < 64; i++) {
aaa = this.ROTATE(vv_[0], 12);
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_16_63, i));
SS1 = this.ROTATE(SS1, 7);
SS2 = SS1 ^ aaa;
TT1 = Int32.parse(Int32.parse(this.FF_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
TT2 = Int32.parse(Int32.parse(this.GG_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
vv_[3] = vv_[2];
vv_[2] = this.ROTATE(vv_[1], 9);
vv_[1] = vv_[0];
vv_[0] = TT1;
vv_[7] = vv_[6];
vv_[6] = this.ROTATE(vv_[5], 19);
vv_[5] = vv_[4];
vv_[4] = this.P0(TT2)
}
for (i = 0; i < 8; i++) {
vv[i] ^= Int32.parse(vv_[i])
}
this.xOff = 0;
Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
},
ProcessWord: function(in_Renamed, inOff) {
var n = in_Renamed[inOff] << 24;
n |= (in_Renamed[++inOff] & 0xff) << 16;
n |= (in_Renamed[++inOff] & 0xff) << 8;
n |= (in_Renamed[++inOff] & 0xff);
this.X[this.xOff] = n;
if (++this.xOff == 16) {
this.ProcessBlock()
}
},
ProcessLength: function(bitLength) {
if (this.xOff > 14) {
this.ProcessBlock()
}
this.X[14] = (this.URShiftLong(bitLength, 32));
this.X[15] = (bitLength & (0xffffffff))
},
IntToBigEndian: function(n, bs, off) {
bs[off] = Int32.parseByte(this.URShift(n, 24));
bs[++off] = Int32.parseByte(this.URShift(n, 16));
bs[++off] = Int32.parseByte(this.URShift(n, 8));
bs[++off] = Int32.parseByte(n)
},
DoFinal: function(out_Renamed, outOff) {
this.Finish();
for (var i = 0; i < 8; i++) {
this.IntToBigEndian(this.v[i], out_Renamed, outOff + i * 4)
}
this.Reset();
return this.DIGEST_LENGTH
},
Update: function(input) {
this.xBuf[this.xBufOff++] = input;
if (this.xBufOff == this.xBuf.length) {
this.ProcessWord(this.xBuf, 0);
this.xBufOff = 0
}
this.byteCount++
},
BlockUpdate: function(input, inOff, length) {
while ((this.xBufOff != 0) && (length > 0)) {
this.Update(input[inOff]);
inOff++;
length--
}
while (length > this.xBuf.length) {
this.ProcessWord(input, inOff);
inOff += this.xBuf.length;
length -= this.xBuf.length;
this.byteCount += this.xBuf.length
}
while (length > 0) {
this.Update(input[inOff]);
inOff++;
length--
}
},
Finish: function() {
var bitLength = (this.byteCount << 3);
this.Update((128));
while (this.xBufOff != 0) this.Update((0));
this.ProcessLength(bitLength);
this.ProcessBlock()
},
ROTATE: function(x, n) {
return (x << n) | (this.URShift(x, (32 - n)))
},
P0: function(X) {
return ((X) ^ this.ROTATE((X), 9) ^ this.ROTATE((X), 17))
},
P1: function(X) {
return ((X) ^ this.ROTATE((X), 15) ^ this.ROTATE((X), 23))
},
FF_00_15: function(X, Y, Z) {
return (X ^ Y ^ Z)
},
FF_16_63: function(X, Y, Z) {
return ((X & Y) | (X & Z) | (Y & Z))
},
GG_00_15: function(X, Y, Z) {
return (X ^ Y ^ Z)
},
GG_16_63: function(X, Y, Z) {
return ((X & Y) | (~X & Z))
},
URShift: function(number, bits) {
if (number > Int32.maxValue || number < Int32.minValue) {
number = Int32.parse(number)
}
if (number >= 0) {
return number >> bits
} else {
return (number >> bits) + (2 << ~bits)
}
},
URShiftLong: function(number, bits) {
var returnV;
var big = new BigInteger();
big.fromInt(number);
if (big.signum() >= 0) {
returnV = big.shiftRight(bits).intValue()
} else {
var bigAdd = new BigInteger();
bigAdd.fromInt(2);
var shiftLeftBits = ~bits;
var shiftLeftNumber = '';
if (shiftLeftBits < 0) {
var shiftRightBits = 64 + shiftLeftBits;
for (var i = 0; i < shiftRightBits; i++) {
shiftLeftNumber += '0'
}
var shiftLeftNumberBigAdd = new BigInteger();
shiftLeftNumberBigAdd.fromInt(number >> bits);
var shiftLeftNumberBig = new BigInteger("10" + shiftLeftNumber, 2);
shiftLeftNumber = shiftLeftNumberBig.toRadix(10);
var r = shiftLeftNumberBig.add(shiftLeftNumberBigAdd);
returnV = r.toRadix(10)
} else {
shiftLeftNumber = bigAdd.shiftLeft((~bits)).intValue();
returnV = (number >> bits) + shiftLeftNumber
}
}
return returnV
},
GetZ: function(g, pubKeyHex) {
var userId = CryptoJS.enc.Utf8.parse("1234567812345678");
var len = userId.words.length * 4 * 8;
this.Update((len >> 8 & 0x00ff));
this.Update((len & 0x00ff));
var userIdWords = this.GetWords(userId.toString());
this.BlockUpdate(userIdWords, 0, userIdWords.length);
var aWords = this.GetWords(g.curve.a.toBigInteger().toRadix(16));
var bWords = this.GetWords(g.curve.b.toBigInteger().toRadix(16));
var gxWords = this.GetWords(g.getX().toBigInteger().toRadix(16));
var gyWords = this.GetWords(g.getY().toBigInteger().toRadix(16));
var pxWords = this.GetWords(pubKeyHex.substr(0, 64));
var pyWords = this.GetWords(pubKeyHex.substr(64, 64));
this.BlockUpdate(aWords, 0, aWords.length);
this.BlockUpdate(bWords, 0, bWords.length);
this.BlockUpdate(gxWords, 0, gxWords.length);
this.BlockUpdate(gyWords, 0, gyWords.length);
this.BlockUpdate(pxWords, 0, pxWords.length);
this.BlockUpdate(pyWords, 0, pyWords.length);
var md = new Array(this.GetDigestSize());
this.DoFinal(md, 0);
return md
},
GetWords: function(hexStr) {
var words = [];
var hexStrLength = hexStr.length;
for (var i = 0; i < hexStrLength; i += 2) {
words[words.length] = parseInt(hexStr.substr(i, 2), 16)
}
return words
},
GetHex: function(arr) {
var words = [];
var j = 0;
for (var i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j]) << (24 - (i % 8) * 4);
j++
}
var wordArray = new CryptoJS.lib.WordArray.init(words, arr.length);
return wordArray
}
};
Array.Clear = function(destinationArray, destinationIndex, length) {
for (elm in destinationArray) {
destinationArray[elm] = null
}
};
Array.Copy = function(sourceArray, sourceIndex, destinationArray, destinationIndex, length) {
var cloneArray = sourceArray.slice(sourceIndex, sourceIndex + length);
for (var i = 0; i < cloneArray.length; i++) {
destinationArray[destinationIndex] = cloneArray[i];
destinationIndex++
}
};
window.Int32 = {
minValue: -parseInt('10000000000000000000000000000000', 2),
maxValue: parseInt('1111111111111111111111111111111', 2),
parse: function(n) {
if (n < this.minValue) {
var bigInteger = new Number(-n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return (result + 1)
} else if (n > this.maxValue) {
var bigInteger = Number(n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return -(result + 1)
} else {
return n
}
},
parseByte: function(n) {
if (n < 0) {
var bigInteger = new Number(-n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return (result + 1)
} else if (n > 255) {
var bigInteger = Number(n);
var bigIntegerRadix = bigInteger.toString(2);
return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8), 2)
} else {
return n
}
}
};
================================================
FILE: JavaScript/demo/js/sm3-sm2-1.0.js
================================================
/*! sm3-sm2-1.0.js (c) Jonllen Peng | http://www.jonllen.com/
*/
/*
* sm3-sm2-1.0.js
*
* Copyright (c) 2014 Jonllen Peng (www.jonllen.com)
*/
/**
* @fileOverview
* @name sm3-sm2-1.0.js
* @author Jonllen (www.jonllen.com)
* @version 1.0.0 (2014-06-18)
*/
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
/**
* class for SM2 key generation, sm3WithSM2 signing and verifcation
* @name KJUR.crypto.SM3withSM2
* @class class for SM2 key generation, SM2 signing and verifcation
* @description
*
* CAUTION: Most of the case, you don't need to use this class except
* for generating an SM2 key pair. Please use {@link KJUR.crypto.Signature} class instead.
*
*
* This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
* Currently this class supports following named curves and their aliases.
*
*
secp256r1, NIST P-256, P-256, prime256v1 (*)
*
secp256k1 (*)
*
secp384r1, NIST P-384, P-384 (*)
*
sm2
*
*
*/
KJUR.crypto.SM3withSM2 = function(params) {
var curveName = "sm2"; // curve name default
var ecparams = null;
var prvKeyHex = null;
var pubKeyHex = null;
var rng = new SecureRandom();
var P_OVER_FOUR = null;
this.type = "SM2";
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;
}
/**
* 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 = KJUR.crypto.ECDSA({'curve': 'sm2'});
* var keypair = ec.generateKeyPairHex();
* var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
* var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
*/
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.SM3withSM2
* @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 = KJUR.crypto.SM3withSM2({'curve': 'sm2'});
* 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);
// k BigInteger
var k = null;
var kp = null;
var r = null;
var s = null;
var userD = d;
do
{
do
{
var keypair = this.generateKeyPairHex();
k = new BigInteger(keypair.ecprvhex, 16);
var pubkeyHex = keypair.ecpubhex;
kp = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
// r
r = e.add(kp.getX().toBigInteger());
r = r.mod(n);
}
while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));
// (1 + dA)~-1
var da_1 = userD.add(BigInteger.ONE);
da_1 = da_1.modInverse(n);
// s
s = r.multiply(userD);
s = k.subtract(s).mod(n);
s = da_1.multiply(s).mod(n);
}
while (s.equals(BigInteger.ZERO));
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.SM3withSM2
* @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 = KJUR.crypto.SM3withSM2({'curve': 'sm2'});
* 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'];
var t = r.add(s).mod(n);
if (t.equals(BigInteger.ZERO))
return false;
var x1y1 = G.multiply(s);
x1y1 = x1y1.add(Q.multiply(t));
var R = e.add(x1y1.getX().toBigInteger()).mod(n);
return r.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};
};
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']);
}
};
================================================
FILE: JavaScript/demo/js/sm3.js
================================================
(function(){var C=CryptoJS;var C_lib=C.lib;var WordArray=C_lib.WordArray;var Hasher=C_lib.Hasher;var C_algo=C.algo;var W=[];var SM3=C_algo.SM3=Hasher.extend({_doReset:function(){this._hash=new WordArray.init([0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e])},_doProcessBlock:function(M,offset){var H=this._hash.words;var a=H[0];var b=H[1];var c=H[2];var d=H[3];var e=H[4];for(var i=0;i<80;i++){if(i<16){W[i]=M[offset+i]|0}else{var n=W[i-3]^W[i-8]^W[i-14]^W[i-16];W[i]=(n<<1)|(n>>>31)}var t=((a<<5)|(a>>>27))+e+W[i];if(i<20){t+=((b&c)|(~b&d))+0x5a827999}else if(i<40){t+=(b^c^d)+0x6ed9eba1}else if(i<60){t+=((b&c)|(b&d)|(c&d))-0x70e44324}else{t+=(b^c^d)-0x359d3e2a}e=d;d=c;c=(b<<30)|(b>>>2);b=a;a=t}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},_doFinalize:function(){var data=this._data;var dataWords=data.words;var nBitsTotal=this._nDataBytes*8;var nBitsLeft=data.sigBytes*8;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;this._process();return this._hash},clone:function(){var clone=Hasher.clone.call(this);clone._hash=this._hash.clone();return clone}});C.SM3=Hasher._createHelper(SM3);C.HmacSM3=Hasher._createHmacHelper(SM3)}());function SM3Digest(){this.BYTE_LENGTH=64;this.xBuf=new Array();this.xBufOff=0;this.byteCount=0;this.DIGEST_LENGTH=32;this.v0=[0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e];this.v0=[0x7380166f,0x4914b2b9,0x172442d7,-628488704,-1452330820,0x163138aa,-477237683,-1325724082];this.v=new Array(8);this.v_=new Array(8);this.X0=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.X=new Array(68);this.xOff=0;this.T_00_15=0x79cc4519;this.T_16_63=0x7a879d8a;if(arguments.length>0){this.InitDigest(arguments[0])}else{this.Init()}}SM3Digest.prototype={Init:function(){this.xBuf=new Array(4);this.Reset()},InitDigest:function(t){this.xBuf=new Array(t.xBuf.length);Array.Copy(t.xBuf,0,this.xBuf,0,t.xBuf.length);this.xBufOff=t.xBufOff;this.byteCount=t.byteCount;Array.Copy(t.X,0,this.X,0,t.X.length);this.xOff=t.xOff;Array.Copy(t.v,0,this.v,0,t.v.length)},GetDigestSize:function(){return this.DIGEST_LENGTH},Reset:function(){this.byteCount=0;this.xBufOff=0;Array.Clear(this.xBuf,0,this.xBuf.length);Array.Copy(this.v0,0,this.v,0,this.v0.length);this.xOff=0;Array.Copy(this.X0,0,this.X,0,this.X0.length)},GetByteLength:function(){return this.BYTE_LENGTH},ProcessBlock:function(){var i;var ww=this.X;var ww_=new Array(64);for(i=16;i<68;i++){ww[i]=this.P1(ww[i-16]^ww[i-9]^(this.ROTATE(ww[i-3],15)))^(this.ROTATE(ww[i-13],7))^ww[i-6]}for(i=0;i<64;i++){ww_[i]=ww[i]^ww[i+4]}var vv=this.v;var vv_=this.v_;Array.Copy(vv,0,vv_,0,this.v0.length);var SS1,SS2,TT1,TT2,aaa;for(i=0;i<16;i++){aaa=this.ROTATE(vv_[0],12);SS1=Int32.parse(Int32.parse(aaa+vv_[4])+this.ROTATE(this.T_00_15,i));SS1=this.ROTATE(SS1,7);SS2=SS1^aaa;TT1=Int32.parse(Int32.parse(this.FF_00_15(vv_[0],vv_[1],vv_[2])+vv_[3])+SS2)+ww_[i];TT2=Int32.parse(Int32.parse(this.GG_00_15(vv_[4],vv_[5],vv_[6])+vv_[7])+SS1)+ww[i];vv_[3]=vv_[2];vv_[2]=this.ROTATE(vv_[1],9);vv_[1]=vv_[0];vv_[0]=TT1;vv_[7]=vv_[6];vv_[6]=this.ROTATE(vv_[5],19);vv_[5]=vv_[4];vv_[4]=this.P0(TT2)}for(i=16;i<64;i++){aaa=this.ROTATE(vv_[0],12);SS1=Int32.parse(Int32.parse(aaa+vv_[4])+this.ROTATE(this.T_16_63,i));SS1=this.ROTATE(SS1,7);SS2=SS1^aaa;TT1=Int32.parse(Int32.parse(this.FF_16_63(vv_[0],vv_[1],vv_[2])+vv_[3])+SS2)+ww_[i];TT2=Int32.parse(Int32.parse(this.GG_16_63(vv_[4],vv_[5],vv_[6])+vv_[7])+SS1)+ww[i];vv_[3]=vv_[2];vv_[2]=this.ROTATE(vv_[1],9);vv_[1]=vv_[0];vv_[0]=TT1;vv_[7]=vv_[6];vv_[6]=this.ROTATE(vv_[5],19);vv_[5]=vv_[4];vv_[4]=this.P0(TT2)}for(i=0;i<8;i++){vv[i]^=Int32.parse(vv_[i])}this.xOff=0;Array.Copy(this.X0,0,this.X,0,this.X0.length)},ProcessWord:function(in_Renamed,inOff){var n=in_Renamed[inOff]<<24;n|=(in_Renamed[++inOff]&0xff)<<16;n|=(in_Renamed[++inOff]&0xff)<<8;n|=(in_Renamed[++inOff]&0xff);this.X[this.xOff]=n;if(++this.xOff==16){this.ProcessBlock()}},ProcessLength:function(bitLength){if(this.xOff>14){this.ProcessBlock()}this.X[14]=(this.URShiftLong(bitLength,32));this.X[15]=(bitLength&(0xffffffff))},IntToBigEndian:function(n,bs,off){bs[off]=Int32.parseByte(this.URShift(n,24));bs[++off]=Int32.parseByte(this.URShift(n,16));bs[++off]=Int32.parseByte(this.URShift(n,8));bs[++off]=Int32.parseByte(n)},DoFinal:function(out_Renamed,outOff){this.Finish();for(var i=0;i<8;i++){this.IntToBigEndian(this.v[i],out_Renamed,outOff+i*4)}this.Reset();return this.DIGEST_LENGTH},Update:function(input){this.xBuf[this.xBufOff++]=input;if(this.xBufOff==this.xBuf.length){this.ProcessWord(this.xBuf,0);this.xBufOff=0}this.byteCount++},BlockUpdate:function(input,inOff,length){while((this.xBufOff!=0)&&(length>0)){this.Update(input[inOff]);inOff++;length--}while(length>this.xBuf.length){this.ProcessWord(input,inOff);inOff+=this.xBuf.length;length-=this.xBuf.length;this.byteCount+=this.xBuf.length}while(length>0){this.Update(input[inOff]);inOff++;length--}},Finish:function(){var bitLength=(this.byteCount<<3);this.Update((128));while(this.xBufOff!=0)this.Update((0));this.ProcessLength(bitLength);this.ProcessBlock()},ROTATE:function(x,n){return(x<Int32.maxValue||number=0){return number>>bits}else{return(number>>bits)+(2<<~bits)}},URShiftLong:function(number,bits){var returnV;var big=new BigInteger();big.fromInt(number);if(big.signum()>=0){returnV=big.shiftRight(bits).intValue()}else{var bigAdd=new BigInteger();bigAdd.fromInt(2);var shiftLeftBits=~bits;var shiftLeftNumber='';if(shiftLeftBits<0){var shiftRightBits=64+shiftLeftBits;for(var i=0;i>bits);var shiftLeftNumberBig=new BigInteger("10"+shiftLeftNumber,2);shiftLeftNumber=shiftLeftNumberBig.toRadix(10);var r=shiftLeftNumberBig.add(shiftLeftNumberBigAdd);returnV=r.toRadix(10)}else{shiftLeftNumber=bigAdd.shiftLeft((~bits)).intValue();returnV=(number>>bits)+shiftLeftNumber}}return returnV},GetZ:function(g,pubKeyHex){var userId=CryptoJS.enc.Utf8.parse("1234567812345678");var len=userId.words.length*4*8;this.Update((len>>8&0x00ff));this.Update((len&0x00ff));var userIdWords=this.GetWords(userId.toString());this.BlockUpdate(userIdWords,0,userIdWords.length);var aWords=this.GetWords(g.curve.a.toBigInteger().toRadix(16));var bWords=this.GetWords(g.curve.b.toBigInteger().toRadix(16));var gxWords=this.GetWords(g.getX().toBigInteger().toRadix(16));var gyWords=this.GetWords(g.getY().toBigInteger().toRadix(16));var pxWords=this.GetWords(pubKeyHex.substr(0,64));var pyWords=this.GetWords(pubKeyHex.substr(64,64));this.BlockUpdate(aWords,0,aWords.length);this.BlockUpdate(bWords,0,bWords.length);this.BlockUpdate(gxWords,0,gxWords.length);this.BlockUpdate(gyWords,0,gyWords.length);this.BlockUpdate(pxWords,0,pxWords.length);this.BlockUpdate(pyWords,0,pyWords.length);var md=new Array(this.GetDigestSize());this.DoFinal(md,0);return md},GetWords:function(hexStr){var words=[];var hexStrLength=hexStr.length;for(var i=0;i>>3]|=parseInt(arr[j])<<(24-(i%8)*4);j++}var wordArray=new CryptoJS.lib.WordArray.init(words,arr.length);return wordArray}};Array.Clear=function(destinationArray,destinationIndex,length){for(elm in destinationArray){destinationArray[elm]=null}};Array.Copy=function(sourceArray,sourceIndex,destinationArray,destinationIndex,length){var cloneArray=sourceArray.slice(sourceIndex,sourceIndex+length);for(var i=0;ithis.maxValue){var bigInteger=Number(n);var bigIntegerRadix=bigInteger.toString(2);var subBigIntegerRadix=bigIntegerRadix.substr(bigIntegerRadix.length-31,31);var reBigIntegerRadix='';for(var i=0;i255){var bigInteger=Number(n);var bigIntegerRadix=bigInteger.toString(2);return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length-8,8),2)}else{return n}}};
================================================
FILE: JavaScript/demo/js/sm4.js
================================================
/*! sm4-1.0.js (c) Windard Yang | https://www.windard.com/
*/
/*
* sm4-1.0.js
*
* Copyright (c) 2014 Windard Yang (www.windard.com)
*/
/**
* @fileOverview
* @name sm4-1.0.js
* @author Windard (www.windard.com)
* @version 1.0.0 (2016-11-17)
*/
/* this is sm4 in javascript by windard , today is 2016 11-17 ,
*I'm afraid that can I finished this project , but after all
*in December, everything will be done , that's prefect
*/
/*
* garbage , rubbish programe language, should havn't big decimal number
* can't circular bitwise left shift, can do xor well
*/
/*
* fuck it at all , finally finished it , and there has many other works need to do
*
*/
var SboxTable = new Array();
SboxTable[ 0] = new Array(0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05);
SboxTable[ 1] = new Array(0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99);
SboxTable[ 2] = new Array(0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62);
SboxTable[ 3] = new Array(0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6);
SboxTable[ 4] = new Array(0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8);
SboxTable[ 5] = new Array(0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35);
SboxTable[ 6] = new Array(0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87);
SboxTable[ 7] = new Array(0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e);
SboxTable[ 8] = new Array(0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1);
SboxTable[ 9] = new Array(0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3);
SboxTable[10] = new Array(0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f);
SboxTable[11] = new Array(0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51);
SboxTable[12] = new Array(0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8);
SboxTable[13] = new Array(0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0);
SboxTable[14] = new Array(0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84);
SboxTable[15] = new Array(0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48);
var CK = new Array(
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
);
var FK = new Array(0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc);
// function bigxor(a, b) {
// if (a.toString(2).length < 33 && b.toString(2).length < 33){
// return a ^ b
// }
// var abin = a.toString(2);
// var bbin = b.toString(2);
// var loggest = abin.length >= bbin.length ? abin.length : bbin.length;
// abin = abin.length == loggest ? abin :"0".repeat(loggest - abin.length) + abin;
// bbin = bbin.length == loggest ? bbin :"0".repeat(loggest - bbin.length) + bbin;
// var result = "";
// for (var i = loggest - 1; i >= 0; i--) {
// result = abin[i] == bbin[i] ? '0'+result : '1'+result;
// };
// return parseInt(result, 2);
// }
function bigxor(a, b){
return a ^ b
}
// function leftshift(a, n, size=32) {
// var result = new Array(size);
// result.fill(0);
// var bin = a.toString(2);
// bin = bin.length == size ? bin :"0".repeat(size - bin.length) + bin;
// for (var i = bin.length - 1; i >= 0; i--) {
// result[(i - n + size)%size] = bin[i];
// };
// result = result.join("");
// return parseInt(result, 2);
// }
function leftshift(a, n, size=32) {
n = n % size
return (a << n) | (a >>> (size - n))
}
function prefixInteger(str, length) {
return Array(length+1).join("0").split("").concat(String(str).split(""))
.slice(-length).join("");
}
// function sm4Sbox(a) {
// var a1 = prefixInteger(a.toString(16),8).slice(0,2);
// var a2 = prefixInteger(a.toString(16),8).slice(2,4);
// var a3 = prefixInteger(a.toString(16),8).slice(4,6);
// var a4 = prefixInteger(a.toString(16),8).slice(6,8);
// var b1 = SboxTable[parseInt(a1[0], 16)][parseInt(a1[1], 16)];
// var b2 = SboxTable[parseInt(a2[0], 16)][parseInt(a2[1], 16)];
// var b3 = SboxTable[parseInt(a3[0], 16)][parseInt(a3[1], 16)];
// var b4 = SboxTable[parseInt(a4[0], 16)][parseInt(a4[1], 16)];
// return parseInt(prefixInteger(b1.toString(16), 2) + prefixInteger(b2.toString(16), 2) + prefixInteger(b3.toString(16), 2) + prefixInteger(b4.toString(16), 2) , 16)
// }
function sm4Sbox(a) {
var b1 = SboxTable[(a & 0xf0000000) >>> 28][(a & 0x0f000000) >>> 24]
var b2 = SboxTable[(a & 0x00f00000) >>> 20][(a & 0x000f0000) >>> 16]
var b3 = SboxTable[(a & 0x0000f000) >>> 12][(a & 0x00000f00) >>> 8]
var b4 = SboxTable[(a & 0x000000f0) >>> 4][(a & 0x0000000f) >>> 0]
return (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)
}
function GET_ULONG_BE (a) {
a = sm4Sbox(a)
return bigxor(bigxor(bigxor(a, leftshift(a, 2)), bigxor(leftshift(a, 10), leftshift(a, 18))), leftshift(a, 24))
}
function PUT_ULONG_BE(b) {
b = sm4Sbox(b)
return bigxor(b, bigxor(leftshift(b, 13), leftshift(b, 23)));
}
function sm4_getkey (MK) {
var K = new Array();
var rk = new Array();
K[0] = bigxor(MK[0], FK[0]);
K[1] = bigxor(MK[1], FK[1]);
K[2] = bigxor(MK[2], FK[2]);
K[3] = bigxor(MK[3], FK[3]);
for (var i = 0; i < 32; i++) {
K[i+4] = bigxor(K[i], PUT_ULONG_BE(bigxor(bigxor(K[i+1], K[i+2]), bigxor(K[i+3], CK[i]))));
rk[i] = K[i+4].toString(16);
};
return rk;
}
function KJUR_encrypt_sm4 (messsage, key, method) {
var MK = key;
var X = messsage;
var rk = sm4_getkey(MK);
for (var i = 0; i < 32; i++) {
X[i+4] = bigxor(X[i], GET_ULONG_BE(bigxor(bigxor(X[i+1], X[i+2]), bigxor(X[i+3], parseInt(rk[i], 16)))))
};
var Y = new Array(X[35], X[34], X[33], X[32])
return Y;
}
function KJUR_decrypt_sm4 (ciphertext, key, method) {
var MK = key;
var X = ciphertext;
var frk = sm4_getkey(MK);
var rk = new Array()
for (var i = frk.length - 1; i >= 0; i--) {
rk[frk.length - 1 - i] = frk[i]
};
for (var i = 0; i < 32; i++) {
X[i+4] = bigxor(X[i], GET_ULONG_BE(bigxor(bigxor(X[i+1], X[i+2]), bigxor(X[i+3], parseInt(rk[i], 16)))))
};
var Y = new Array(X[35], X[34], X[33], X[32])
return Y;
}
================================================
FILE: JavaScript/demo/js/tripledes.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var BlockCipher = C_lib.BlockCipher;
var C_algo = C.algo;
// Permuted Choice 1 constants
var PC1 = [
57, 49, 41, 33, 25, 17, 9, 1,
58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 27, 19, 11, 3,
60, 52, 44, 36, 63, 55, 47, 39,
31, 23, 15, 7, 62, 54, 46, 38,
30, 22, 14, 6, 61, 53, 45, 37,
29, 21, 13, 5, 28, 20, 12, 4
];
// Permuted Choice 2 constants
var PC2 = [
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
];
// Cumulative bit shift constants
var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
// SBOXes and round permutation constants
var SBOX_P = [
{
0x0: 0x808200,
0x10000000: 0x8000,
0x20000000: 0x808002,
0x30000000: 0x2,
0x40000000: 0x200,
0x50000000: 0x808202,
0x60000000: 0x800202,
0x70000000: 0x800000,
0x80000000: 0x202,
0x90000000: 0x800200,
0xa0000000: 0x8200,
0xb0000000: 0x808000,
0xc0000000: 0x8002,
0xd0000000: 0x800002,
0xe0000000: 0x0,
0xf0000000: 0x8202,
0x8000000: 0x0,
0x18000000: 0x808202,
0x28000000: 0x8202,
0x38000000: 0x8000,
0x48000000: 0x808200,
0x58000000: 0x200,
0x68000000: 0x808002,
0x78000000: 0x2,
0x88000000: 0x800200,
0x98000000: 0x8200,
0xa8000000: 0x808000,
0xb8000000: 0x800202,
0xc8000000: 0x800002,
0xd8000000: 0x8002,
0xe8000000: 0x202,
0xf8000000: 0x800000,
0x1: 0x8000,
0x10000001: 0x2,
0x20000001: 0x808200,
0x30000001: 0x800000,
0x40000001: 0x808002,
0x50000001: 0x8200,
0x60000001: 0x200,
0x70000001: 0x800202,
0x80000001: 0x808202,
0x90000001: 0x808000,
0xa0000001: 0x800002,
0xb0000001: 0x8202,
0xc0000001: 0x202,
0xd0000001: 0x800200,
0xe0000001: 0x8002,
0xf0000001: 0x0,
0x8000001: 0x808202,
0x18000001: 0x808000,
0x28000001: 0x800000,
0x38000001: 0x200,
0x48000001: 0x8000,
0x58000001: 0x800002,
0x68000001: 0x2,
0x78000001: 0x8202,
0x88000001: 0x8002,
0x98000001: 0x800202,
0xa8000001: 0x202,
0xb8000001: 0x808200,
0xc8000001: 0x800200,
0xd8000001: 0x0,
0xe8000001: 0x8200,
0xf8000001: 0x808002
},
{
0x0: 0x40084010,
0x1000000: 0x4000,
0x2000000: 0x80000,
0x3000000: 0x40080010,
0x4000000: 0x40000010,
0x5000000: 0x40084000,
0x6000000: 0x40004000,
0x7000000: 0x10,
0x8000000: 0x84000,
0x9000000: 0x40004010,
0xa000000: 0x40000000,
0xb000000: 0x84010,
0xc000000: 0x80010,
0xd000000: 0x0,
0xe000000: 0x4010,
0xf000000: 0x40080000,
0x800000: 0x40004000,
0x1800000: 0x84010,
0x2800000: 0x10,
0x3800000: 0x40004010,
0x4800000: 0x40084010,
0x5800000: 0x40000000,
0x6800000: 0x80000,
0x7800000: 0x40080010,
0x8800000: 0x80010,
0x9800000: 0x0,
0xa800000: 0x4000,
0xb800000: 0x40080000,
0xc800000: 0x40000010,
0xd800000: 0x84000,
0xe800000: 0x40084000,
0xf800000: 0x4010,
0x10000000: 0x0,
0x11000000: 0x40080010,
0x12000000: 0x40004010,
0x13000000: 0x40084000,
0x14000000: 0x40080000,
0x15000000: 0x10,
0x16000000: 0x84010,
0x17000000: 0x4000,
0x18000000: 0x4010,
0x19000000: 0x80000,
0x1a000000: 0x80010,
0x1b000000: 0x40000010,
0x1c000000: 0x84000,
0x1d000000: 0x40004000,
0x1e000000: 0x40000000,
0x1f000000: 0x40084010,
0x10800000: 0x84010,
0x11800000: 0x80000,
0x12800000: 0x40080000,
0x13800000: 0x4000,
0x14800000: 0x40004000,
0x15800000: 0x40084010,
0x16800000: 0x10,
0x17800000: 0x40000000,
0x18800000: 0x40084000,
0x19800000: 0x40000010,
0x1a800000: 0x40004010,
0x1b800000: 0x80010,
0x1c800000: 0x0,
0x1d800000: 0x4010,
0x1e800000: 0x40080010,
0x1f800000: 0x84000
},
{
0x0: 0x104,
0x100000: 0x0,
0x200000: 0x4000100,
0x300000: 0x10104,
0x400000: 0x10004,
0x500000: 0x4000004,
0x600000: 0x4010104,
0x700000: 0x4010000,
0x800000: 0x4000000,
0x900000: 0x4010100,
0xa00000: 0x10100,
0xb00000: 0x4010004,
0xc00000: 0x4000104,
0xd00000: 0x10000,
0xe00000: 0x4,
0xf00000: 0x100,
0x80000: 0x4010100,
0x180000: 0x4010004,
0x280000: 0x0,
0x380000: 0x4000100,
0x480000: 0x4000004,
0x580000: 0x10000,
0x680000: 0x10004,
0x780000: 0x104,
0x880000: 0x4,
0x980000: 0x100,
0xa80000: 0x4010000,
0xb80000: 0x10104,
0xc80000: 0x10100,
0xd80000: 0x4000104,
0xe80000: 0x4010104,
0xf80000: 0x4000000,
0x1000000: 0x4010100,
0x1100000: 0x10004,
0x1200000: 0x10000,
0x1300000: 0x4000100,
0x1400000: 0x100,
0x1500000: 0x4010104,
0x1600000: 0x4000004,
0x1700000: 0x0,
0x1800000: 0x4000104,
0x1900000: 0x4000000,
0x1a00000: 0x4,
0x1b00000: 0x10100,
0x1c00000: 0x4010000,
0x1d00000: 0x104,
0x1e00000: 0x10104,
0x1f00000: 0x4010004,
0x1080000: 0x4000000,
0x1180000: 0x104,
0x1280000: 0x4010100,
0x1380000: 0x0,
0x1480000: 0x10004,
0x1580000: 0x4000100,
0x1680000: 0x100,
0x1780000: 0x4010004,
0x1880000: 0x10000,
0x1980000: 0x4010104,
0x1a80000: 0x10104,
0x1b80000: 0x4000004,
0x1c80000: 0x4000104,
0x1d80000: 0x4010000,
0x1e80000: 0x4,
0x1f80000: 0x10100
},
{
0x0: 0x80401000,
0x10000: 0x80001040,
0x20000: 0x401040,
0x30000: 0x80400000,
0x40000: 0x0,
0x50000: 0x401000,
0x60000: 0x80000040,
0x70000: 0x400040,
0x80000: 0x80000000,
0x90000: 0x400000,
0xa0000: 0x40,
0xb0000: 0x80001000,
0xc0000: 0x80400040,
0xd0000: 0x1040,
0xe0000: 0x1000,
0xf0000: 0x80401040,
0x8000: 0x80001040,
0x18000: 0x40,
0x28000: 0x80400040,
0x38000: 0x80001000,
0x48000: 0x401000,
0x58000: 0x80401040,
0x68000: 0x0,
0x78000: 0x80400000,
0x88000: 0x1000,
0x98000: 0x80401000,
0xa8000: 0x400000,
0xb8000: 0x1040,
0xc8000: 0x80000000,
0xd8000: 0x400040,
0xe8000: 0x401040,
0xf8000: 0x80000040,
0x100000: 0x400040,
0x110000: 0x401000,
0x120000: 0x80000040,
0x130000: 0x0,
0x140000: 0x1040,
0x150000: 0x80400040,
0x160000: 0x80401000,
0x170000: 0x80001040,
0x180000: 0x80401040,
0x190000: 0x80000000,
0x1a0000: 0x80400000,
0x1b0000: 0x401040,
0x1c0000: 0x80001000,
0x1d0000: 0x400000,
0x1e0000: 0x40,
0x1f0000: 0x1000,
0x108000: 0x80400000,
0x118000: 0x80401040,
0x128000: 0x0,
0x138000: 0x401000,
0x148000: 0x400040,
0x158000: 0x80000000,
0x168000: 0x80001040,
0x178000: 0x40,
0x188000: 0x80000040,
0x198000: 0x1000,
0x1a8000: 0x80001000,
0x1b8000: 0x80400040,
0x1c8000: 0x1040,
0x1d8000: 0x80401000,
0x1e8000: 0x400000,
0x1f8000: 0x401040
},
{
0x0: 0x80,
0x1000: 0x1040000,
0x2000: 0x40000,
0x3000: 0x20000000,
0x4000: 0x20040080,
0x5000: 0x1000080,
0x6000: 0x21000080,
0x7000: 0x40080,
0x8000: 0x1000000,
0x9000: 0x20040000,
0xa000: 0x20000080,
0xb000: 0x21040080,
0xc000: 0x21040000,
0xd000: 0x0,
0xe000: 0x1040080,
0xf000: 0x21000000,
0x800: 0x1040080,
0x1800: 0x21000080,
0x2800: 0x80,
0x3800: 0x1040000,
0x4800: 0x40000,
0x5800: 0x20040080,
0x6800: 0x21040000,
0x7800: 0x20000000,
0x8800: 0x20040000,
0x9800: 0x0,
0xa800: 0x21040080,
0xb800: 0x1000080,
0xc800: 0x20000080,
0xd800: 0x21000000,
0xe800: 0x1000000,
0xf800: 0x40080,
0x10000: 0x40000,
0x11000: 0x80,
0x12000: 0x20000000,
0x13000: 0x21000080,
0x14000: 0x1000080,
0x15000: 0x21040000,
0x16000: 0x20040080,
0x17000: 0x1000000,
0x18000: 0x21040080,
0x19000: 0x21000000,
0x1a000: 0x1040000,
0x1b000: 0x20040000,
0x1c000: 0x40080,
0x1d000: 0x20000080,
0x1e000: 0x0,
0x1f000: 0x1040080,
0x10800: 0x21000080,
0x11800: 0x1000000,
0x12800: 0x1040000,
0x13800: 0x20040080,
0x14800: 0x20000000,
0x15800: 0x1040080,
0x16800: 0x80,
0x17800: 0x21040000,
0x18800: 0x40080,
0x19800: 0x21040080,
0x1a800: 0x0,
0x1b800: 0x21000000,
0x1c800: 0x1000080,
0x1d800: 0x40000,
0x1e800: 0x20040000,
0x1f800: 0x20000080
},
{
0x0: 0x10000008,
0x100: 0x2000,
0x200: 0x10200000,
0x300: 0x10202008,
0x400: 0x10002000,
0x500: 0x200000,
0x600: 0x200008,
0x700: 0x10000000,
0x800: 0x0,
0x900: 0x10002008,
0xa00: 0x202000,
0xb00: 0x8,
0xc00: 0x10200008,
0xd00: 0x202008,
0xe00: 0x2008,
0xf00: 0x10202000,
0x80: 0x10200000,
0x180: 0x10202008,
0x280: 0x8,
0x380: 0x200000,
0x480: 0x202008,
0x580: 0x10000008,
0x680: 0x10002000,
0x780: 0x2008,
0x880: 0x200008,
0x980: 0x2000,
0xa80: 0x10002008,
0xb80: 0x10200008,
0xc80: 0x0,
0xd80: 0x10202000,
0xe80: 0x202000,
0xf80: 0x10000000,
0x1000: 0x10002000,
0x1100: 0x10200008,
0x1200: 0x10202008,
0x1300: 0x2008,
0x1400: 0x200000,
0x1500: 0x10000000,
0x1600: 0x10000008,
0x1700: 0x202000,
0x1800: 0x202008,
0x1900: 0x0,
0x1a00: 0x8,
0x1b00: 0x10200000,
0x1c00: 0x2000,
0x1d00: 0x10002008,
0x1e00: 0x10202000,
0x1f00: 0x200008,
0x1080: 0x8,
0x1180: 0x202000,
0x1280: 0x200000,
0x1380: 0x10000008,
0x1480: 0x10002000,
0x1580: 0x2008,
0x1680: 0x10202008,
0x1780: 0x10200000,
0x1880: 0x10202000,
0x1980: 0x10200008,
0x1a80: 0x2000,
0x1b80: 0x202008,
0x1c80: 0x200008,
0x1d80: 0x0,
0x1e80: 0x10000000,
0x1f80: 0x10002008
},
{
0x0: 0x100000,
0x10: 0x2000401,
0x20: 0x400,
0x30: 0x100401,
0x40: 0x2100401,
0x50: 0x0,
0x60: 0x1,
0x70: 0x2100001,
0x80: 0x2000400,
0x90: 0x100001,
0xa0: 0x2000001,
0xb0: 0x2100400,
0xc0: 0x2100000,
0xd0: 0x401,
0xe0: 0x100400,
0xf0: 0x2000000,
0x8: 0x2100001,
0x18: 0x0,
0x28: 0x2000401,
0x38: 0x2100400,
0x48: 0x100000,
0x58: 0x2000001,
0x68: 0x2000000,
0x78: 0x401,
0x88: 0x100401,
0x98: 0x2000400,
0xa8: 0x2100000,
0xb8: 0x100001,
0xc8: 0x400,
0xd8: 0x2100401,
0xe8: 0x1,
0xf8: 0x100400,
0x100: 0x2000000,
0x110: 0x100000,
0x120: 0x2000401,
0x130: 0x2100001,
0x140: 0x100001,
0x150: 0x2000400,
0x160: 0x2100400,
0x170: 0x100401,
0x180: 0x401,
0x190: 0x2100401,
0x1a0: 0x100400,
0x1b0: 0x1,
0x1c0: 0x0,
0x1d0: 0x2100000,
0x1e0: 0x2000001,
0x1f0: 0x400,
0x108: 0x100400,
0x118: 0x2000401,
0x128: 0x2100001,
0x138: 0x1,
0x148: 0x2000000,
0x158: 0x100000,
0x168: 0x401,
0x178: 0x2100400,
0x188: 0x2000001,
0x198: 0x2100000,
0x1a8: 0x0,
0x1b8: 0x2100401,
0x1c8: 0x100401,
0x1d8: 0x400,
0x1e8: 0x2000400,
0x1f8: 0x100001
},
{
0x0: 0x8000820,
0x1: 0x20000,
0x2: 0x8000000,
0x3: 0x20,
0x4: 0x20020,
0x5: 0x8020820,
0x6: 0x8020800,
0x7: 0x800,
0x8: 0x8020000,
0x9: 0x8000800,
0xa: 0x20800,
0xb: 0x8020020,
0xc: 0x820,
0xd: 0x0,
0xe: 0x8000020,
0xf: 0x20820,
0x80000000: 0x800,
0x80000001: 0x8020820,
0x80000002: 0x8000820,
0x80000003: 0x8000000,
0x80000004: 0x8020000,
0x80000005: 0x20800,
0x80000006: 0x20820,
0x80000007: 0x20,
0x80000008: 0x8000020,
0x80000009: 0x820,
0x8000000a: 0x20020,
0x8000000b: 0x8020800,
0x8000000c: 0x0,
0x8000000d: 0x8020020,
0x8000000e: 0x8000800,
0x8000000f: 0x20000,
0x10: 0x20820,
0x11: 0x8020800,
0x12: 0x20,
0x13: 0x800,
0x14: 0x8000800,
0x15: 0x8000020,
0x16: 0x8020020,
0x17: 0x20000,
0x18: 0x0,
0x19: 0x20020,
0x1a: 0x8020000,
0x1b: 0x8000820,
0x1c: 0x8020820,
0x1d: 0x20800,
0x1e: 0x820,
0x1f: 0x8000000,
0x80000010: 0x20000,
0x80000011: 0x800,
0x80000012: 0x8020020,
0x80000013: 0x20820,
0x80000014: 0x20,
0x80000015: 0x8020000,
0x80000016: 0x8000000,
0x80000017: 0x8000820,
0x80000018: 0x8020820,
0x80000019: 0x8000020,
0x8000001a: 0x8000800,
0x8000001b: 0x0,
0x8000001c: 0x20800,
0x8000001d: 0x820,
0x8000001e: 0x20020,
0x8000001f: 0x8020800
}
];
// Masks that select the SBOX input
var SBOX_MASK = [
0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f
];
/**
* DES block cipher algorithm.
*/
var DES = C_algo.DES = BlockCipher.extend({
_doReset: function () {
// Shortcuts
var key = this._key;
var keyWords = key.words;
// Select 56 bits according to PC1
var keyBits = [];
for (var i = 0; i < 56; i++) {
var keyBitPos = PC1[i] - 1;
keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1;
}
// Assemble 16 subkeys
var subKeys = this._subKeys = [];
for (var nSubKey = 0; nSubKey < 16; nSubKey++) {
// Create subkey
var subKey = subKeys[nSubKey] = [];
// Shortcut
var bitShift = BIT_SHIFTS[nSubKey];
// Select 48 bits according to PC2
for (var i = 0; i < 24; i++) {
// Select from the left 28 key bits
subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6);
// Select from the right 28 key bits
subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6);
}
// Since each subkey is applied to an expanded 32-bit input,
// the subkey can be broken into 8 values scaled to 32-bits,
// which allows the key to be used without expansion
subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
for (var i = 1; i < 7; i++) {
subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3);
}
subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
}
// Compute inverse subkeys
var invSubKeys = this._invSubKeys = [];
for (var i = 0; i < 16; i++) {
invSubKeys[i] = subKeys[15 - i];
}
},
encryptBlock: function (M, offset) {
this._doCryptBlock(M, offset, this._subKeys);
},
decryptBlock: function (M, offset) {
this._doCryptBlock(M, offset, this._invSubKeys);
},
_doCryptBlock: function (M, offset, subKeys) {
// Get input
this._lBlock = M[offset];
this._rBlock = M[offset + 1];
// Initial permutation
exchangeLR.call(this, 4, 0x0f0f0f0f);
exchangeLR.call(this, 16, 0x0000ffff);
exchangeRL.call(this, 2, 0x33333333);
exchangeRL.call(this, 8, 0x00ff00ff);
exchangeLR.call(this, 1, 0x55555555);
// Rounds
for (var round = 0; round < 16; round++) {
// Shortcuts
var subKey = subKeys[round];
var lBlock = this._lBlock;
var rBlock = this._rBlock;
// Feistel function
var f = 0;
for (var i = 0; i < 8; i++) {
f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
}
this._lBlock = rBlock;
this._rBlock = lBlock ^ f;
}
// Undo swap from last round
var t = this._lBlock;
this._lBlock = this._rBlock;
this._rBlock = t;
// Final permutation
exchangeLR.call(this, 1, 0x55555555);
exchangeRL.call(this, 8, 0x00ff00ff);
exchangeRL.call(this, 2, 0x33333333);
exchangeLR.call(this, 16, 0x0000ffff);
exchangeLR.call(this, 4, 0x0f0f0f0f);
// Set output
M[offset] = this._lBlock;
M[offset + 1] = this._rBlock;
},
keySize: 64/32,
ivSize: 64/32,
blockSize: 64/32
});
// Swap bits across the left and right words
function exchangeLR(offset, mask) {
var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
this._rBlock ^= t;
this._lBlock ^= t << offset;
}
function exchangeRL(offset, mask) {
var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
this._lBlock ^= t;
this._rBlock ^= t << offset;
}
/**
* Shortcut functions to the cipher's object interface.
*
* @example
*
* var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
* var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg);
*/
C.DES = BlockCipher._createHelper(DES);
/**
* Triple-DES block cipher algorithm.
*/
var TripleDES = C_algo.TripleDES = BlockCipher.extend({
_doReset: function () {
// Shortcuts
var key = this._key;
var keyWords = key.words;
// Create DES instances
this._des1 = DES.createEncryptor(WordArray.create(keyWords.slice(0, 2)));
this._des2 = DES.createEncryptor(WordArray.create(keyWords.slice(2, 4)));
this._des3 = DES.createEncryptor(WordArray.create(keyWords.slice(4, 6)));
},
encryptBlock: function (M, offset) {
this._des1.encryptBlock(M, offset);
this._des2.decryptBlock(M, offset);
this._des3.encryptBlock(M, offset);
},
decryptBlock: function (M, offset) {
this._des3.decryptBlock(M, offset);
this._des2.encryptBlock(M, offset);
this._des1.decryptBlock(M, offset);
},
keySize: 192/32,
ivSize: 64/32,
blockSize: 64/32
});
/**
* Shortcut functions to the cipher's object interface.
*
* @example
*
* var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
* var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
*/
C.TripleDES = BlockCipher._createHelper(TripleDES);
}());
================================================
FILE: JavaScript/demo/js/utils.js
================================================
/*! utils-1.0.js (c) Windard Yang | https://www.windard.com/
*/
/*
* utils-1.0.js
*
* Copyright (c) 2014 Windard Yang (www.windard.com)
*/
/**
* @fileOverview
* @name utils-1.0.js
* @author Windard (www.windard.com)
* @version 1.0.0 (2017-11-15)
*/
function encode(s) {
return s.replace(/[\d\D]/g, function($) {
return ("000" + $.charCodeAt(0).toString(16)).slice(-4);
});
}
function decode(s) {
return s.replace(/.{4}/g, function($) {
return String.fromCharCode(parseInt($, 16));
});
}
function PKCS7_padding_encode(data){
var result = new Array();
for (var i = 0; i < data.length; i++) {
result.push(data.charCodeAt(i))
};
var size = 4-result.length%4
for (i = 0; i < size; i++) {
result.push(size)
};
return result;
}
function PKCS7_padding_decode(data){
var result="";
var size = data[data.length-1];
for (var i = 0; i < size ; i++) {
data.pop();
};
for(i = 0;i < data.length; i++) {
result += String.fromCharCode(data[i]);
};
return result;
}
function randomkey(key) {
var result = "";
for(var i = 0;i < key.length/2 ;i+=8 ) {
tempnum = bigxor(parseInt(key.slice(i,i+8), 16), Math.round(Math.random()*1000000000)).toString(16)
console.log(tempnum,tempnum.length)
result += tempnum.length == 8 ? tempnum : "0".repeat(8 - tempnum.length) + tempnum
}
return result;
}
function xorkey(key) {
var result = new Array();
for(var i = 0;i < key.length ;i+=8 ) {
result.push(parseInt(key.slice(i,i+8), 16))
}
return result;
}
function sm4_encode_cbc(data, key) {
var iv = new Array(0x01234567,0x89abcdef,0xfedcba98,0x76543210);
var message = new Array();
var result = new Array();
key = xorkey(key);
data = PKCS7_padding_encode(data);
for (var x = 0 ; x < data.length/4 ; x++) {
for (var i = 0 ; i < iv.length ; i++) {
message.push(bigxor(iv[i], data[i+x*4]));
};
ciphertext = KJUR_encrypt_sm4(message, key, "cbc")
iv = ciphertext
result = result.concat(ciphertext);
message = new Array();
}
return result;
}
function bigxor(a, b) {
var abin = a.toString(2);
var bbin = b.toString(2);
var loggest = abin.length >= bbin.length ? abin.length : bbin.length;
abin = abin.length == loggest ? abin :"0".repeat(loggest - abin.length) + abin;
bbin = bbin.length == loggest ? bbin :"0".repeat(loggest - bbin.length) + bbin;
var result = "";
for (var i = loggest - 1; i >= 0; i--) {
result = abin[i] == bbin[i] ? '0'+result : '1'+result;
};
return parseInt(result, 2);
}
function sm4_decode_cbc(data, key) {
var iv = new Array(0x01234567,0x89abcdef,0xfedcba98,0x76543210);
var message = new Array();
var result = new Array();
key = xorkey(key);
for(var x=data.length/4-1;x>=0;x--){
if(x==0){
iv = new Array(0x01234567,0x89abcdef,0xfedcba98,0x76543210);
}else{
iv = data.slice((x-1)*4,x*4)
}
message = KJUR_decrypt_sm4(data.slice(x*4,(x+1)*4), key);
for(var j=message.length-1;j>=0;j--){
result.push(bigxor(message[j], iv[j]))
}
}
result.reverse();
result = PKCS7_padding_decode(result);
return result;
}
================================================
FILE: JavaScript/demo/js/x509-1.1.js
================================================
/*! x509-1.1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* x509.js - X509 class to read subject public key from certificate.
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name x509-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version x509 1.1.2 (2013-Oct-06)
* @since jsrsasign 1.x.x
* @license MIT License
*/
/*
* Depends:
* base64.js
* rsa.js
* asn1hex.js
*/
/**
* X.509 certificate class.
* @class X.509 certificate class
* @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
* @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
* @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
* @property {String} hex hexacedimal string for X.509 certificate.
* @author Kenji Urushima
* @version 1.0.1 (08 May 2012)
* @see 'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/
*/
function X509() {
this.subjectPublicKeyRSA = null;
this.subjectPublicKeyRSA_hN = null;
this.subjectPublicKeyRSA_hE = null;
this.hex = null;
// ===== get basic fields from hex =====================================
/**
* get hexadecimal string of serialNumber field of certificate.
* @name getSerialNumberHex
* @memberOf X509#
* @function
*/
this.getSerialNumberHex = function() {
return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
};
/**
* get hexadecimal string of issuer field of certificate.
* @name getIssuerHex
* @memberOf X509#
* @function
*/
this.getIssuerHex = function() {
return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
};
/**
* get string of issuer field of certificate.
* @name getIssuerString
* @memberOf X509#
* @function
*/
this.getIssuerString = function() {
return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
};
/**
* get hexadecimal string of subject field of certificate.
* @name getSubjectHex
* @memberOf X509#
* @function
*/
this.getSubjectHex = function() {
return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
};
/**
* get string of subject field of certificate.
* @name getSubjectString
* @memberOf X509#
* @function
*/
this.getSubjectString = function() {
return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
};
/**
* get notBefore field string of certificate.
* @name getNotBefore
* @memberOf X509#
* @function
*/
this.getNotBefore = function() {
var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
s = s.replace(/(..)/g, "%$1");
s = decodeURIComponent(s);
return s;
};
/**
* get notAfter field string of certificate.
* @name getNotAfter
* @memberOf X509#
* @function
*/
this.getNotAfter = function() {
var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
s = s.replace(/(..)/g, "%$1");
s = decodeURIComponent(s);
return s;
};
// ===== read certificate public key ==========================
// ===== read certificate =====================================
/**
* read PEM formatted X.509 certificate from string.
* @name readCertPEM
* @memberOf X509#
* @function
* @param {String} sCertPEM string for PEM formatted X.509 certificate
*/
this.readCertPEM = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
var rsa = new RSAKey();
rsa.setPublic(a[0], a[1]);
this.subjectPublicKeyRSA = rsa;
this.subjectPublicKeyRSA_hN = a[0];
this.subjectPublicKeyRSA_hE = a[1];
this.hex = hCert;
};
this.readCertPEMWithoutRSAInit = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
this.subjectPublicKeyRSA_hN = a[0];
this.subjectPublicKeyRSA_hE = a[1];
this.hex = hCert;
};
};
X509.pemToBase64 = function(sCertPEM) {
var s = sCertPEM;
s = s.replace("-----BEGIN CERTIFICATE-----", "");
s = s.replace("-----END CERTIFICATE-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
};
X509.pemToHex = function(sCertPEM) {
var b64Cert = X509.pemToBase64(sCertPEM);
var hCert = b64tohex(b64Cert);
return hCert;
};
// NOTE: Without BITSTRING encapsulation.
X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert);
if (pInfo == -1) return -1;
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo);
if (a.length != 2) return -1;
var pBitString = a[1];
if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
return pBitStringV + 2;
};
// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
// NOTE: v1 and v3 supported
X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) {
var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert);
if (a.length < 1) return -1;
if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
if (a.length < 6) return -1;
return a[6];
} else {
if (a.length < 5) return -1;
return a[5];
}
};
X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
if (a.length != 2) return [];
var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
if (hN != null && hE != null) {
return [hN, hE];
} else {
return [];
}
};
X509.getHexTbsCertificateFromCert = function(hCert) {
var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
return pTbsCert;
};
X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
return a;
};
X509.hex2dn = function(hDN) {
var s = "";
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
for (var i = 0; i < a.length; i++) {
var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
s = s + "/" + X509.hex2rdn(hRDN);
}
return s;
};
X509.hex2rdn = function(hRDN) {
var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
var type = "";
try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
hValue = hValue.replace(/(..)/g, "%$1");
var value = decodeURIComponent(hValue);
return type + "=" + value;
};
X509.DN_ATTRHEX = {
"0603550406": "C",
"060355040a": "O",
"060355040b": "OU",
"0603550403": "CN",
"0603550405": "SN",
"0603550408": "ST",
"0603550407": "L",
};
/**
* get RSAKey/ECDSA public key object from PEM certificate string
* @name getPublicKeyFromCertPEM
* @memberOf X509
* @function
* @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
* @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
* @since x509 1.1.1
* @description
* NOTE: DSA is also supported since x509 1.1.2.
*/
X509.getPublicKeyFromCertPEM = function(sCertPEM) {
var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);
if (info.algoid == "2a864886f70d010101") { // RSA
var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
var key = new RSAKey();
key.setPublic(aRSA.n, aRSA.e);
return key;
} else if (info.algoid == "2a8648ce3d0201") { // ECC
var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
key.setPublicKeyHex(info.keyhex);
return key;
} else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
y = y.substr(2);
var key = new KJUR.crypto.DSA();
key.setPublic(new BigInteger(p, 16),
new BigInteger(q, 16),
new BigInteger(g, 16),
new BigInteger(y, 16));
return key;
} else {
throw "unsupported key";
}
};
/**
* get public key information from PEM certificate
* @name getPublicKeyInfoPropOfCertPEM
* @memberOf X509
* @function
* @param {String} sCertPEM string of PEM formatted certificate
* @return {Hash} hash of information for public key
* @since x509 1.1.1
* @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
*
keyhex - hexadecimal string of key in the certificate
*
* @since x509 1.1.1
*/
X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
var result = {};
result.algparam = null;
var hCert = X509.pemToHex(sCertPEM);
// 1. Certificate ASN.1
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0);
if (a1.length != 3)
throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
// 2. tbsCertificate
if (hCert.substr(a1[0], 2) != "30")
throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq
var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]);
// 3. subjectPublicKeyInfo
if (a2.length < 7)
throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]);
if (a3.length != 2)
throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey
// 4. AlgId
var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);
if (a4.length != 2)
throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId
result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);
if (hCert.substr(a4[1], 2) == "06") { // EC
result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
} else if (hCert.substr(a4[1], 2) == "30") { // DSA
result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
}
// 5. Public Key Hex
if (hCert.substr(a3[1], 02) != "03")
throw "malformed X.509 certificate PEM (code:006)"; // not bitstring
var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
result.keyhex = unusedBitAndKeyHex.substr(2);
return result;
};
/*
X509.prototype.readCertPEM = _x509_readCertPEM;
X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
X509.prototype.getIssuerHex = _x509_getIssuerHex;
X509.prototype.getSubjectHex = _x509_getSubjectHex;
X509.prototype.getIssuerString = _x509_getIssuerString;
X509.prototype.getSubjectString = _x509_getSubjectString;
X509.prototype.getNotBefore = _x509_getNotBefore;
X509.prototype.getNotAfter = _x509_getNotAfter;
*/
================================================
FILE: JavaScript/demo/js/yahoo-min.js
================================================
/*
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(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l ";if(!f.isObject(j)){return j+"";}else{if(j instanceof Date||("nodeType" in j&&"tagName" in j)){return j;}else{if(f.isFunction(j)){return k;}}}p=(f.isNumber(p))?p:3;if(f.isArray(j)){r.push("[");for(l=0,n=j.length;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j;
}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;m国密算法实现
================================================
FILE: JavaScript/des/JavaScript DES Example.html
================================================
JavaScript DES Example
The Data Encryption Standard (DES) was introduced in 19xx and
is formally defined in
FIPS 46-3
Using a 56-bit key (usually entered as a 64-bit value with odd parity bits),
working on a 64-bit data block.
There are several modes for using DES to encrypt blocks of data
that may be more (or less) than 8 bytes in size. Click here
for more details on how DES works.
The 56-bit key used by DES is no longer sufficient for good security, but
many applications use triple-DES
(encrypt using key part A, decrypt using key part B, encrypt using key part A)
to acheive a 112-bit key while maintaining compatibility with
plain DES (using key part A = key part B).
Decryption is identical to encryption, except that the subkeys are used in the
opposite order. That is, subkey 16 is used in round 1, subkey 15 is used in round 2, etc.,
ending with subkey 1 being used in round 16.
The f function mixes the bits of the R portion using the
subkey for the current round.
First the 32-bit R value is expanded to 48 bits using a permutation E.
That value is then exclusive-or'ed with the subkey. The 48 bits are then divided into
eight 6-bit chunks, each of which is fed into a S-Box that mixes the bits and produces
a 4-bit output. Those 4-bit outputs are combined into a 32-bit value, and permuted
once again to produce the f-function output.
Return to my home page
Go to the EKU CS Department page
================================================
FILE: JavaScript/js/sm4.js
================================================
/*! sm4-1.0.js (c) Windard Yang | https://www.windard.com/
*/
/*
* sm4-1.0.js
*
* Copyright (c) 2014 Windard Yang (www.windard.com)
*/
/**
* @fileOverview
* @name sm4-1.0.js
* @author Windard (www.windard.com)
* @version 1.0.0 (2016-11-17)
*/
/* this is sm4 in javascript by windard , today is 2016 11-17 ,
*I'm afraid that can I finished this project , but after all
*in December, everything will be done , that's prefect
*/
/*
* garbage , rubbish programe language, should havn't big decimal number
* can't circular bitwise left shift, can do xor well
*/
/*
* fuck it at all , finally finished it , and there has many other works need to do
*
*/
var SboxTable = new Array();
SboxTable[ 0] = new Array(0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05);
SboxTable[ 1] = new Array(0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99);
SboxTable[ 2] = new Array(0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62);
SboxTable[ 3] = new Array(0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6);
SboxTable[ 4] = new Array(0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8);
SboxTable[ 5] = new Array(0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35);
SboxTable[ 6] = new Array(0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87);
SboxTable[ 7] = new Array(0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e);
SboxTable[ 8] = new Array(0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1);
SboxTable[ 9] = new Array(0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3);
SboxTable[10] = new Array(0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f);
SboxTable[11] = new Array(0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51);
SboxTable[12] = new Array(0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8);
SboxTable[13] = new Array(0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0);
SboxTable[14] = new Array(0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84);
SboxTable[15] = new Array(0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48);
var CK = new Array(
0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
0x10171e25,0x2c333a41,0x484f565d,0x646b7279
);
var FK = new Array(0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc);
// function bigxor(a, b) {
// if (a.toString(2).length < 33 && b.toString(2).length < 33){
// return a ^ b
// }
// var abin = a.toString(2);
// var bbin = b.toString(2);
// var loggest = abin.length >= bbin.length ? abin.length : bbin.length;
// abin = abin.length == loggest ? abin :"0".repeat(loggest - abin.length) + abin;
// bbin = bbin.length == loggest ? bbin :"0".repeat(loggest - bbin.length) + bbin;
// var result = "";
// for (var i = loggest - 1; i >= 0; i--) {
// result = abin[i] == bbin[i] ? '0'+result : '1'+result;
// };
// return parseInt(result, 2);
// }
function bigxor(a, b){
return a ^ b
}
// function leftshift(a, n, size=32) {
// var result = new Array(size);
// result.fill(0);
// var bin = a.toString(2);
// bin = bin.length == size ? bin :"0".repeat(size - bin.length) + bin;
// for (var i = bin.length - 1; i >= 0; i--) {
// result[(i - n + size)%size] = bin[i];
// };
// result = result.join("");
// return parseInt(result, 2);
// }
function leftshift(a, n, size=32) {
n = n % size
return (a << n) | (a >>> (size - n))
}
function prefixInteger(str, length) {
return Array(length+1).join("0").split("").concat(String(str).split(""))
.slice(-length).join("");
}
// function sm4Sbox(a) {
// var a1 = prefixInteger(a.toString(16),8).slice(0,2);
// var a2 = prefixInteger(a.toString(16),8).slice(2,4);
// var a3 = prefixInteger(a.toString(16),8).slice(4,6);
// var a4 = prefixInteger(a.toString(16),8).slice(6,8);
// var b1 = SboxTable[parseInt(a1[0], 16)][parseInt(a1[1], 16)];
// var b2 = SboxTable[parseInt(a2[0], 16)][parseInt(a2[1], 16)];
// var b3 = SboxTable[parseInt(a3[0], 16)][parseInt(a3[1], 16)];
// var b4 = SboxTable[parseInt(a4[0], 16)][parseInt(a4[1], 16)];
// return parseInt(prefixInteger(b1.toString(16), 2) + prefixInteger(b2.toString(16), 2) + prefixInteger(b3.toString(16), 2) + prefixInteger(b4.toString(16), 2) , 16)
// }
function sm4Sbox(a) {
var b1 = SboxTable[(a & 0xf0000000) >>> 28][(a & 0x0f000000) >>> 24]
var b2 = SboxTable[(a & 0x00f00000) >>> 20][(a & 0x000f0000) >>> 16]
var b3 = SboxTable[(a & 0x0000f000) >>> 12][(a & 0x00000f00) >>> 8]
var b4 = SboxTable[(a & 0x000000f0) >>> 4][(a & 0x0000000f) >>> 0]
return (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0)
}
function GET_ULONG_BE (a) {
a = sm4Sbox(a)
return bigxor(bigxor(bigxor(a, leftshift(a, 2)), bigxor(leftshift(a, 10), leftshift(a, 18))), leftshift(a, 24))
}
function PUT_ULONG_BE(b) {
b = sm4Sbox(b)
return bigxor(b, bigxor(leftshift(b, 13), leftshift(b, 23)));
}
function sm4_getkey (MK) {
var K = new Array();
var rk = new Array();
K[0] = bigxor(MK[0], FK[0]);
K[1] = bigxor(MK[1], FK[1]);
K[2] = bigxor(MK[2], FK[2]);
K[3] = bigxor(MK[3], FK[3]);
for (var i = 0; i < 32; i++) {
K[i+4] = bigxor(K[i], PUT_ULONG_BE(bigxor(bigxor(K[i+1], K[i+2]), bigxor(K[i+3], CK[i]))));
rk[i] = K[i+4].toString(16);
};
return rk;
}
function KJUR_encrypt_sm4 (messsage, key, method="cbc") {
var MK = key;
var X = messsage;
var rk = sm4_getkey(MK);
for (var i = 0; i < 32; i++) {
X[i+4] = bigxor(X[i], GET_ULONG_BE(bigxor(bigxor(X[i+1], X[i+2]), bigxor(X[i+3], parseInt(rk[i], 16)))))
};
var Y = new Array(X[35].toString(16), X[34].toString(16), X[33].toString(16), X[32].toString(16))
return Y;
}
function KJUR_decrypt_sm4 (ciphertext, key, method="cbc") {
var MK = key;
var X = ciphertext;
var frk = sm4_getkey(MK);
var rk = new Array()
for (var i = frk.length - 1; i >= 0; i--) {
rk[frk.length - 1 - i] = frk[i]
};
for (var i = 0; i < 32; i++) {
X[i+4] = bigxor(X[i], GET_ULONG_BE(bigxor(bigxor(X[i+1], X[i+2]), bigxor(X[i+3], parseInt(rk[i], 16)))))
};
var Y = new Array(X[35].toString(16), X[34].toString(16), X[33].toString(16), X[32].toString(16))
return Y;
}
================================================
FILE: JavaScript/sm2/js/asn1-1.0.js
================================================
/*! asn1-1.0.4.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* asn1.js - ASN.1 DER encoder classes
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name asn1-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version asn1 1.0.4 (2013-Oct-02)
* @since jsrsasign 2.1
* @license MIT License
*/
/**
* kjur's class library name space
*
* This name space provides following name spaces:
*
{@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}
*
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}
*
*
* 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
* @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) {
var ns1 = KJUR.asn1;
var dataWA = CryptoJS.enc.Hex.parse(dataHex);
var dataB64 = CryptoJS.enc.Base64.stringify(dataWA);
var pemBody = dataB64.replace(/(.{64})/g, "$1\r\n");
pemBody = pemBody.replace(/\r\n$/, '');
return "-----BEGIN " + pemHeader + "-----\r\n" +
pemBody +
"\r\n-----END " + pemHeader + "-----\r\n";
};
/**
* 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
*
'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 ns1 = KJUR.asn1;
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:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + key + ":") == -1)
throw "undefined key: " + key;
if (key == "bool") return new ns1.DERBoolean(param[key]);
if (key == "int") return new ns1.DERInteger(param[key]);
if (key == "bitstr") return new ns1.DERBitString(param[key]);
if (key == "octstr") return new ns1.DEROctetString(param[key]);
if (key == "null") return new ns1.DERNull(param[key]);
if (key == "oid") return new ns1.DERObjectIdentifier(param[key]);
if (key == "utf8str") return new ns1.DERUTF8String(param[key]);
if (key == "numstr") return new ns1.DERNumericString(param[key]);
if (key == "prnstr") return new ns1.DERPrintableString(param[key]);
if (key == "telstr") return new ns1.DERTeletexString(param[key]);
if (key == "ia5str") return new ns1.DERIA5String(param[key]);
if (key == "utctime") return new ns1.DERUTCTime(param[key]);
if (key == "gentime") return new ns1.DERGeneralizedTime(param[key]);
if (key == "seq") {
var paramList = param[key];
var a = [];
for (var i = 0; i < paramList.length; i++) {
var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
a.push(asn1Obj);
}
return new ns1.DERSequence({'array': a});
}
if (key == "set") {
var paramList = param[key];
var a = [];
for (var i = 0; i < paramList.length; i++) {
var asn1Obj = ns1.ASN1Util.newObject(paramList[i]);
a.push(asn1Obj);
}
return new ns1.DERSet({'array': a});
}
if (key == "tag") {
var tagParam = param[key];
if (Object.prototype.toString.call(tagParam) === '[object Array]' &&
tagParam.length == 3) {
var obj = ns1.ASN1Util.newObject(tagParam[2]);
return new ns1.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 = ns1.ASN1Util.newObject(tagParam.obj);
return new ns1.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();
};
};
// ********************************************************************
// 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
*/
this.setString = function(newS) {
this.hTLV = null;
this.isModified = true;
this.s = newS;
this.hV = stohex(this.s);
};
/**
* 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;
};
this.formatDate = function(dateObject, type) {
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);
return year + month + day + hour + min + sec + '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
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERBitString = function(params) {
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.
*/
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.
*/
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 false with specified length
* @name newFalseArray
* @memberOf KJUR.asn1.DERBitString
* @function
* @param {Integer} nLength length of array to generate
* @return {array} array of boolean faluse
* @description
* This static method may be useful to initialize boolean array.
*/
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
* @see KJUR.asn1.DERAbstractString - superclass
*/
KJUR.asn1.DEROctetString = function(params) {
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)
*/
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.
*/
this.setValueName = function(oidName) {
if (typeof KJUR.asn1.x509.OID.name2oidList[oidName] != "undefined") {
var oid = KJUR.asn1.x509.OID.name2oidList[oidName];
this.setValueOidString(oid);
} else {
throw "DERObjectIdentifier oidName undefined: " + oidName;
}
};
this.getFreshValueHex = function() {
return this.hV;
};
if (typeof params != "undefined") {
if (typeof params == "string" && params.match(/^[0-2].[0-9.]+$/)) {
this.setValueOidString(params);
} else if (KJUR.asn1.x509.OID.name2oidList[params] !== undefined) {
this.setValueOidString(KJUR.asn1.x509.OID.name2oidList[params]);
} else if (typeof params['oid'] != "undefined") {
this.setValueOidString(params['oid']);
} else if (typeof params['hex'] != "undefined") {
this.setValueHex(params['hex']);
} else if (typeof params['name'] != "undefined") {
this.setValueName(params['name']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.DERObjectIdentifier, 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
* var d1 = new KJUR.asn1.DERUTCTime();
* d1.setString('130430125959Z');
*
* var d2 = new KJUR.asn1.DERUTCTime({'str': '130430125959Z'});
* var d3 = new KJUR.asn1.DERUTCTime({'date': new Date(Date.UTC(2015, 0, 31, 0, 0, 0, 0))});
* var 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)
*/
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);
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setString(params['str']);
} else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
this.setString(params);
} else if (typeof params['hex'] != "undefined") {
this.setStringHex(params['hex']);
} else if (typeof 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'})
* @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.
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERGeneralizedTime = function(params) {
KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
this.hT = "18";
/**
* 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:
* var o = new DERUTCTime();
* var date = new Date(Date.UTC(2015, 0, 31, 23, 59, 59, 0)); #2015JAN31 23:59:59
* o.setByDate(date);
*/
this.setByDate = function(dateObject) {
this.hTLV = null;
this.isModified = true;
this.date = dateObject;
this.s = this.formatDate(this.date, 'gen');
this.hV = stohex(this.s);
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setString(params['str']);
} else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
this.setString(params);
} else if (typeof params['hex'] != "undefined") {
this.setStringHex(params['hex']);
} else if (typeof params['date'] != "undefined") {
this.setByDate(params['date']);
}
}
};
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
*
* NOTE: 'params' can be omitted.
*/
KJUR.asn1.DERSet = function(params) {
KJUR.asn1.DERSet.superclass.constructor.call(this, params);
this.hT = "31";
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());
}
a.sort();
this.hV = a.join('');
return this.hV;
};
};
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);
================================================
FILE: JavaScript/sm2/js/asn1hex-1.1.js
================================================
/*! asn1hex-1.1.4.js (c) 2012-2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* asn1hex.js - Hexadecimal represented ASN.1 string library
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/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.1.4 (2013-Oct-02)
* @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
*/
var ASN1HEX = new function() {
/**
* get byte length for ASN.1 L(length) bytes
* @name getByteLengthOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return byte length for ASN.1 L(length) bytes
*/
this.getByteLengthOfL_AtObj = function(s, pos) {
if (s.substring(pos + 2, pos + 3) != '8') return 1;
var i = parseInt(s.substring(pos + 3, pos + 4));
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 getHexOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string for ASN.1 L(length) bytes
*/
this.getHexOfL_AtObj = function(s, pos) {
var len = this.getByteLengthOfL_AtObj(s, pos);
if (len < 1) return '';
return s.substring(pos + 2, pos + 2 + len * 2);
};
// 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
/**
* get integer value of ASN.1 length for ASN.1 data
* @name getIntOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return ASN.1 L(length) integer value
*/
this.getIntOfL_AtObj = function(s, pos) {
var hLength = this.getHexOfL_AtObj(s, pos);
if (hLength == '') return -1;
var bi;
if (parseInt(hLength.substring(0, 1)) < 8) {
bi = new BigInteger(hLength, 16);
} else {
bi = new BigInteger(hLength.substring(2), 16);
}
return bi.intValue();
};
/**
* get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
* @name getStartPosOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
*/
this.getStartPosOfV_AtObj = function(s, pos) {
var l_len = this.getByteLengthOfL_AtObj(s, pos);
if (l_len < 0) return l_len;
return pos + (l_len + 1) * 2;
};
/**
* get hexadecimal string of ASN.1 V(value)
* @name getHexOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 value.
*/
this.getHexOfV_AtObj = function(s, pos) {
var pos1 = this.getStartPosOfV_AtObj(s, pos);
var len = this.getIntOfL_AtObj(s, pos);
return s.substring(pos1, pos1 + len * 2);
};
/**
* get hexadecimal string of ASN.1 TLV at
* @name getHexOfTLV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 TLV.
* @since 1.1
*/
this.getHexOfTLV_AtObj = function(s, pos) {
var hT = s.substr(pos, 2);
var hL = this.getHexOfL_AtObj(s, pos);
var hV = this.getHexOfV_AtObj(s, pos);
return hT + hL + hV;
};
/**
* get next sibling starting index for ASN.1 object string
* @name getPosOfNextSibling_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return next sibling starting index for ASN.1 object string
*/
this.getPosOfNextSibling_AtObj = function(s, pos) {
var pos1 = this.getStartPosOfV_AtObj(s, pos);
var len = this.getIntOfL_AtObj(s, pos);
return pos1 + len * 2;
};
/**
* get array of indexes of child ASN.1 objects
* @name getPosArrayOfChildren_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} start string index of ASN.1 object
* @return {Array of Number} array of indexes for childen of ASN.1 objects
*/
this.getPosArrayOfChildren_AtObj = function(h, pos) {
var a = new Array();
var p0 = this.getStartPosOfV_AtObj(h, pos);
a.push(p0);
var len = this.getIntOfL_AtObj(h, pos);
var p = p0;
var k = 0;
while (1) {
var pNext = this.getPosOfNextSibling_AtObj(h, p);
if (pNext == null || (pNext - p0 >= (len * 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 getNthChildIndex_AtObj
* @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 1.1
*/
this.getNthChildIndex_AtObj = function(h, idx, nth) {
var a = this.getPosArrayOfChildren_AtObj(h, idx);
return a[nth];
};
// ========== decendant methods ==============================
/**
* get string index of nth child object of ASN.1 object refered by h, idx
* @name getDecendantIndexByNthList
* @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
* @return {Number} string index refered by nthList
* @since 1.1
* @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 - [0]
* SEQUENCE - [0, 0]
* IA5STRING 000 - [0, 0, 0]
* UTF8STRING 001 - [0, 0, 1]
* SET - [0, 1]
* IA5STRING 010 - [0, 1, 0]
* UTF8STRING 011 - [0, 1, 1]
*/
this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
if (nthList.length == 0) {
return currentIndex;
}
var firstNth = nthList.shift();
var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
};
/**
* get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
* @name getDecendantHexTLVByNthList
* @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
* @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
* @since 1.1
*/
this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
return this.getHexOfTLV_AtObj(h, idx);
};
/**
* get hexadecimal string of ASN.1 V refered by current index and nth index list.
* @name getDecendantHexVByNthList
* @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
* @return {Number} hexadecimal string of ASN.1 V refered by nthList
* @since 1.1
*/
this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
return this.getHexOfV_AtObj(h, idx);
};
};
/*
* @since asn1hex 1.1.4
*/
ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
var idx = this.getDecendantIndexByNthList(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 this.getHexOfV_AtObj(h, idx);
};
================================================
FILE: JavaScript/sm2/js/asn1x509-1.0.js
================================================
/*! asn1x509-1.0.7.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* asn1x509.js - ASN.1 DER encoder classes for X.509 certificate
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name asn1x509-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.0.7 (2013-Oct-11)
* @since jsrsasign 2.1
* @license MIT License
*/
/**
* kjur's class library name space
* // already documented in asn1-1.0.js
* @name KJUR
* @namespace kjur's class library name space
*/
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
/**
* kjur's ASN.1 class library name space
* // already documented in asn1-1.0.js
* @name KJUR.asn1
* @namespace
*/
if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {};
/**
* kjur's ASN.1 class for X.509 certificate library name space
*
*
FEATURES
*
*
easily issue any kind of certificate
*
APIs are very similar to BouncyCastle library ASN.1 classes. So easy to learn.
*
*
*
PROVIDED CLASSES
*
*
{@link KJUR.asn1.x509.Certificate}
*
{@link KJUR.asn1.x509.TBSCertificate}
*
{@link KJUR.asn1.x509.Extension}
*
{@link KJUR.asn1.x509.X500Name}
*
{@link KJUR.asn1.x509.RDN}
*
{@link KJUR.asn1.x509.AttributeTypeAndValue}
*
{@link KJUR.asn1.x509.SubjectPublicKeyInfo}
*
{@link KJUR.asn1.x509.AlgorithmIdentifier}
*
{@link KJUR.asn1.x509.GeneralName}
*
{@link KJUR.asn1.x509.GeneralNames}
*
{@link KJUR.asn1.x509.DistributionPointName}
*
{@link KJUR.asn1.x509.DistributionPoint}
*
{@link KJUR.asn1.x509.CRL}
*
{@link KJUR.asn1.x509.TBSCertList}
*
{@link KJUR.asn1.x509.CRLEntry}
*
{@link KJUR.asn1.x509.OID}
*
*
SUPPORTED EXTENSIONS
*
*
{@link KJUR.asn1.x509.BasicConstraints}
*
{@link KJUR.asn1.x509.KeyUsage}
*
{@link KJUR.asn1.x509.CRLDistributionPoints}
*
{@link KJUR.asn1.x509.ExtKeyUsage}
*
* NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
* @name KJUR.asn1.x509
* @namespace
*/
if (typeof KJUR.asn1.x509 == "undefined" || !KJUR.asn1.x509) KJUR.asn1.x509 = {};
// === BEGIN Certificate ===================================================
/**
* X.509 Certificate class to sign and generate hex encoded certificate
* @name KJUR.asn1.x509.Certificate
* @class X.509 Certificate class to sign and generate hex encoded certificate
* @param {Array} params associative array of parameters (ex. {'tbscertobj': obj, 'prvkeyobj': key})
* @extends KJUR.asn1.ASN1Object
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
prvkeyobj - specify {@link RSAKey}, {@link KJUR.crypto.ECDSA} or {@link KJUR.crypto.DSA} object for CA private key to sign the certificate
*
(DEPRECATED)rsaprvkey - specify {@link RSAKey} object CA private key
*
(DEPRECATED)rsaprvpem - specify PEM string of RSA CA private key
*
* NOTE1: 'params' can be omitted.
* NOTE2: DSA/ECDSA is also supported for CA signging key from asn1x509 1.0.6.
* @example
* var caKey = KEYUTIL.getKey(caKeyPEM); // CA's private key
* var cert = new KJUR.asn1x509.Certificate({'tbscertobj': tbs, 'prvkeyobj': caKey});
* cert.sign(); // issue certificate by CA's private key
* var certPEM = cert.getPEMString();
*
* // Certificate ::= SEQUENCE {
* // tbsCertificate TBSCertificate,
* // signatureAlgorithm AlgorithmIdentifier,
* // signature BIT STRING }
*/
KJUR.asn1.x509.Certificate = function(params) {
KJUR.asn1.x509.Certificate.superclass.constructor.call(this);
var asn1TBSCert = null;
var asn1SignatureAlg = null;
var asn1Sig = null;
var hexSig = null;
var prvKey = null;
var rsaPrvKey = null; // DEPRECATED
/**
* set PKCS#5 encrypted RSA PEM private key as CA key
* @name setRsaPrvKeyByPEMandPass
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @param {String} rsaPEM string of PKCS#5 encrypted RSA PEM private key
* @param {String} passPEM passcode string to decrypt private key
* @since 1.0.1
* @description
*
*
EXAMPLES
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs});
* cert.setRsaPrvKeyByPEMandPass("-----BEGIN RSA PRIVATE..(snip)", "password");
*/
this.setRsaPrvKeyByPEMandPass = function(rsaPEM, passPEM) {
var caKeyHex = PKCS5PKEY.getDecryptedKeyHex(rsaPEM, passPEM);
var caKey = new RSAKey();
caKey.readPrivateKeyFromASN1HexString(caKeyHex);
this.prvKey = caKey;
};
/**
* sign TBSCertificate and set signature value internally
* @name sign
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @description
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
*/
this.sign = function() {
this.asn1SignatureAlg = this.asn1TBSCert.asn1SignatureAlg;
sig = new KJUR.crypto.Signature({'alg': 'SHA1withRSA'});
sig.init(this.prvKey);
sig.updateHex(this.asn1TBSCert.getEncodedHex());
this.hexSig = sig.sign();
this.asn1Sig = new KJUR.asn1.DERBitString({'hex': '00' + this.hexSig});
var seq = new KJUR.asn1.DERSequence({'array': [this.asn1TBSCert,
this.asn1SignatureAlg,
this.asn1Sig]});
this.hTLV = seq.getEncodedHex();
this.isModified = false;
};
this.getEncodedHex = function() {
if (this.isModified == false && this.hTLV != null) return this.hTLV;
throw "not signed yet";
};
/**
* get PEM formatted certificate string after signed
* @name getPEMString
* @memberOf KJUR.asn1.x509.Certificate
* @function
* @return PEM formatted string of certificate
* @description
* @example
* var cert = new KJUR.asn1.x509.Certificate({'tbscertobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
* var sPEM = cert.getPEMString();
*/
this.getPEMString = function() {
var hCert = this.getEncodedHex();
var wCert = CryptoJS.enc.Hex.parse(hCert);
var b64Cert = CryptoJS.enc.Base64.stringify(wCert);
var pemBody = b64Cert.replace(/(.{64})/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n" + pemBody + "\r\n-----END CERTIFICATE-----\r\n";
};
if (typeof params != "undefined") {
if (typeof params['tbscertobj'] != "undefined") {
this.asn1TBSCert = params['tbscertobj'];
}
if (typeof params['prvkeyobj'] != "undefined") {
this.prvKey = params['prvkeyobj'];
} else if (typeof params['rsaprvkey'] != "undefined") {
this.prvKey = params['rsaprvkey'];
} else if ((typeof params['rsaprvpem'] != "undefined") &&
(typeof params['rsaprvpas'] != "undefined")) {
this.setRsaPrvKeyByPEMandPass(params['rsaprvpem'], params['rsaprvpas']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Certificate, KJUR.asn1.ASN1Object);
/**
* ASN.1 TBSCertificate structure class
* @name KJUR.asn1.x509.TBSCertificate
* @class ASN.1 TBSCertificate structure class
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @description
*
*
EXAMPLE
* @example
* var o = new KJUR.asn1.x509.TBSCertificate();
* o.setSerialNumberByParam({'int': 4});
* o.setSignatureAlgByParam({'name': 'SHA1withRSA'});
* o.setIssuerByParam({'str': '/C=US/O=a'});
* o.setNotBeforeByParam({'str': '130504235959Z'});
* o.setNotAfterByParam({'str': '140504235959Z'});
* o.setSubjectByParam({'str': '/C=US/CN=b'});
* o.setSubjectPublicKeyByParam({'rsakey': rsaKey});
* o.appendExtension(new KJUR.asn1.x509.BasicConstraints({'cA':true}));
* o.appendExtension(new KJUR.asn1.x509.KeyUsage({'bin':'11'}));
*/
KJUR.asn1.x509.TBSCertificate = function(params) {
KJUR.asn1.x509.TBSCertificate.superclass.constructor.call(this);
this._initialize = function() {
this.asn1Array = new Array();
this.asn1Version =
new KJUR.asn1.DERTaggedObject({'obj': new KJUR.asn1.DERInteger({'int': 2})});
this.asn1SerialNumber = null;
this.asn1SignatureAlg = null;
this.asn1Issuer = null;
this.asn1NotBefore = null;
this.asn1NotAfter = null;
this.asn1Subject = null;
this.asn1SubjPKey = null;
this.extensionsArray = new Array();
};
/**
* set serial number field by parameter
* @name setSerialNumberByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} intParam DERInteger param
* @description
* @example
* tbsc.setSerialNumberByParam({'int': 3});
*/
this.setSerialNumberByParam = function(intParam) {
this.asn1SerialNumber = new KJUR.asn1.DERInteger(intParam);
};
/**
* set signature algorithm field by parameter
* @name setSignatureAlgByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} algIdParam AlgorithmIdentifier parameter
* @description
* @example
* tbsc.setSignatureAlgByParam({'name': 'SHA1withRSA'});
*/
this.setSignatureAlgByParam = function(algIdParam) {
this.asn1SignatureAlg = new KJUR.asn1.x509.AlgorithmIdentifier(algIdParam);
};
/**
* set issuer name field by parameter
* @name setIssuerByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setIssuerParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setIssuerByParam = function(x500NameParam) {
this.asn1Issuer = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* set notBefore field by parameter
* @name setNotBeforeByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNotBeforeByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNotBeforeByParam = function(timeParam) {
this.asn1NotBefore = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set notAfter field by parameter
* @name setNotAfterByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNotAfterByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNotAfterByParam = function(timeParam) {
this.asn1NotAfter = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set subject name field by parameter
* @name setSubjectByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setSubjectParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setSubjectByParam = function(x500NameParam) {
this.asn1Subject = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* (DEPRECATED) set subject public key info field by RSA key parameter
* @name setSubjectPublicKeyByParam
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Array} subjPKeyParam SubjectPublicKeyInfo parameter of RSA
* @deprecated
* @description
* @example
* tbsc.setSubjectPublicKeyByParam({'rsakey': pubKey});
* @see KJUR.asn1.x509.SubjectPublicKeyInfo
*/
this.setSubjectPublicKeyByParam = function(subjPKeyParam) {
this.asn1SubjPKey = new KJUR.asn1.x509.SubjectPublicKeyInfo(subjPKeyParam);
};
/**
* set subject public key info by RSA/ECDSA/DSA key parameter
* @name setSubjectPublicKeyByGetKey
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Object} keyParam public key parameter which passed to {@link KEYUTIL.getKey} argument
* @description
* @example
* tbsc.setSubjectPublicKeyByGetKeyParam(certPEMString); // or
* tbsc.setSubjectPublicKeyByGetKeyParam(pkcs8PublicKeyPEMString); // or
* tbsc.setSubjectPublicKeyByGetKeyParam(kjurCryptoECDSAKeyObject); // et.al.
* @see KJUR.asn1.x509.SubjectPublicKeyInfo
* @see KEYUTIL.getKey
* @since asn1x509 1.0.6
*/
this.setSubjectPublicKeyByGetKey = function(keyParam) {
var keyObj = KEYUTIL.getKey(keyParam);
this.asn1SubjPKey = new KJUR.asn1.x509.SubjectPublicKeyInfo(keyObj);
};
/**
* append X.509v3 extension to this object
* @name appendExtension
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {Extension} extObj X.509v3 Extension object
* @description
* @example
* tbsc.appendExtension(new KJUR.asn1.x509.BasicConstraints({'cA':true, 'critical': true}));
* tbsc.appendExtension(new KJUR.asn1.x509.KeyUsage({'bin':'11'}));
* @see KJUR.asn1.x509.Extension
*/
this.appendExtension = function(extObj) {
this.extensionsArray.push(extObj);
};
/**
* append X.509v3 extension to this object by name and parameters
* @name appendExtensionByName
* @memberOf KJUR.asn1.x509.TBSCertificate
* @function
* @param {name} name name of X.509v3 Extension object
* @param {Array} extParams parameters as argument of Extension constructor.
* @description
* @example
* tbsc.appendExtensionByName('BasicConstraints', {'cA':true, 'critical': true});
* tbsc.appendExtensionByName('KeyUsage', {'bin':'11'});
* tbsc.appendExtensionByName('CRLDistributionPoints', {uri: 'http://aaa.com/a.crl'});
* tbsc.appendExtensionByName('ExtKeyUsage', {array: [{name: 'clientAuth'}]});
* @see KJUR.asn1.x509.Extension
*/
this.appendExtensionByName = function(name, extParams) {
if (name.toLowerCase() == "basicconstraints") {
var extObj = new KJUR.asn1.x509.BasicConstraints(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "keyusage") {
var extObj = new KJUR.asn1.x509.KeyUsage(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "crldistributionpoints") {
var extObj = new KJUR.asn1.x509.CRLDistributionPoints(extParams);
this.appendExtension(extObj);
} else if (name.toLowerCase() == "extkeyusage") {
var extObj = new KJUR.asn1.x509.ExtKeyUsage(extParams);
this.appendExtension(extObj);
} else {
throw "unsupported extension name: " + name;
}
};
this.getEncodedHex = function() {
if (this.asn1NotBefore == null || this.asn1NotAfter == null)
throw "notBefore and/or notAfter not set";
var asn1Validity =
new KJUR.asn1.DERSequence({'array':[this.asn1NotBefore, this.asn1NotAfter]});
this.asn1Array = new Array();
this.asn1Array.push(this.asn1Version);
this.asn1Array.push(this.asn1SerialNumber);
this.asn1Array.push(this.asn1SignatureAlg);
this.asn1Array.push(this.asn1Issuer);
this.asn1Array.push(asn1Validity);
this.asn1Array.push(this.asn1Subject);
this.asn1Array.push(this.asn1SubjPKey);
if (this.extensionsArray.length > 0) {
var extSeq = new KJUR.asn1.DERSequence({"array": this.extensionsArray});
var extTagObj = new KJUR.asn1.DERTaggedObject({'explicit': true,
'tag': 'a3',
'obj': extSeq});
this.asn1Array.push(extTagObj);
}
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.hTLV = o.getEncodedHex();
this.isModified = false;
return this.hTLV;
};
this._initialize();
};
YAHOO.lang.extend(KJUR.asn1.x509.TBSCertificate, KJUR.asn1.ASN1Object);
// === END TBSCertificate ===================================================
// === BEGIN X.509v3 Extensions Related =======================================
/**
* base Extension ASN.1 structure class
* @name KJUR.asn1.x509.Extension
* @class base Extension ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'critical': true})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
* // Extension ::= SEQUENCE {
* // extnID OBJECT IDENTIFIER,
* // critical BOOLEAN DEFAULT FALSE,
* // extnValue OCTET STRING }
*/
KJUR.asn1.x509.Extension = function(params) {
KJUR.asn1.x509.Extension.superclass.constructor.call(this);
var asn1ExtnValue = null;
this.getEncodedHex = function() {
var asn1Oid = new KJUR.asn1.DERObjectIdentifier({'oid': this.oid});
var asn1EncapExtnValue =
new KJUR.asn1.DEROctetString({'hex': this.getExtnValueHex()});
var asn1Array = new Array();
asn1Array.push(asn1Oid);
if (this.critical) asn1Array.push(new KJUR.asn1.DERBoolean());
asn1Array.push(asn1EncapExtnValue);
var asn1Seq = new KJUR.asn1.DERSequence({'array': asn1Array});
return asn1Seq.getEncodedHex();
};
this.critical = false;
if (typeof params != "undefined") {
if (typeof params['critical'] != "undefined") {
this.critical = params['critical'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Extension, KJUR.asn1.ASN1Object);
/**
* KeyUsage ASN.1 structure class
* @name KJUR.asn1.x509.KeyUsage
* @class KeyUsage ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'bin': '11', 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.KeyUsage = function(params) {
KJUR.asn1.x509.KeyUsage.superclass.constructor.call(this, params);
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.15";
if (typeof params != "undefined") {
if (typeof params['bin'] != "undefined") {
this.asn1ExtnValue = new KJUR.asn1.DERBitString(params);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.KeyUsage, KJUR.asn1.x509.Extension);
/**
* BasicConstraints ASN.1 structure class
* @name KJUR.asn1.x509.BasicConstraints
* @class BasicConstraints ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'cA': true, 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.BasicConstraints = function(params) {
KJUR.asn1.x509.BasicConstraints.superclass.constructor.call(this, params);
var cA = false;
var pathLen = -1;
this.getExtnValueHex = function() {
var asn1Array = new Array();
if (this.cA) asn1Array.push(new KJUR.asn1.DERBoolean());
if (this.pathLen > -1)
asn1Array.push(new KJUR.asn1.DERInteger({'int': this.pathLen}));
var asn1Seq = new KJUR.asn1.DERSequence({'array': asn1Array});
this.asn1ExtnValue = asn1Seq;
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.19";
this.cA = false;
this.pathLen = -1;
if (typeof params != "undefined") {
if (typeof params['cA'] != "undefined") {
this.cA = params['cA'];
}
if (typeof params['pathLen'] != "undefined") {
this.pathLen = params['pathLen'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.BasicConstraints, KJUR.asn1.x509.Extension);
/**
* CRLDistributionPoints ASN.1 structure class
* @name KJUR.asn1.x509.CRLDistributionPoints
* @class CRLDistributionPoints ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'uri': 'http://a.com/', 'critical': true})
* @extends KJUR.asn1.x509.Extension
* @description
* @example
*/
KJUR.asn1.x509.CRLDistributionPoints = function(params) {
KJUR.asn1.x509.CRLDistributionPoints.superclass.constructor.call(this, params);
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.setByDPArray = function(dpArray) {
this.asn1ExtnValue = new KJUR.asn1.DERSequence({'array': dpArray});
};
this.setByOneURI = function(uri) {
var gn1 = new KJUR.asn1.x509.GeneralNames([{'uri': uri}]);
var dpn1 = new KJUR.asn1.x509.DistributionPointName(gn1);
var dp1 = new KJUR.asn1.x509.DistributionPoint({'dpobj': dpn1});
this.setByDPArray([dp1]);
};
this.oid = "2.5.29.31";
if (typeof params != "undefined") {
if (typeof params['array'] != "undefined") {
this.setByDPArray(params['array']);
} else if (typeof params['uri'] != "undefined") {
this.setByOneURI(params['uri']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRLDistributionPoints, KJUR.asn1.x509.Extension);
/**
* KeyUsage ASN.1 structure class
* @name KJUR.asn1.x509.ExtKeyUsage
* @class ExtKeyUsage ASN.1 structure class
* @param {Array} params associative array of parameters
* @extends KJUR.asn1.x509.Extension
* @description
* @example
* var e1 =
* new KJUR.asn1.x509.ExtKeyUsage({'critical': true,
* 'array':
* [{'oid': '2.5.29.37.0', // anyExtendedKeyUsage
* 'name': 'clientAuth'}]});
*
* // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
* // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
* // KeyPurposeId ::= OBJECT IDENTIFIER
*/
KJUR.asn1.x509.ExtKeyUsage = function(params) {
KJUR.asn1.x509.ExtKeyUsage.superclass.constructor.call(this, params);
this.setPurposeArray = function(purposeArray) {
this.asn1ExtnValue = new KJUR.asn1.DERSequence();
for (var i = 0; i < purposeArray.length; i++) {
var o = new KJUR.asn1.DERObjectIdentifier(purposeArray[i]);
this.asn1ExtnValue.appendASN1Object(o);
}
};
this.getExtnValueHex = function() {
return this.asn1ExtnValue.getEncodedHex();
};
this.oid = "2.5.29.37";
if (typeof params != "undefined") {
if (typeof params['array'] != "undefined") {
this.setPurposeArray(params['array']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.ExtKeyUsage, KJUR.asn1.x509.Extension);
// === END X.509v3 Extensions Related =======================================
// === BEGIN CRL Related ===================================================
/**
* X.509 CRL class to sign and generate hex encoded CRL
* @name KJUR.asn1.x509.CRL
* @class X.509 CRL class to sign and generate hex encoded certificate
* @param {Array} params associative array of parameters (ex. {'tbsobj': obj, 'rsaprvkey': key})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
tbsobj - specify {@link KJUR.asn1.x509.TBSCertList} object to be signed
*
rsaprvkey - specify {@link RSAKey} object CA private key
*
* NOTE: 'params' can be omitted.
*
EXAMPLE
* @example
* var prvKey = new RSAKey(); // CA's private key
* prvKey.readPrivateKeyFromASN1HexString("3080...");
* var crl = new KJUR.asn1x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* crl.sign(); // issue CRL by CA's private key
* var hCRL = crl.getEncodedHex();
*
* // CertificateList ::= SEQUENCE {
* // tbsCertList TBSCertList,
* // signatureAlgorithm AlgorithmIdentifier,
* // signatureValue BIT STRING }
*/
KJUR.asn1.x509.CRL = function(params) {
KJUR.asn1.x509.CRL.superclass.constructor.call(this);
var asn1TBSCertList = null;
var asn1SignatureAlg = null;
var asn1Sig = null;
var hexSig = null;
var rsaPrvKey = null;
/**
* set PKCS#5 encrypted RSA PEM private key as CA key
* @name setRsaPrvKeyByPEMandPass
* @memberOf KJUR.asn1.x509.CRL
* @function
* @param {String} rsaPEM string of PKCS#5 encrypted RSA PEM private key
* @param {String} passPEM passcode string to decrypt private key
* @description
*
*
EXAMPLES
* @example
*/
this.setRsaPrvKeyByPEMandPass = function(rsaPEM, passPEM) {
var caKeyHex = PKCS5PKEY.getDecryptedKeyHex(rsaPEM, passPEM);
var caKey = new RSAKey();
caKey.readPrivateKeyFromASN1HexString(caKeyHex);
this.rsaPrvKey = caKey;
};
/**
* sign TBSCertList and set signature value internally
* @name sign
* @memberOf KJUR.asn1.x509.CRL
* @function
* @description
* @example
* var cert = new KJUR.asn1.x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
*/
this.sign = function() {
this.asn1SignatureAlg = this.asn1TBSCertList.asn1SignatureAlg;
sig = new KJUR.crypto.Signature({'alg': 'SHA1withRSA', 'prov': 'cryptojs/jsrsa'});
sig.initSign(this.rsaPrvKey);
sig.updateHex(this.asn1TBSCertList.getEncodedHex());
this.hexSig = sig.sign();
this.asn1Sig = new KJUR.asn1.DERBitString({'hex': '00' + this.hexSig});
var seq = new KJUR.asn1.DERSequence({'array': [this.asn1TBSCertList,
this.asn1SignatureAlg,
this.asn1Sig]});
this.hTLV = seq.getEncodedHex();
this.isModified = false;
};
this.getEncodedHex = function() {
if (this.isModified == false && this.hTLV != null) return this.hTLV;
throw "not signed yet";
};
/**
* get PEM formatted CRL string after signed
* @name getPEMString
* @memberOf KJUR.asn1.x509.CRL
* @function
* @return PEM formatted string of certificate
* @description
* @example
* var cert = new KJUR.asn1.x509.CRL({'tbsobj': tbs, 'rsaprvkey': prvKey});
* cert.sign();
* var sPEM = cert.getPEMString();
*/
this.getPEMString = function() {
var hCert = this.getEncodedHex();
var wCert = CryptoJS.enc.Hex.parse(hCert);
var b64Cert = CryptoJS.enc.Base64.stringify(wCert);
var pemBody = b64Cert.replace(/(.{64})/g, "$1\r\n");
return "-----BEGIN X509 CRL-----\r\n" + pemBody + "\r\n-----END X509 CRL-----\r\n";
};
if (typeof params != "undefined") {
if (typeof params['tbsobj'] != "undefined") {
this.asn1TBSCertList = params['tbsobj'];
}
if (typeof params['rsaprvkey'] != "undefined") {
this.rsaPrvKey = params['rsaprvkey'];
}
if ((typeof params['rsaprvpem'] != "undefined") &&
(typeof params['rsaprvpas'] != "undefined")) {
this.setRsaPrvKeyByPEMandPass(params['rsaprvpem'], params['rsaprvpas']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRL, KJUR.asn1.ASN1Object);
/**
* ASN.1 TBSCertList structure class for CRL
* @name KJUR.asn1.x509.TBSCertList
* @class ASN.1 TBSCertList structure class for CRL
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
*
*
EXAMPLE
* @example
* var o = new KJUR.asn1.x509.TBSCertList();
* o.setSignatureAlgByParam({'name': 'SHA1withRSA'});
* o.setIssuerByParam({'str': '/C=US/O=a'});
* o.setNotThisUpdateByParam({'str': '130504235959Z'});
* o.setNotNextUpdateByParam({'str': '140504235959Z'});
* o.addRevokedCert({'int': 4}, {'str':'130514235959Z'}));
* o.addRevokedCert({'hex': '0f34dd'}, {'str':'130514235959Z'}));
*
* // TBSCertList ::= SEQUENCE {
* // version Version OPTIONAL,
* // -- if present, MUST be v2
* // signature AlgorithmIdentifier,
* // issuer Name,
* // thisUpdate Time,
* // nextUpdate Time OPTIONAL,
* // revokedCertificates SEQUENCE OF SEQUENCE {
* // userCertificate CertificateSerialNumber,
* // revocationDate Time,
* // crlEntryExtensions Extensions OPTIONAL
* // -- if present, version MUST be v2
* // } OPTIONAL,
* // crlExtensions [0] EXPLICIT Extensions OPTIONAL
*/
KJUR.asn1.x509.TBSCertList = function(params) {
KJUR.asn1.x509.TBSCertList.superclass.constructor.call(this);
var aRevokedCert = null;
/**
* set signature algorithm field by parameter
* @name setSignatureAlgByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} algIdParam AlgorithmIdentifier parameter
* @description
* @example
* tbsc.setSignatureAlgByParam({'name': 'SHA1withRSA'});
*/
this.setSignatureAlgByParam = function(algIdParam) {
this.asn1SignatureAlg = new KJUR.asn1.x509.AlgorithmIdentifier(algIdParam);
};
/**
* set issuer name field by parameter
* @name setIssuerByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} x500NameParam X500Name parameter
* @description
* @example
* tbsc.setIssuerParam({'str': '/C=US/CN=b'});
* @see KJUR.asn1.x509.X500Name
*/
this.setIssuerByParam = function(x500NameParam) {
this.asn1Issuer = new KJUR.asn1.x509.X500Name(x500NameParam);
};
/**
* set thisUpdate field by parameter
* @name setThisUpdateByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setThisUpdateByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setThisUpdateByParam = function(timeParam) {
this.asn1ThisUpdate = new KJUR.asn1.x509.Time(timeParam);
};
/**
* set nextUpdate field by parameter
* @name setNextUpdateByParam
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} timeParam Time parameter
* @description
* @example
* tbsc.setNextUpdateByParam({'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.setNextUpdateByParam = function(timeParam) {
this.asn1NextUpdate = new KJUR.asn1.x509.Time(timeParam);
};
/**
* add revoked certficate by parameter
* @name addRevokedCert
* @memberOf KJUR.asn1.x509.TBSCertList
* @function
* @param {Array} snParam DERInteger parameter for certificate serial number
* @param {Array} timeParam Time parameter for revocation date
* @description
* @example
* tbsc.addRevokedCert({'int': 3}, {'str': '130508235959Z'});
* @see KJUR.asn1.x509.Time
*/
this.addRevokedCert = function(snParam, timeParam) {
var param = {};
if (snParam != undefined && snParam != null) param['sn'] = snParam;
if (timeParam != undefined && timeParam != null) param['time'] = timeParam;
var o = new KJUR.asn1.x509.CRLEntry(param);
this.aRevokedCert.push(o);
};
this.getEncodedHex = function() {
this.asn1Array = new Array();
if (this.asn1Version != null) this.asn1Array.push(this.asn1Version);
this.asn1Array.push(this.asn1SignatureAlg);
this.asn1Array.push(this.asn1Issuer);
this.asn1Array.push(this.asn1ThisUpdate);
if (this.asn1NextUpdate != null) this.asn1Array.push(this.asn1NextUpdate);
if (this.aRevokedCert.length > 0) {
var seq = new KJUR.asn1.DERSequence({'array': this.aRevokedCert});
this.asn1Array.push(seq);
}
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.hTLV = o.getEncodedHex();
this.isModified = false;
return this.hTLV;
};
this._initialize = function() {
this.asn1Version = null;
this.asn1SignatureAlg = null;
this.asn1Issuer = null;
this.asn1ThisUpdate = null;
this.asn1NextUpdate = null;
this.aRevokedCert = new Array();
};
this._initialize();
};
YAHOO.lang.extend(KJUR.asn1.x509.TBSCertList, KJUR.asn1.ASN1Object);
/**
* ASN.1 CRLEntry structure class for CRL
* @name KJUR.asn1.x509.CRLEntry
* @class ASN.1 CRLEntry structure class for CRL
* @param {Array} params associative array of parameters (ex. {})
* @extends KJUR.asn1.ASN1Object
* @since 1.0.3
* @description
* @example
* var e = new KJUR.asn1.x509.CRLEntry({'time': {'str': '130514235959Z'}, 'sn': {'int': 234}});
*
* // revokedCertificates SEQUENCE OF SEQUENCE {
* // userCertificate CertificateSerialNumber,
* // revocationDate Time,
* // crlEntryExtensions Extensions OPTIONAL
* // -- if present, version MUST be v2 }
*/
KJUR.asn1.x509.CRLEntry = function(params) {
KJUR.asn1.x509.CRLEntry.superclass.constructor.call(this);
var sn = null;
var time = null;
/**
* set DERInteger parameter for serial number of revoked certificate
* @name setCertSerial
* @memberOf KJUR.asn1.x509.CRLEntry
* @function
* @param {Array} intParam DERInteger parameter for certificate serial number
* @description
* @example
* entry.setCertSerial({'int': 3});
*/
this.setCertSerial = function(intParam) {
this.sn = new KJUR.asn1.DERInteger(intParam);
};
/**
* set Time parameter for revocation date
* @name setRevocationDate
* @memberOf KJUR.asn1.x509.CRLEntry
* @function
* @param {Array} timeParam Time parameter for revocation date
* @description
* @example
* entry.setRevocationDate({'str': '130508235959Z'});
*/
this.setRevocationDate = function(timeParam) {
this.time = new KJUR.asn1.x509.Time(timeParam);
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": [this.sn, this.time]});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['time'] != "undefined") {
this.setRevocationDate(params['time']);
}
if (typeof params['sn'] != "undefined") {
this.setCertSerial(params['sn']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.CRLEntry, KJUR.asn1.ASN1Object);
// === END CRL Related ===================================================
// === BEGIN X500Name Related =================================================
/**
* X500Name ASN.1 structure class
* @name KJUR.asn1.x509.X500Name
* @class X500Name ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': '/C=US/O=a'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.X500Name = function(params) {
KJUR.asn1.x509.X500Name.superclass.constructor.call(this);
this.asn1Array = new Array();
this.setByString = function(dnStr) {
var a = dnStr.split('/');
a.shift();
for (var i = 0; i < a.length; i++) {
this.asn1Array.push(new KJUR.asn1.x509.RDN({'str':a[i]}));
}
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": this.asn1Array});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.X500Name, KJUR.asn1.ASN1Object);
/**
* RDN (Relative Distinguish Name) ASN.1 structure class
* @name KJUR.asn1.x509.RDN
* @class RDN (Relative Distinguish Name) ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': 'C=US'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.RDN = function(params) {
KJUR.asn1.x509.RDN.superclass.constructor.call(this);
this.asn1Array = new Array();
this.addByString = function(rdnStr) {
this.asn1Array.push(new KJUR.asn1.x509.AttributeTypeAndValue({'str':rdnStr}));
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSet({"array": this.asn1Array});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.addByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.RDN, KJUR.asn1.ASN1Object);
/**
* AttributeTypeAndValue ASN.1 structure class
* @name KJUR.asn1.x509.AttributeTypeAndValue
* @class AttributeTypeAndValue ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': 'C=US'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.AttributeTypeAndValue = function(params) {
KJUR.asn1.x509.AttributeTypeAndValue.superclass.constructor.call(this);
var typeObj = null;
var valueObj = null;
var defaultDSType = "utf8";
this.setByString = function(attrTypeAndValueStr) {
if (attrTypeAndValueStr.match(/^([^=]+)=(.+)$/)) {
this.setByAttrTypeAndValueStr(RegExp.$1, RegExp.$2);
} else {
throw "malformed attrTypeAndValueStr: " + attrTypeAndValueStr;
}
};
this.setByAttrTypeAndValueStr = function(shortAttrType, valueStr) {
this.typeObj = KJUR.asn1.x509.OID.atype2obj(shortAttrType);
var dsType = defaultDSType;
if (shortAttrType == "C") dsType = "prn";
this.valueObj = this.getValueObj(dsType, valueStr);
};
this.getValueObj = function(dsType, valueStr) {
if (dsType == "utf8") return new KJUR.asn1.DERUTF8String({"str": valueStr});
if (dsType == "prn") return new KJUR.asn1.DERPrintableString({"str": valueStr});
if (dsType == "tel") return new KJUR.asn1.DERTeletexString({"str": valueStr});
if (dsType == "ia5") return new KJUR.asn1.DERIA5String({"str": valueStr});
throw "unsupported directory string type: type=" + dsType + " value=" + valueStr;
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({"array": [this.typeObj, this.valueObj]});
this.TLV = o.getEncodedHex();
return this.TLV;
};
if (typeof params != "undefined") {
if (typeof params['str'] != "undefined") {
this.setByString(params['str']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.AttributeTypeAndValue, KJUR.asn1.ASN1Object);
// === END X500Name Related =================================================
// === BEGIN Other ASN1 structure class ======================================
/**
* SubjectPublicKeyInfo ASN.1 structure class
* @name KJUR.asn1.x509.SubjectPublicKeyInfo
* @class SubjectPublicKeyInfo ASN.1 structure class
* @param {Object} params parameter for subject public key
* @extends KJUR.asn1.ASN1Object
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
{@link RSAKey} object
*
{@link KJUR.crypto.ECDSA} object
*
{@link KJUR.crypto.DSA} object
*
(DEPRECATED)rsakey - specify {@link RSAKey} object of subject public key
*
(DEPRECATED)rsapem - specify a string of PEM public key of RSA key
*
* NOTE1: 'params' can be omitted.
* NOTE2: DSA/ECDSA key object is also supported since asn1x509 1.0.6.
*
EXAMPLE
* @example
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(RSAKey_object);
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(KJURcryptoECDSA_object);
* var spki = new KJUR.asn1.x509.SubjectPublicKeyInfo(KJURcryptoDSA_object);
*/
KJUR.asn1.x509.SubjectPublicKeyInfo = function(params) {
KJUR.asn1.x509.SubjectPublicKeyInfo.superclass.constructor.call(this);
var asn1AlgId = null;
var asn1SubjPKey = null;
var rsaKey = null;
/**
* (DEPRECATED) set RSAKey object as subject public key
* @name setRSAKey
* @memberOf KJUR.asn1.x509.SubjectPublicKeyInfo
* @function
* @param {RSAKey} rsaKey {@link RSAKey} object for RSA public key
* @description
* @deprecated
* @example
* spki.setRSAKey(rsaKey);
*/
this.setRSAKey = function(rsaKey) {
if (! RSAKey.prototype.isPrototypeOf(rsaKey))
throw "argument is not RSAKey instance";
this.rsaKey = rsaKey;
var asn1RsaN = new KJUR.asn1.DERInteger({'bigint': rsaKey.n});
var asn1RsaE = new KJUR.asn1.DERInteger({'int': rsaKey.e});
var asn1RsaPub = new KJUR.asn1.DERSequence({'array': [asn1RsaN, asn1RsaE]});
var rsaKeyHex = asn1RsaPub.getEncodedHex();
this.asn1AlgId = new KJUR.asn1.x509.AlgorithmIdentifier({'name':'rsaEncryption'});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex':'00'+rsaKeyHex});
};
/**
* (DEPRECATED) set a PEM formatted RSA public key string as RSA public key
* @name setRSAPEM
* @memberOf KJUR.asn1.x509.SubjectPublicKeyInfo
* @function
* @param {String} rsaPubPEM PEM formatted RSA public key string
* @deprecated
* @description
* @example
* spki.setRSAPEM(rsaPubPEM);
*/
this.setRSAPEM = function(rsaPubPEM) {
if (rsaPubPEM.match(/-----BEGIN PUBLIC KEY-----/)) {
var s = rsaPubPEM;
s = s.replace(/^-----[^-]+-----/, '');
s = s.replace(/-----[^-]+-----\s*$/, '');
var rsaB64 = s.replace(/\s+/g, '');
var rsaWA = CryptoJS.enc.Base64.parse(rsaB64);
var rsaP8Hex = CryptoJS.enc.Hex.stringify(rsaWA);
var a = _rsapem_getHexValueArrayOfChildrenFromHex(rsaP8Hex);
var hBitStrVal = a[1];
var rsaHex = hBitStrVal.substr(2);
var a3 = _rsapem_getHexValueArrayOfChildrenFromHex(rsaHex);
var rsaKey = new RSAKey();
rsaKey.setPublic(a3[0], a3[1]);
this.setRSAKey(rsaKey);
} else {
throw "key not supported";
}
};
/*
* @since asn1x509 1.0.7
*/
this.getASN1Object = function() {
if (this.asn1AlgId == null || this.asn1SubjPKey == null)
throw "algId and/or subjPubKey not set";
var o = new KJUR.asn1.DERSequence({'array':
[this.asn1AlgId, this.asn1SubjPKey]});
return o;
};
this.getEncodedHex = function() {
var o = this.getASN1Object();
this.hTLV = o.getEncodedHex();
return this.hTLV;
};
this._setRSAKey = function(key) {
var asn1RsaPub = KJUR.asn1.ASN1Util.newObject({
'seq': [{'int': {'bigint': key.n}}, {'int': {'int': key.e}}]
});
var rsaKeyHex = asn1RsaPub.getEncodedHex();
this.asn1AlgId = new KJUR.asn1.x509.AlgorithmIdentifier({'name':'rsaEncryption'});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex':'00'+rsaKeyHex});
};
this._setEC = function(key) {
var asn1Params = new KJUR.asn1.DERObjectIdentifier({'name': key.curveName});
this.asn1AlgId =
new KJUR.asn1.x509.AlgorithmIdentifier({'name': 'ecPublicKey',
'asn1params': asn1Params});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex': '00' + key.pubKeyHex});
};
this._setDSA = function(key) {
var asn1Params = new KJUR.asn1.ASN1Util.newObject({
'seq': [{'int': {'bigint': key.p}},
{'int': {'bigint': key.q}},
{'int': {'bigint': key.g}}]
});
this.asn1AlgId =
new KJUR.asn1.x509.AlgorithmIdentifier({'name': 'dsa',
'asn1params': asn1Params});
var pubInt = new KJUR.asn1.DERInteger({'bigint': key.y});
this.asn1SubjPKey = new KJUR.asn1.DERBitString({'hex': '00' + pubInt.getEncodedHex()});
};
if (typeof params != "undefined") {
if (typeof RSAKey != 'undefined' && params instanceof RSAKey) {
this._setRSAKey(params);
} else if (typeof KJUR.crypto.ECDSA != 'undefined' &&
params instanceof KJUR.crypto.ECDSA) {
this._setEC(params);
} else if (typeof KJUR.crypto.DSA != 'undefined' &&
params instanceof KJUR.crypto.DSA) {
this._setDSA(params);
} else if (typeof params['rsakey'] != "undefined") {
this.setRSAKey(params['rsakey']);
} else if (typeof params['rsapem'] != "undefined") {
this.setRSAPEM(params['rsapem']);
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.SubjectPublicKeyInfo, KJUR.asn1.ASN1Object);
/**
* Time ASN.1 structure class
* @name KJUR.asn1.x509.Time
* @class Time ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'str': '130508235959Z'})
* @extends KJUR.asn1.ASN1Object
* @description
*
*
EXAMPLES
* @example
* var t1 = new KJUR.asn1.x509.Time{'str': '130508235959Z'} // UTCTime by default
* var t2 = new KJUR.asn1.x509.Time{'type': 'gen', 'str': '20130508235959Z'} // GeneralizedTime
*/
KJUR.asn1.x509.Time = function(params) {
KJUR.asn1.x509.Time.superclass.constructor.call(this);
var type = null;
var timeParams = null;
this.setTimeParams = function(timeParams) {
this.timeParams = timeParams;
}
this.getEncodedHex = function() {
if (this.timeParams == null) {
throw "timeParams shall be specified. ({'str':'130403235959Z'}}";
}
var o = null;
if (this.type == "utc") {
o = new KJUR.asn1.DERUTCTime(this.timeParams);
} else {
o = new KJUR.asn1.DERGeneralizedTime(this.timeParams);
}
this.TLV = o.getEncodedHex();
return this.TLV;
};
this.type = "utc";
if (typeof params != "undefined") {
if (typeof params['type'] != "undefined") {
this.type = params['type'];
}
this.timeParams = params;
}
};
YAHOO.lang.extend(KJUR.asn1.x509.Time, KJUR.asn1.ASN1Object);
/**
* AlgorithmIdentifier ASN.1 structure class
* @name KJUR.asn1.x509.AlgorithmIdentifier
* @class AlgorithmIdentifier ASN.1 structure class
* @param {Array} params associative array of parameters (ex. {'name': 'SHA1withRSA'})
* @extends KJUR.asn1.ASN1Object
* @description
* @example
*/
KJUR.asn1.x509.AlgorithmIdentifier = function(params) {
KJUR.asn1.x509.AlgorithmIdentifier.superclass.constructor.call(this);
var nameAlg = null;
var asn1Alg = null;
var asn1Params = null;
var paramEmpty = false;
this.getEncodedHex = function() {
if (this.nameAlg == null && this.asn1Alg == null) {
throw "algorithm not specified";
}
if (this.nameAlg != null && this.asn1Alg == null) {
this.asn1Alg = KJUR.asn1.x509.OID.name2obj(this.nameAlg);
}
var a = [this.asn1Alg];
if (! this.paramEmpty) a.push(this.asn1Params);
var o = new KJUR.asn1.DERSequence({'array': a});
this.hTLV = o.getEncodedHex();
return this.hTLV;
};
if (typeof params != "undefined") {
if (typeof params['name'] != "undefined") {
this.nameAlg = params['name'];
}
if (typeof params['asn1params'] != "undefined") {
this.asn1Params = params['asn1params'];
}
if (typeof params['paramempty'] != "undefined") {
this.paramEmpty = params['paramempty'];
}
}
if (this.asn1Params == null) {
this.asn1Params = new KJUR.asn1.DERNull();
}
};
YAHOO.lang.extend(KJUR.asn1.x509.AlgorithmIdentifier, KJUR.asn1.ASN1Object);
/**
* GeneralName ASN.1 structure class
* @name KJUR.asn1.x509.GeneralName
* @class GeneralName ASN.1 structure class
* @description
*
* As for argument 'params' for constructor, you can specify one of
* following properties:
*
*
rfc822 - rfc822Name[1] (ex. user1@foo.com)
*
dns - dNSName[2] (ex. foo.com)
*
uri - uniformResourceIdentifier[6] (ex. http://foo.com/)
*
* NOTE: Currently this only supports 'uniformResourceIdentifier'.
*
EXAMPLE AND ASN.1 SYNTAX
* @example
* var gn = new KJUR.asn1.x509.GeneralName({'uri': 'http://aaa.com/'});
*
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] Name,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER }
*/
KJUR.asn1.x509.GeneralName = function(params) {
KJUR.asn1.x509.GeneralName.superclass.constructor.call(this);
var asn1Obj = null;
var type = null;
var pTag = {'rfc822': '81', 'dns': '82', 'uri': '86'};
this.setByParam = function(params) {
var str = null;
var v = null;
if (typeof params['rfc822'] != "undefined") {
this.type = 'rfc822';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (typeof params['dns'] != "undefined") {
this.type = 'dns';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (typeof params['uri'] != "undefined") {
this.type = 'uri';
v = new KJUR.asn1.DERIA5String({'str': params[this.type]});
}
if (this.type == null)
throw "unsupported type in params=" + params;
this.asn1Obj = new KJUR.asn1.DERTaggedObject({'explicit': false,
'tag': pTag[this.type],
'obj': v});
};
this.getEncodedHex = function() {
return this.asn1Obj.getEncodedHex();
}
if (typeof params != "undefined") {
this.setByParam(params);
}
};
YAHOO.lang.extend(KJUR.asn1.x509.GeneralName, KJUR.asn1.ASN1Object);
/**
* GeneralNames ASN.1 structure class
* @name KJUR.asn1.x509.GeneralNames
* @class GeneralNames ASN.1 structure class
* @description
*
*
EXAMPLE AND ASN.1 SYNTAX
* @example
* var gns = new KJUR.asn1.x509.GeneralNames([{'uri': 'http://aaa.com/'}, {'uri': 'http://bbb.com/'}]);
*
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
*/
KJUR.asn1.x509.GeneralNames = function(paramsArray) {
KJUR.asn1.x509.GeneralNames.superclass.constructor.call(this);
var asn1Array = null;
/**
* set a array of {@link KJUR.asn1.x509.GeneralName} parameters
* @name setByParamArray
* @memberOf KJUR.asn1.x509.GeneralNames
* @function
* @param {Array} paramsArray Array of {@link KJUR.asn1.x509.GeneralNames}
* @description
*
*
EXAMPLES
* @example
* var gns = new KJUR.asn1.x509.GeneralNames();
* gns.setByParamArray([{'uri': 'http://aaa.com/'}, {'uri': 'http://bbb.com/'}]);
*/
this.setByParamArray = function(paramsArray) {
for (var i = 0; i < paramsArray.length; i++) {
var o = new KJUR.asn1.x509.GeneralName(paramsArray[i]);
this.asn1Array.push(o);
}
};
this.getEncodedHex = function() {
var o = new KJUR.asn1.DERSequence({'array': this.asn1Array});
return o.getEncodedHex();
};
this.asn1Array = new Array();
if (typeof paramsArray != "undefined") {
this.setByParamArray(paramsArray);
}
};
YAHOO.lang.extend(KJUR.asn1.x509.GeneralNames, KJUR.asn1.ASN1Object);
/**
* DistributionPointName ASN.1 structure class
* @name KJUR.asn1.x509.DistributionPointName
* @class DistributionPointName ASN.1 structure class
* @description
* @example
*/
KJUR.asn1.x509.DistributionPointName = function(gnOrRdn) {
KJUR.asn1.x509.DistributionPointName.superclass.constructor.call(this);
var asn1Obj = null;
var type = null;
var tag = null;
var asn1V = null;
this.getEncodedHex = function() {
if (this.type != "full")
throw "currently type shall be 'full': " + this.type;
this.asn1Obj = new KJUR.asn1.DERTaggedObject({'explicit': false,
'tag': this.tag,
'obj': this.asn1V});
this.hTLV = this.asn1Obj.getEncodedHex();
return this.hTLV;
};
if (typeof gnOrRdn != "undefined") {
if (KJUR.asn1.x509.GeneralNames.prototype.isPrototypeOf(gnOrRdn)) {
this.type = "full";
this.tag = "a0";
this.asn1V = gnOrRdn;
} else {
throw "This class supports GeneralNames only as argument";
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.DistributionPointName, KJUR.asn1.ASN1Object);
/**
* DistributionPoint ASN.1 structure class
* @name KJUR.asn1.x509.DistributionPoint
* @class DistributionPoint ASN.1 structure class
* @description
* @example
*/
KJUR.asn1.x509.DistributionPoint = function(params) {
KJUR.asn1.x509.DistributionPoint.superclass.constructor.call(this);
var asn1DP = null;
this.getEncodedHex = function() {
var seq = new KJUR.asn1.DERSequence();
if (this.asn1DP != null) {
var o1 = new KJUR.asn1.DERTaggedObject({'explicit': true,
'tag': 'a0',
'obj': this.asn1DP});
seq.appendASN1Object(o1);
}
this.hTLV = seq.getEncodedHex();
return this.hTLV;
};
if (typeof params != "undefined") {
if (typeof params['dpobj'] != "undefined") {
this.asn1DP = params['dpobj'];
}
}
};
YAHOO.lang.extend(KJUR.asn1.x509.DistributionPoint, KJUR.asn1.ASN1Object);
/**
* static object for OID
* @name KJUR.asn1.x509.OID
* @class static object for OID
* @property {Assoc Array} atype2oidList for short attribyte type name and oid (i.e. 'C' and '2.5.4.6')
* @property {Assoc Array} name2oidList for oid name and oid (i.e. 'keyUsage' and '2.5.29.15')
* @property {Assoc Array} objCache for caching name and DERObjectIdentifier object
* @description
*
*
atype2oidList
*
currently supports 'C', 'O', 'OU', 'ST', 'L' and 'CN' only.
*
name2oidList
*
currently supports 'SHA1withRSA', 'rsaEncryption' and some extension OIDs
*
* @example
*/
KJUR.asn1.x509.OID = new function(params) {
this.atype2oidList = {
'C': '2.5.4.6',
'O': '2.5.4.10',
'OU': '2.5.4.11',
'ST': '2.5.4.8',
'L': '2.5.4.7',
'CN': '2.5.4.3',
};
this.name2oidList = {
'sha384': '2.16.840.1.101.3.4.2.2',
'sha224': '2.16.840.1.101.3.4.2.4',
'MD2withRSA': '1.2.840.113549.1.1.2',
'MD4withRSA': '1.2.840.113549.1.1.3',
'MD5withRSA': '1.2.840.113549.1.1.4',
'SHA1withRSA': '1.2.840.113549.1.1.5',
'SHA224withRSA': '1.2.840.113549.1.1.14',
'SHA256withRSA': '1.2.840.113549.1.1.11',
'SHA384withRSA': '1.2.840.113549.1.1.12',
'SHA512withRSA': '1.2.840.113549.1.1.13',
'SHA1withECDSA': '1.2.840.10045.4.1',
'SHA224withECDSA': '1.2.840.10045.4.3.1',
'SHA256withECDSA': '1.2.840.10045.4.3.2',
'SHA384withECDSA': '1.2.840.10045.4.3.3',
'SHA512withECDSA': '1.2.840.10045.4.3.4',
'dsa': '1.2.840.10040.4.1',
'SHA1withDSA': '1.2.840.10040.4.3',
'SHA224withDSA': '2.16.840.1.101.3.4.3.1',
'SHA256withDSA': '2.16.840.1.101.3.4.3.2',
'rsaEncryption': '1.2.840.113549.1.1.1',
'subjectKeyIdentifier': '2.5.29.14',
'countryName': '2.5.4.6',
'organization': '2.5.4.10',
'organizationalUnit': '2.5.4.11',
'stateOrProvinceName': '2.5.4.8',
'locality': '2.5.4.7',
'commonName': '2.5.4.3',
'keyUsage': '2.5.29.15',
'basicConstraints': '2.5.29.19',
'cRLDistributionPoints': '2.5.29.31',
'certificatePolicies': '2.5.29.32',
'authorityKeyIdentifier': '2.5.29.35',
'extKeyUsage': '2.5.29.37',
'anyExtendedKeyUsage': '2.5.29.37.0',
'serverAuth': '1.3.6.1.5.5.7.3.1',
'clientAuth': '1.3.6.1.5.5.7.3.2',
'codeSigning': '1.3.6.1.5.5.7.3.3',
'emailProtection': '1.3.6.1.5.5.7.3.4',
'timeStamping': '1.3.6.1.5.5.7.3.8',
'ocspSigning': '1.3.6.1.5.5.7.3.9',
'ecPublicKey': '1.2.840.10045.2.1',
'secp256r1': '1.2.840.10045.3.1.7',
'secp256k1': '1.3.132.0.10',
'secp384r1': '1.3.132.0.34',
'pkcs5PBES2': '1.2.840.113549.1.5.13',
'pkcs5PBKDF2': '1.2.840.113549.1.5.12',
'des-EDE3-CBC': '1.2.840.113549.3.7',
};
this.objCache = {};
/**
* get DERObjectIdentifier by registered OID name
* @name name2obj
* @memberOf KJUR.asn1.x509.OID
* @function
* @param {String} name OID
* @description
* @example
* var asn1ObjOID = OID.name2obj('SHA1withRSA');
*/
this.name2obj = function(name) {
if (typeof this.objCache[name] != "undefined")
return this.objCache[name];
if (typeof this.name2oidList[name] == "undefined")
throw "Name of ObjectIdentifier not defined: " + name;
var oid = this.name2oidList[name];
var obj = new KJUR.asn1.DERObjectIdentifier({'oid': oid});
this.objCache[name] = obj;
return obj;
};
/**
* get DERObjectIdentifier by registered attribyte type name such like 'C' or 'CN'
* @name atype2obj
* @memberOf KJUR.asn1.x509.OID
* @function
* @param {String} atype short attribute type name such like 'C' or 'CN'
* @description
* @example
* var asn1ObjOID = OID.atype2obj('CN');
*/
this.atype2obj = function(atype) {
if (typeof this.objCache[atype] != "undefined")
return this.objCache[atype];
if (typeof this.atype2oidList[atype] == "undefined")
throw "AttributeType name undefined: " + atype;
var oid = this.atype2oidList[atype];
var obj = new KJUR.asn1.DERObjectIdentifier({'oid': oid});
this.objCache[atype] = obj;
return obj;
};
};
/**
* X.509 certificate and CRL utilities class
* @name KJUR.asn1.x509.X509Util
* @class X.509 certificate and CRL utilities class
*/
KJUR.asn1.x509.X509Util = new function() {
/**
* get PKCS#8 PEM public key string from RSAKey object
* @name getPKCS8PubKeyPEMfromRSAKey
* @memberOf KJUR.asn1.x509.X509Util
* @function
* @param {RSAKey} rsaKey RSA public key of {@link RSAKey} object
* @description
* @example
* var pem = KJUR.asn1.x509.X509Util.getPKCS8PubKeyPEMfromRSAKey(pubKey);
*/
this.getPKCS8PubKeyPEMfromRSAKey = function(rsaKey) {
var pem = null;
var hN = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(rsaKey.n);
var hE = KJUR.asn1.ASN1Util.integerToByteHex(rsaKey.e);
var iN = new KJUR.asn1.DERInteger({hex: hN});
var iE = new KJUR.asn1.DERInteger({hex: hE});
var asn1PubKey = new KJUR.asn1.DERSequence({array: [iN, iE]});
var hPubKey = asn1PubKey.getEncodedHex();
var o1 = new KJUR.asn1.x509.AlgorithmIdentifier({name: 'rsaEncryption'});
var o2 = new KJUR.asn1.DERBitString({hex: '00' + hPubKey});
var seq = new KJUR.asn1.DERSequence({array: [o1, o2]});
var hP8 = seq.getEncodedHex();
var pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(hP8, "PUBLIC KEY");
return pem;
};
};
/**
* issue a certificate in PEM format
* @name newCertPEM
* @memberOf KJUR.asn1.x509.X509Util
* @function
* @param {Array} param parameter to issue a certificate
* @since asn1x509 1.0.6
* @description
* This method can issue a certificate by a simple
* JSON object.
* NOTE: When using DSA or ECDSA CA signing key,
* use 'paramempty' in 'sigalg' to ommit parameter field
* of AlgorithmIdentifer. In case of RSA, parameter
* NULL will be specified by default.
* @example
* var certPEM = KJUR.asn1.x509.X509Util.newCertPEM(
* { serial: {int: 4},
* sigalg: {name: 'SHA1withECDSA', paramempty: true},
* issuer: {str: '/C=US/O=a'},
* notbefore: {'str': '130504235959Z'},
* notafter: {'str': '140504235959Z'},
* subject: {str: '/C=US/O=b'},
* sbjpubkey: pubKeyPEM,
* ext: [
* {basicConstraints: {cA: true, critical: true}},
* {keyUsage: {bin: '11'}},
* ],
* cakey: [prvkey, pass]}
* );
*/
KJUR.asn1.x509.X509Util.newCertPEM = function(param) {
var ns1 = KJUR.asn1.x509;
var o = new ns1.TBSCertificate();
if (param.serial !== undefined)
o.setSerialNumberByParam(param.serial);
else
throw "serial number undefined.";
if (typeof param.sigalg.name == 'string')
o.setSignatureAlgByParam(param.sigalg);
else
throw "unproper signature algorithm name";
if (param.issuer !== undefined)
o.setIssuerByParam(param.issuer);
else
throw "issuer name undefined.";
if (param.notbefore !== undefined)
o.setNotBeforeByParam(param.notbefore);
else
throw "notbefore undefined.";
if (param.notafter !== undefined)
o.setNotAfterByParam(param.notafter);
else
throw "notafter undefined.";
if (param.subject !== undefined)
o.setSubjectByParam(param.subject);
else
throw "subject name undefined.";
if (param.sbjpubkey !== undefined)
o.setSubjectPublicKeyByGetKey(param.sbjpubkey);
else
throw "subject public key undefined.";
if (param.ext.length !== undefined) {
for (var i = 0; i < param.ext.length; i++) {
for (key in param.ext[i]) {
o.appendExtensionByName(key, param.ext[i][key]);
}
}
}
var caKey = null;
if (param.cakey)
caKey = KEYUTIL.getKey.apply(null, param.cakey);
else
throw "ca key undefined";
var cert = new ns1.Certificate({'tbscertobj': o, 'prvkeyobj': caKey});
cert.sign();
return cert.getPEMString();
};
/*
org.bouncycastle.asn1.x500
AttributeTypeAndValue
DirectoryString
RDN
X500Name
X500NameBuilder
org.bouncycastleasn1.x509
TBSCertificate
*/
================================================
FILE: JavaScript/sm2/js/base64.js
================================================
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
*/
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad="=";
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);
}
if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
return ret;
}
// convert a base64 string to hex
function b64tohex(s) {
var ret = ""
var i;
var k = 0; // b64 state, 0-3
var slop;
var v;
for(i = 0; i < s.length; ++i) {
if(s.charAt(i) == b64pad) break;
v = b64map.indexOf(s.charAt(i));
if(v < 0) continue;
if(k == 0) {
ret += int2char(v >> 2);
slop = v & 3;
k = 1;
}
else if(k == 1) {
ret += int2char((slop << 2) | (v >> 4));
slop = v & 0xf;
k = 2;
}
else if(k == 2) {
ret += int2char(slop);
ret += int2char(v >> 2);
slop = v & 3;
k = 3;
}
else {
ret += int2char((slop << 2) | (v >> 4));
ret += int2char(v & 0xf);
k = 0;
}
}
if(k == 1)
ret += int2char(slop << 2);
return ret;
}
// convert a base64 string to a byte/number array
function b64toBA(s) {
//piggyback on b64tohex for now, optimize later
var h = b64tohex(s);
var i;
var a = new Array();
for(i = 0; 2*i < h.length; ++i) {
a[i] = parseInt(h.substring(2*i,2*i+2),16);
}
return a;
}
================================================
FILE: JavaScript/sm2/js/cipher-core.js
================================================
/*
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
*/
/**
* Cipher core components.
*/
CryptoJS.lib.Cipher || (function (undefined) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var Base = C_lib.Base;
var WordArray = C_lib.WordArray;
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
var C_enc = C.enc;
var Utf8 = C_enc.Utf8;
var Base64 = C_enc.Base64;
var C_algo = C.algo;
var EvpKDF = C_algo.EvpKDF;
/**
* Abstract base cipher template.
*
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
*/
var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*
* @property {WordArray} iv The IV to use for this operation.
*/
cfg: Base.extend(),
/**
* Creates this cipher in encryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
*/
createEncryptor: function (key, cfg) {
return this.create(this._ENC_XFORM_MODE, key, cfg);
},
/**
* Creates this cipher in decryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
*/
createDecryptor: function (key, cfg) {
return this.create(this._DEC_XFORM_MODE, key, cfg);
},
/**
* Initializes a newly created cipher.
*
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @example
*
* var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
*/
init: function (xformMode, key, cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Store transform mode and key
this._xformMode = xformMode;
this._key = key;
// Set initial values
this.reset();
},
/**
* Resets this cipher to its initial state.
*
* @example
*
* cipher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-cipher logic
this._doReset();
},
/**
* Adds data to be encrypted or decrypted.
*
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
*
* @return {WordArray} The data after processing.
*
* @example
*
* var encrypted = cipher.process('data');
* var encrypted = cipher.process(wordArray);
*/
process: function (dataUpdate) {
// Append
this._append(dataUpdate);
// Process available blocks
return this._process();
},
/**
* Finalizes the encryption or decryption process.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
*
* @return {WordArray} The data after final processing.
*
* @example
*
* var encrypted = cipher.finalize();
* var encrypted = cipher.finalize('data');
* var encrypted = cipher.finalize(wordArray);
*/
finalize: function (dataUpdate) {
// Final data update
if (dataUpdate) {
this._append(dataUpdate);
}
// Perform concrete-cipher logic
var finalProcessedData = this._doFinalize();
return finalProcessedData;
},
keySize: 128/32,
ivSize: 128/32,
_ENC_XFORM_MODE: 1,
_DEC_XFORM_MODE: 2,
/**
* Creates shortcut functions to a cipher's object interface.
*
* @param {Cipher} cipher The cipher to create a helper for.
*
* @return {Object} An object with encrypt and decrypt shortcut functions.
*
* @static
*
* @example
*
* var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
*/
_createHelper: (function () {
function selectCipherStrategy(key) {
if (typeof key == 'string') {
return PasswordBasedCipher;
} else {
return SerializableCipher;
}
}
return function (cipher) {
return {
encrypt: function (message, key, cfg) {
return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
},
decrypt: function (ciphertext, key, cfg) {
return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
}
};
};
}())
});
/**
* Abstract base stream cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
*/
var StreamCipher = C_lib.StreamCipher = Cipher.extend({
_doFinalize: function () {
// Process partial blocks
var finalProcessedBlocks = this._process(!!'flush');
return finalProcessedBlocks;
},
blockSize: 1
});
/**
* Mode namespace.
*/
var C_mode = C.mode = {};
/**
* Abstract base block cipher mode template.
*/
var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
/**
* Creates this mode for encryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
*/
createEncryptor: function (cipher, iv) {
return this.Encryptor.create(cipher, iv);
},
/**
* Creates this mode for decryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
*/
createDecryptor: function (cipher, iv) {
return this.Decryptor.create(cipher, iv);
},
/**
* Initializes a newly created mode.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @example
*
* var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
*/
init: function (cipher, iv) {
this._cipher = cipher;
this._iv = iv;
}
});
/**
* Cipher Block Chaining mode.
*/
var CBC = C_mode.CBC = (function () {
/**
* Abstract base CBC mode.
*/
var CBC = BlockCipherMode.extend();
/**
* CBC encryptor.
*/
CBC.Encryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// XOR and encrypt
xorBlock.call(this, words, offset, blockSize);
cipher.encryptBlock(words, offset);
// Remember this block to use with next block
this._prevBlock = words.slice(offset, offset + blockSize);
}
});
/**
* CBC decryptor.
*/
CBC.Decryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// Remember this block to use with next block
var thisBlock = words.slice(offset, offset + blockSize);
// Decrypt and XOR
cipher.decryptBlock(words, offset);
xorBlock.call(this, words, offset, blockSize);
// This block becomes the previous block
this._prevBlock = thisBlock;
}
});
function xorBlock(words, offset, blockSize) {
// Shortcut
var iv = this._iv;
// Choose mixing block
if (iv) {
var block = iv;
// Remove IV for subsequent blocks
this._iv = undefined;
} else {
var block = this._prevBlock;
}
// XOR blocks
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= block[i];
}
}
return CBC;
}());
/**
* Padding namespace.
*/
var C_pad = C.pad = {};
/**
* PKCS #5/7 padding strategy.
*/
var Pkcs7 = C_pad.Pkcs7 = {
/**
* Pads data using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to pad.
* @param {number} blockSize The multiple that the data should be padded to.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.pad(wordArray, 4);
*/
pad: function (data, blockSize) {
// Shortcut
var blockSizeBytes = blockSize * 4;
// Count padding bytes
var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
// Create padding word
var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
// Create padding
var paddingWords = [];
for (var i = 0; i < nPaddingBytes; i += 4) {
paddingWords.push(paddingWord);
}
var padding = WordArray.create(paddingWords, nPaddingBytes);
// Add padding
data.concat(padding);
},
/**
* Unpads data that had been padded using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to unpad.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.unpad(wordArray);
*/
unpad: function (data) {
// Get number of padding bytes from last byte
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
// Remove padding
data.sigBytes -= nPaddingBytes;
}
};
/**
* Abstract base block cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
*/
var BlockCipher = C_lib.BlockCipher = Cipher.extend({
/**
* Configuration options.
*
* @property {Mode} mode The block mode to use. Default: CBC
* @property {Padding} padding The padding strategy to use. Default: Pkcs7
*/
cfg: Cipher.cfg.extend({
mode: CBC,
padding: Pkcs7
}),
reset: function () {
// Reset cipher
Cipher.reset.call(this);
// Shortcuts
var cfg = this.cfg;
var iv = cfg.iv;
var mode = cfg.mode;
// Reset block mode
if (this._xformMode == this._ENC_XFORM_MODE) {
var modeCreator = mode.createEncryptor;
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
var modeCreator = mode.createDecryptor;
// Keep at least one block in the buffer for unpadding
this._minBufferSize = 1;
}
this._mode = modeCreator.call(mode, this, iv && iv.words);
},
_doProcessBlock: function (words, offset) {
this._mode.processBlock(words, offset);
},
_doFinalize: function () {
// Shortcut
var padding = this.cfg.padding;
// Finalize
if (this._xformMode == this._ENC_XFORM_MODE) {
// Pad data
padding.pad(this._data, this.blockSize);
// Process final blocks
var finalProcessedBlocks = this._process(!!'flush');
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
// Process final blocks
var finalProcessedBlocks = this._process(!!'flush');
// Unpad data
padding.unpad(finalProcessedBlocks);
}
return finalProcessedBlocks;
},
blockSize: 128/32
});
/**
* A collection of cipher parameters.
*
* @property {WordArray} ciphertext The raw ciphertext.
* @property {WordArray} key The key to this ciphertext.
* @property {WordArray} iv The IV used in the ciphering operation.
* @property {WordArray} salt The salt used with a key derivation function.
* @property {Cipher} algorithm The cipher algorithm.
* @property {Mode} mode The block mode used in the ciphering operation.
* @property {Padding} padding The padding scheme used in the ciphering operation.
* @property {number} blockSize The block size of the cipher.
* @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
*/
var CipherParams = C_lib.CipherParams = Base.extend({
/**
* Initializes a newly created cipher params object.
*
* @param {Object} cipherParams An object with any of the possible cipher parameters.
*
* @example
*
* var cipherParams = CryptoJS.lib.CipherParams.create({
* ciphertext: ciphertextWordArray,
* key: keyWordArray,
* iv: ivWordArray,
* salt: saltWordArray,
* algorithm: CryptoJS.algo.AES,
* mode: CryptoJS.mode.CBC,
* padding: CryptoJS.pad.PKCS7,
* blockSize: 4,
* formatter: CryptoJS.format.OpenSSL
* });
*/
init: function (cipherParams) {
this.mixIn(cipherParams);
},
/**
* Converts this cipher params object to a string.
*
* @param {Format} formatter (Optional) The formatting strategy to use.
*
* @return {string} The stringified cipher params.
*
* @throws Error If neither the formatter nor the default formatter is set.
*
* @example
*
* var string = cipherParams + '';
* var string = cipherParams.toString();
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
*/
toString: function (formatter) {
return (formatter || this.formatter).stringify(this);
}
});
/**
* Format namespace.
*/
var C_format = C.format = {};
/**
* OpenSSL formatting strategy.
*/
var OpenSSLFormatter = C_format.OpenSSL = {
/**
* Converts a cipher params object to an OpenSSL-compatible string.
*
* @param {CipherParams} cipherParams The cipher params object.
*
* @return {string} The OpenSSL-compatible string.
*
* @static
*
* @example
*
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
*/
stringify: function (cipherParams) {
// Shortcuts
var ciphertext = cipherParams.ciphertext;
var salt = cipherParams.salt;
// Format
if (salt) {
var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
} else {
var wordArray = ciphertext;
}
return wordArray.toString(Base64);
},
/**
* Converts an OpenSSL-compatible string to a cipher params object.
*
* @param {string} openSSLStr The OpenSSL-compatible string.
*
* @return {CipherParams} The cipher params object.
*
* @static
*
* @example
*
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
*/
parse: function (openSSLStr) {
// Parse base64
var ciphertext = Base64.parse(openSSLStr);
// Shortcut
var ciphertextWords = ciphertext.words;
// Test for salt
if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
// Extract salt
var salt = WordArray.create(ciphertextWords.slice(2, 4));
// Remove salt from ciphertext
ciphertextWords.splice(0, 4);
ciphertext.sigBytes -= 16;
}
return CipherParams.create({ ciphertext: ciphertext, salt: salt });
}
};
/**
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
*/
var SerializableCipher = C_lib.SerializableCipher = Base.extend({
/**
* Configuration options.
*
* @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
*/
cfg: Base.extend({
format: OpenSSLFormatter
}),
/**
* Encrypts a message.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Encrypt
var encryptor = cipher.createEncryptor(key, cfg);
var ciphertext = encryptor.finalize(message);
// Shortcut
var cipherCfg = encryptor.cfg;
// Create and return serializable cipher params
return CipherParams.create({
ciphertext: ciphertext,
key: key,
iv: cipherCfg.iv,
algorithm: cipher,
mode: cipherCfg.mode,
padding: cipherCfg.padding,
blockSize: cipher.blockSize,
formatter: cfg.format
});
},
/**
* Decrypts serialized ciphertext.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Decrypt
var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
return plaintext;
},
/**
* Converts serialized ciphertext to CipherParams,
* else assumed CipherParams already and returns ciphertext unchanged.
*
* @param {CipherParams|string} ciphertext The ciphertext.
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
*
* @return {CipherParams} The unserialized ciphertext.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
*/
_parse: function (ciphertext, format) {
if (typeof ciphertext == 'string') {
return format.parse(ciphertext, this);
} else {
return ciphertext;
}
}
});
/**
* Key derivation function namespace.
*/
var C_kdf = C.kdf = {};
/**
* OpenSSL key derivation function.
*/
var OpenSSLKdf = C_kdf.OpenSSL = {
/**
* Derives a key and IV from a password.
*
* @param {string} password The password to derive from.
* @param {number} keySize The size in words of the key to generate.
* @param {number} ivSize The size in words of the IV to generate.
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
*
* @return {CipherParams} A cipher params object with the key, IV, and salt.
*
* @static
*
* @example
*
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
*/
execute: function (password, keySize, ivSize, salt) {
// Generate random salt
if (!salt) {
salt = WordArray.random(64/8);
}
// Derive key and IV
var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
// Separate key and IV
var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
key.sigBytes = keySize * 4;
// Return params
return CipherParams.create({ key: key, iv: iv, salt: salt });
}
};
/**
* A serializable cipher wrapper that derives the key from a password,
* and returns ciphertext as a serializable cipher params object.
*/
var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
/**
* Configuration options.
*
* @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
*/
cfg: SerializableCipher.cfg.extend({
kdf: OpenSSLKdf
}),
/**
* Encrypts a message using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
// Add IV to config
cfg.iv = derivedParams.iv;
// Encrypt
var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
// Mix in derived params
ciphertext.mixIn(derivedParams);
return ciphertext;
},
/**
* Decrypts serialized ciphertext using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
// Add IV to config
cfg.iv = derivedParams.iv;
// Decrypt
var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
return plaintext;
}
});
}());
================================================
FILE: JavaScript/sm2/js/core.js
================================================
/*
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
*/
/**
* 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 if (thatWords.length > 0xffff) {
// Copy one word at a time
for (var i = 0; i < thatSigBytes; i += 4) {
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
}
} else {
// Copy all words at once
thisWords.push.apply(thisWords, thatWords);
}
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));
================================================
FILE: JavaScript/sm2/js/crypto-1.1.js
================================================
/*! crypto-1.1.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* crypto.js - Cryptographic Algorithm Provider class
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/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.1.5 (2013-Oct-06)
* @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.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',
'sm3': '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',
'sm3': 'CryptoJS.algo.SM3'
};
/**
* 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
*/
this.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
*/
this.ripemd160 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
return md.digestString(s);
};
/*
* @since 1.1.2
*/
this.getCryptoJSMDByName = function(s) {
};
};
/**
* 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
* @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
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core.js"></script>
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/sha1.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
* md.updateString('aaa')
* var mdHex = md.digest()
*
* // SJCL(Stanford JavaScript Crypto Library) provider sample
* <script src="http://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
* md.updateString('aaa')
* var mdHex = md.digest()
*/
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
* @example
* // for SHA1
* md.setAlgAndProvider('sha1', 'cryptojs');
* // for RIPEMD160
* md.setAlgAndProvider('ripemd160', 'cryptojs');
*/
this.setAlgAndProvider = function(alg, prov) {
if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
// for cryptojs
if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:sm3:'.indexOf(alg) != -1 &&
prov == 'cryptojs') {
try {
this.md = eval(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);
}
}
};
/**
* 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.
* @example
* var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", prov: "cryptojs", "pass": "pass"});
* mac.updateString('aaa')
* var macHex = md.doFinal()
*/
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) {
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 = eval(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
* md.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
* md.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
* md.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
* md.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
* md.digestHex('0f2abd')
*/
this.doFinalHex = function(hex) {
throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
};
if (params !== undefined) {
if (params['pass'] !== undefined) {
this.pass = 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 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() {
if (this.algName.match(/^(.+)with(.+)$/)) {
this.mdAlgName = RegExp.$1.toLowerCase();
this.pubkeyAlgName = RegExp.$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:sm3:'.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.initSign = function(params) {
if (typeof params['ecprvhex'] == 'string' &&
typeof params['eccurvename'] == 'string') {
this.ecprvhex = params['ecprvhex'];
this.eccurvename = params['eccurvename'];
} else {
this.prvKey = params;
}
this.state = "SIGN";
};
this.initVerifyByPublicKey = function(params) {
if (typeof params['ecpubhex'] == 'string' &&
typeof params['eccurvename'] == 'string') {
this.ecpubhex = params['ecpubhex'];
this.eccurvename = params['eccurvename'];
} else if (params instanceof KJUR.crypto.ECDSA) {
this.pubKey = params;
} else if (params instanceof RSAKey) {
this.pubKey = params;
}
this.state = "VERIFY";
};
this.initVerifyByCertificatePEM = function(certPEM) {
var x509 = new X509();
x509.readCertPEM(certPEM);
this.pubKey = x509.subjectPublicKeyRSA;
this.state = "VERIFY";
};
this.updateString = function(str) {
this.md.updateString(str);
};
this.updateHex = function(hex) {
this.md.updateHex(hex);
};
this.sign = function() {
if(this.eccurvename != "sm2") {
this.sHashHex = this.md.digest();
}
if (typeof this.ecprvhex != "undefined" &&
typeof this.eccurvename != "undefined") {
if(this.eccurvename == "sm2")
{
var ec = new KJUR.crypto.SM3withSM2({curve: this.eccurvename});
var G = ec.ecparams['G'];
var Q = G.multiply(new BigInteger(this.ecprvhex, 16));
var pubKeyHex = Q.getX().toBigInteger().toRadix(16) + Q.getY().toBigInteger().toRadix(16);
var smDigest = new SM3Digest();
var z = new SM3Digest().GetZ(G, pubKeyHex);
var zValue = smDigest.GetWords(smDigest.GetHex(z).toString());
var rawData = CryptoJS.enc.Utf8.stringify(this.md.md._data);
rawData = CryptoJS.enc.Utf8.parse(rawData).toString();
rawData = smDigest.GetWords(rawData);
var smHash = new Array(smDigest.GetDigestSize());
smDigest.BlockUpdate(zValue, 0, zValue.length);
smDigest.BlockUpdate(rawData, 0, rawData.length);
smDigest.DoFinal(smHash, 0);
var hashHex = smDigest.GetHex(smHash).toString();
this.sHashHex = hashHex;
this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
}else {
var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
}
} else if (this.pubkeyAlgName == "rsaandmgf1") {
this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
this.mdAlgName,
this.pssSaltLen);
} else if (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 public key alg: " + this.pubkeyAlgName;
}
return this.hSign;
};
this.signString = function(str) {
this.updateString(str);
this.sign();
};
this.signHex = function(hex) {
this.updateHex(hex);
this.sign();
};
this.verify = function(hSigVal) {
if(this.eccurvename != "sm2") {
this.sHashHex = this.md.digest();
}
if (typeof this.ecpubhex != "undefined" &&
typeof this.eccurvename != "undefined") {
if(this.eccurvename == "sm2")
{
var ec = new KJUR.crypto.SM3withSM2({curve: this.eccurvename});
var G = ec.ecparams['G'];
var pubKeyHex = this.ecpubhex.substr(2, 128);
var smDigest = new SM3Digest();
var z = new SM3Digest().GetZ(G, pubKeyHex);
var zValue = smDigest.GetWords(smDigest.GetHex(z).toString());
var rawData = CryptoJS.enc.Utf8.stringify(this.md.md._data);
rawData = CryptoJS.enc.Utf8.parse(rawData).toString();
rawData = smDigest.GetWords(rawData);
var smHash = new Array(smDigest.GetDigestSize());
smDigest.BlockUpdate(zValue, 0, zValue.length);
smDigest.BlockUpdate(rawData, 0, rawData.length);
smDigest.DoFinal(smHash, 0);
var hashHex = smDigest.GetHex(smHash).toString();
this.sHashHex = hashHex;
return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
}else {
var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
}
} else if (this.pubkeyAlgName == "rsaandmgf1") {
return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal,
this.mdAlgName,
this.pssSaltLen);
} else if (this.pubkeyAlgName == "rsa") {
return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
} else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
} else if (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:
*
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;
};
/**
* Initialize this object for verifying with a public key
* @name initVerifyByPublicKey
* @memberOf KJUR.crypto.Signature
* @function
* @param {Object} param RSAKey object of public key or associative array for ECDSA
* @since 1.0.2
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* Public key information will be provided as 'param' parameter and the value will be
* following:
*
* @example
* sig.initVerifyByPublicKey(rsaPrvKey)
*/
this.initVerifyByPublicKey = function(rsaPubKey) {
throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
this.algProvName;
};
/**
* Initialize this object for verifying with a certficate
* @name initVerifyByCertificatePEM
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} certPEM PEM formatted string of certificate
* @since 1.0.2
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* @example
* sig.initVerifyByCertificatePEM(certPEM)
*/
this.initVerifyByCertificatePEM = function(certPEM) {
throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
this.algProvName;
};
/**
* Initialize this object for signing
* @name initSign
* @memberOf KJUR.crypto.Signature
* @function
* @param {Object} param RSAKey object of public key or associative array for ECDSA
* @deprecated from crypto 1.1.5. please use init() method instead.
* @description
* Private key information will be provided as 'param' parameter and the value will be
* following:
*
* @example
* sig.initSign(prvKey)
*/
this.initSign = function(prvKey) {
throw "initSign(prvKey) 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 = new RSAKey();
prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
this.initSign(prvKey);
} catch (ex) {
throw "fatal error to load pem private key: " + ex;
}
}
}
}
};
/**
* 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
};
};
================================================
FILE: JavaScript/sm2/js/ec-patch.js
================================================
/*! (c) Stefan Thomas | https://github.com/bitcoinjs/bitcoinjs-lib
*/
/*
* splitted from bitcoin-lib/ecdsa.js
*
* version 1.0.0 is the original of bitcoin-lib/ecdsa.js
*/
ECFieldElementFp.prototype.getByteLength = function () {
return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
};
ECPointFp.prototype.getEncoded = function (compressed) {
var integerToBytes = function(i, len) {
var bytes = i.toByteArrayUnsigned();
if (len < bytes.length) {
bytes = bytes.slice(bytes.length-len);
} else while (len > bytes.length) {
bytes.unshift(0);
}
return bytes;
};
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
// Get value as a 32-byte Buffer
// Fixed length based on a patch by bitaddress.org and Casascius
var enc = integerToBytes(x, 32);
if (compressed) {
if (y.isEven()) {
// Compressed even pubkey
// M = 02 || X
enc.unshift(0x02);
} else {
// Compressed uneven pubkey
// M = 03 || X
enc.unshift(0x03);
}
} else {
// Uncompressed pubkey
// M = 04 || X || Y
enc.unshift(0x04);
enc = enc.concat(integerToBytes(y, 32));
}
return enc;
};
ECPointFp.decodeFrom = function (curve, enc) {
var type = enc[0];
var dataLen = enc.length-1;
// Extract x and y as byte arrays
var xBa = enc.slice(1, 1 + dataLen/2);
var yBa = enc.slice(1 + dataLen/2, 1 + dataLen);
// Prepend zero byte to prevent interpretation as negative integer
xBa.unshift(0);
yBa.unshift(0);
// Convert to BigIntegers
var x = new BigInteger(xBa);
var y = new BigInteger(yBa);
// Return point
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
};
/*
* @since ec-patch.js 1.0.1
*/
ECPointFp.decodeFromHex = function (curve, encHex) {
var type = encHex.substr(0, 2); // shall be "04"
var dataLen = encHex.length - 2;
// Extract x and y as byte arrays
var xHex = encHex.substr(2, dataLen / 2);
var yHex = encHex.substr(2 + dataLen / 2, dataLen / 2);
// Convert to BigIntegers
var x = new BigInteger(xHex, 16);
var y = new BigInteger(yHex, 16);
// Return point
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
};
ECPointFp.prototype.add2D = function (b) {
if(this.isInfinity()) return b;
if(b.isInfinity()) return this;
if (this.x.equals(b.x)) {
if (this.y.equals(b.y)) {
// this = b, i.e. this must be doubled
return this.twice();
}
// this = -b, i.e. the result is the point at infinity
return this.curve.getInfinity();
}
var x_x = b.x.subtract(this.x);
var y_y = b.y.subtract(this.y);
var gamma = y_y.divide(x_x);
var x3 = gamma.square().subtract(this.x).subtract(b.x);
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
return new ECPointFp(this.curve, x3, y3);
};
ECPointFp.prototype.twice2D = function () {
if (this.isInfinity()) return this;
if (this.y.toBigInteger().signum() == 0) {
// if y1 == 0, then (x1, y1) == (x1, -y1)
// and hence this = -this and thus 2(x1, y1) == infinity
return this.curve.getInfinity();
}
var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO));
var x3 = gamma.square().subtract(this.x.multiply(TWO));
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
return new ECPointFp(this.curve, x3, y3);
};
ECPointFp.prototype.multiply2D = function (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.add2D(hBit ? this : neg);
}
}
return R;
};
ECPointFp.prototype.isOnCurve = function () {
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
var a = this.curve.getA().toBigInteger();
var b = this.curve.getB().toBigInteger();
var n = this.curve.getQ();
var lhs = y.multiply(y).mod(n);
var rhs = x.multiply(x).multiply(x)
.add(a.multiply(x)).add(b).mod(n);
return lhs.equals(rhs);
};
ECPointFp.prototype.toString = function () {
return '('+this.getX().toBigInteger().toString()+','+
this.getY().toBigInteger().toString()+')';
};
/**
* Validate an elliptic curve point.
*
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
*/
ECPointFp.prototype.validate = function () {
var n = this.curve.getQ();
// Check Q != O
if (this.isInfinity()) {
throw new Error("Point is at infinity.");
}
// Check coordinate bounds
var x = this.getX().toBigInteger();
var y = this.getY().toBigInteger();
if (x.compareTo(BigInteger.ONE) < 0 ||
x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
throw new Error('x coordinate out of bounds');
}
if (y.compareTo(BigInteger.ONE) < 0 ||
y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
throw new Error('y coordinate out of bounds');
}
// Check y^2 = x^3 + ax + b (mod n)
if (!this.isOnCurve()) {
throw new Error("Point is not on the curve.");
}
// Check nQ = 0 (Q is a scalar multiple of G)
if (this.multiply(n).isInfinity()) {
// TODO: This check doesn't work - fix.
throw new Error("Point is not a scalar multiple of G.");
}
return true;
};
================================================
FILE: JavaScript/sm2/js/ec.js
================================================
/*! (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;
================================================
FILE: JavaScript/sm2/js/ecdsa-modified-1.0.js
================================================
/*! ecdsa-modified-1.0.4.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
*/
/*
* ecdsa-modified.js - modified Bitcoin.ECDSA class
*
* Copyright (c) 2013 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 1.0.4 (2013-Oct-06)
* @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";
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;
}
/**
* 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 = KJUR.crypto.ECDSA({'curve': 'secp256r1'});
* var keypair = ec.generateKeyPairHex();
* var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
* var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
*/
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 = 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 = 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};
};
/*
* 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 = 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 = 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) {
// 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 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV1);
var hS = ASN1HEX.getHexOfV_AtObj(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;
if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8)
hR = hR.substr(2);
if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8)
hS = hS.substr(2);
if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
throw "unknown ECDSA sig r length error";
if ((((hS.length / 2) * 8) % (16 * 8)) != 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 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();
};
================================================
FILE: JavaScript/sm2/js/ecparam-1.0.js
================================================
/*! 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.
* http://kjur.github.com/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
KJUR.crypto.ECParameterDB.regist(
"sm2", // name
256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", // p
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", // a
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", // b
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", // n
"1", // h
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", // gx
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", // gy
["sm2", "SM2"]); // alias
================================================
FILE: JavaScript/sm2/js/enc-base64.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64 encoding strategy.
*/
var Base64 = C_enc.Base64 = {
/**
* Converts a word array to a Base64 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Base64 string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64 string to a word array.
*
* @param {string} base64Str The Base64 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
*/
parse: function (base64Str) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = this._map;
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex != -1) {
base64StrLength = paddingIndex;
}
}
// Convert
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2);
var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2);
words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
};
}());
================================================
FILE: JavaScript/sm2/js/fingerprint.js
================================================
/*
* fingerprintJS 0.5.4 - Fast browser fingerprint library
* https://github.com/Valve/fingerprintjs
* Copyright (c) 2013 Valentin Vasilyev (valentin.vasilyev@outlook.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
;(function (name, context, definition) {
if (typeof module !== 'undefined' && module.exports) { module.exports = definition(); }
else if (typeof define === 'function' && define.amd) { define(definition); }
else { context[name] = definition(); }
})('Fingerprint', this, function () {
'use strict';
var Fingerprint = function (options) {
var nativeForEach, nativeMap;
nativeForEach = Array.prototype.forEach;
nativeMap = Array.prototype.map;
this.each = function (obj, iterator, context) {
if (obj === null) {
return;
}
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
if (iterator.call(context, obj[i], i, obj) === {}) return;
}
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (iterator.call(context, obj[key], key, obj) === {}) return;
}
}
}
};
this.map = function(obj, iterator, context) {
var results = [];
// Not using strict equality so that this acts as a
// shortcut to checking for `null` and `undefined`.
if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
this.each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list);
});
return results;
};
if (typeof options == 'object'){
this.hasher = options.hasher;
this.screen_resolution = options.screen_resolution;
this.screen_orientation = options.screen_orientation;
this.canvas = options.canvas;
this.ie_activex = options.ie_activex;
} else if(typeof options == 'function'){
this.hasher = options;
}
};
Fingerprint.prototype = {
get: function(){
var keys = [];
keys.push(navigator.userAgent);
keys.push(navigator.language);
keys.push(screen.colorDepth);
if (this.screen_resolution) {
var resolution = this.getScreenResolution();
if (typeof resolution !== 'undefined'){ // headless browsers, such as phantomjs
keys.push(resolution.join('x'));
}
}
keys.push(new Date().getTimezoneOffset());
keys.push(this.hasSessionStorage());
keys.push(this.hasLocalStorage());
keys.push(!!window.indexedDB);
//body might not be defined at this point or removed programmatically
if(document.body){
keys.push(typeof(document.body.addBehavior));
} else {
keys.push(typeof undefined);
}
keys.push(typeof(window.openDatabase));
keys.push(navigator.cpuClass);
keys.push(navigator.platform);
keys.push(navigator.doNotTrack);
keys.push(this.getPluginsString());
if(this.canvas && this.isCanvasSupported()){
keys.push(this.getCanvasFingerprint());
}
if(this.hasher){
return this.hasher(keys.join('###'), 31);
} else {
return this.murmurhash3_32_gc(keys.join('###'), 31);
}
},
/**
* JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
*
* @author Gary Court
* @see http://github.com/garycourt/murmurhash-js
* @author Austin Appleby
* @see http://sites.google.com/site/murmurhash/
*
* @param {string} key ASCII only
* @param {number} seed Positive integer only
* @return {number} 32-bit positive integer hash
*/
murmurhash3_32_gc: function(key, seed) {
var remainder, bytes, h1, h1b, c1, c2, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
},
// https://bugzilla.mozilla.org/show_bug.cgi?id=781447
hasLocalStorage: function () {
try{
return !!window.localStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
hasSessionStorage: function () {
try{
return !!window.sessionStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
isCanvasSupported: function () {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
},
isIE: function () {
if(navigator.appName === 'Microsoft Internet Explorer') {
return true;
} else if(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)){// IE 11
return true;
}
return false;
},
getPluginsString: function () {
if(this.isIE() && this.ie_activex){
return this.getIEPluginsString();
} else {
return this.getRegularPluginsString();
}
},
getRegularPluginsString: function () {
return this.map(navigator.plugins, function (p) {
var mimeTypes = this.map(p, function(mt){
return [mt.type, mt.suffixes].join('~');
}).join(',');
return [p.name, p.description, mimeTypes].join('::');
}, this).join(';');
},
getIEPluginsString: function () {
if(window.ActiveXObject){
var names = ['ShockwaveFlash.ShockwaveFlash',//flash plugin
'AcroPDF.PDF', // Adobe PDF reader 7+
'PDF.PdfCtrl', // Adobe PDF reader 6 and earlier, brrr
'QuickTime.QuickTime', // QuickTime
// 5 versions of real players
'rmocx.RealPlayer G2 Control',
'rmocx.RealPlayer G2 Control.1',
'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
'RealPlayer',
'SWCtl.SWCtl', // ShockWave player
'WMPlayer.OCX', // Windows media player
'AgControl.AgControl', // Silverlight
'Skype.Detection'];
// starting to detect plugins in IE
return this.map(names, function(name){
try{
new ActiveXObject(name);
return name;
} catch(e){
return null;
}
}).join(';');
} else {
return ""; // behavior prior version 0.5.0, not breaking backwards compat.
}
},
getScreenResolution: function () {
var resolution;
if(this.screen_orientation){
resolution = (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height];
}else{
resolution = [screen.height, screen.width];
}
return resolution;
},
getCanvasFingerprint: function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// https://www.browserleaks.com/canvas#how-does-it-work
var txt = 'http://valve.github.io';
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
ctx.fillText(txt, 4, 17);
return canvas.toDataURL();
}
};
return Fingerprint;
});
================================================
FILE: JavaScript/sm2/js/jsbn.js
================================================
/*! (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);
================================================
FILE: JavaScript/sm2/js/jsbn2.js
================================================
/*! (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)
================================================
FILE: JavaScript/sm2/js/md5.js
================================================
/*
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;
// Constants table
var T = [];
// Compute constants
(function () {
for (var i = 0; i < 64; i++) {
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
}
}());
/**
* MD5 hash algorithm.
*/
var MD5 = C_algo.MD5 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476
]);
},
_doProcessBlock: function (M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
);
}
// Shortcuts
var H = this._hash.words;
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Computation
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
a = II(a, b, c, d, M_offset_0, 6, T[48]);
d = II(d, a, b, c, M_offset_7, 10, T[49]);
c = II(c, d, a, b, M_offset_14, 15, T[50]);
b = II(b, c, d, a, M_offset_5, 21, T[51]);
a = II(a, b, c, d, M_offset_12, 6, T[52]);
d = II(d, a, b, c, M_offset_3, 10, T[53]);
c = II(c, d, a, b, M_offset_10, 15, T[54]);
b = II(b, c, d, a, M_offset_1, 21, T[55]);
a = II(a, b, c, d, M_offset_8, 6, T[56]);
d = II(d, a, b, c, M_offset_15, 10, T[57]);
c = II(c, d, a, b, M_offset_6, 15, T[58]);
b = II(b, c, d, a, M_offset_13, 21, T[59]);
a = II(a, b, c, d, M_offset_4, 6, T[60]);
d = II(d, a, b, c, M_offset_11, 10, T[61]);
c = II(c, d, a, b, M_offset_2, 15, T[62]);
b = II(b, c, d, a, M_offset_9, 21, T[63]);
// 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;
},
_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);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
);
data.sigBytes = (dataWords.length + 1) * 4;
// Hash final blocks
this._process();
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
// Return final computed hash
return hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
function FF(a, b, c, d, x, s, t) {
var n = a + ((b & c) | (~b & d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function GG(a, b, c, d, x, s, t) {
var n = a + ((b & d) | (c & ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function HH(a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function II(a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
/**
* 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.MD5('message');
* var hash = CryptoJS.MD5(wordArray);
*/
C.MD5 = Hasher._createHelper(MD5);
/**
* 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.HmacMD5(message, key);
*/
C.HmacMD5 = Hasher._createHmacHelper(MD5);
}(Math));
================================================
FILE: JavaScript/sm2/js/pkcs5pkey-1.0.js
================================================
/*! pkcs5pkey-1.0.5.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* pkcs5pkey.js - reading passcode protected PKCS#5 PEM formatted RSA private key
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name pkcs5pkey-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version pkcs5pkey 1.0.5 (2013-Aug-20)
* @since jsrsasign 2.0.0
* @license MIT License
*/
/**
* @name PKCS5PKEY
* @class class for PKCS#5 and PKCS#8 private key
* @deprecated Since jsrsasign 4.1.3. Please use KEYUTIL class.
* @description
*
* {@link PKCS5PKEY} class has following features:
*
*
read and parse PEM formatted encrypted PKCS#5 private key
*
*/
parsePrivateRawECKeyHexAtObj: function(pkcs8PrvHex, info) {
var keyIdx = info.keyidx;
// 1. sequence
if (pkcs8PrvHex.substr(keyIdx, 2) != "30")
throw "malformed ECC private key(code:001)"; // not sequence
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PrvHex, keyIdx);
if (a1.length != 3)
throw "malformed ECC private key(code:002)"; // not sequence
// 2. EC private key
if (pkcs8PrvHex.substr(a1[1], 2) != "04")
throw "malformed ECC private key(code:003)"; // not octetstring
info.key = ASN1HEX.getHexOfV_AtObj(pkcs8PrvHex, a1[1]);
},
/**
* parse hexadecimal string of PKCS#8 public key
* @name parsePublicPKCS8Hex
* @memberOf PKCS5PKEY
* @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 or null
*
key - hexadecimal string of public key
*
*/
parsePublicPKCS8Hex: function(pkcs8PubHex) {
var result = {};
result.algparam = null;
// 1. AlgID and Key bit string
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getPosArrayOfChildren_AtObj(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 = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[0]);
// 2.2. AlgID param
if (pkcs8PubHex.substr(a2[1], 2) == "06") {
result.algparam = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[1]);
}
// 3. Key
if (pkcs8PubHex.substr(a1[1], 2) != "03")
throw "malformed PKCS8 public key(code:004)"; // Key is not bit string
result.key = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a1[1]).substr(2);
// 4. return result assoc array
return result;
},
/**
* provide hexadecimal string of unencrypted PKCS#8 private key and returns RSAKey object
* @name getRSAKeyFromPublicPKCS8Hex
* @memberOf PKCS5PKEY
* @function
* @param {String} pkcs8PubHex hexadecimal string of unencrypted PKCS#8 public key
* @return {RSAKey} loaded RSAKey object of RSA public key
* @since pkcs5pkey 1.0.4
*/
getRSAKeyFromPublicPKCS8Hex: function(pkcs8PubHex) {
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PubHex, 0);
if (a1.length != 2)
throw "outer DERSequence shall have 2 elements: " + a1.length;
var algIdTLV =ASN1HEX.getHexOfTLV_AtObj(pkcs8PubHex, a1[0]);
if (algIdTLV != "300d06092a864886f70d0101010500") // AlgId rsaEncryption
throw "PKCS8 AlgorithmId is not rsaEncryption";
if (pkcs8PubHex.substr(a1[1], 2) != "03")
throw "PKCS8 Public Key is not BITSTRING encapslated.";
var idxPub = ASN1HEX.getStartPosOfV_AtObj(pkcs8PubHex, a1[1]) + 2; // 2 for unused bit
if (pkcs8PubHex.substr(idxPub, 2) != "30")
throw "PKCS8 Public Key is not SEQUENCE.";
var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(pkcs8PubHex, idxPub);
if (a2.length != 2)
throw "inner DERSequence shall have 2 elements: " + a2.length;
if (pkcs8PubHex.substr(a2[0], 2) != "02")
throw "N is not ASN.1 INTEGER";
if (pkcs8PubHex.substr(a2[1], 2) != "02")
throw "E is not ASN.1 INTEGER";
var hN = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[0]);
var hE = ASN1HEX.getHexOfV_AtObj(pkcs8PubHex, a2[1]);
var pubKey = new RSAKey();
pubKey.setPublic(hN, hE);
return pubKey;
},
//addAlgorithm: function(functionObject, algName, keyLen, ivLen) {
//}
};
}();
================================================
FILE: JavaScript/sm2/js/prng4.js
================================================
/*! (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;
================================================
FILE: JavaScript/sm2/js/rng.js
================================================
/*! (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(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
// Extract entropy (256 bits) from NS4 RNG if available
var z = window.crypto.random(32);
for(t = 0; t < z.length; ++t)
rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
}
while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
t = Math.floor(65536 * Math.random());
rng_pool[rng_pptr++] = t >>> 8;
rng_pool[rng_pptr++] = t & 255;
}
rng_pptr = 0;
rng_seed_time();
//rng_seed_int(window.screenX);
//rng_seed_int(window.screenY);
}
function rng_get_byte() {
if(rng_state == null) {
rng_seed_time();
rng_state = prng_newstate();
rng_state.init(rng_pool);
for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
rng_pool[rng_pptr] = 0;
rng_pptr = 0;
//rng_pool = null;
}
// TODO: allow reseeding after first request
return rng_state.next();
}
function rng_get_bytes(ba) {
var i;
for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
}
function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;
================================================
FILE: JavaScript/sm2/js/rsa.js
================================================
/*! (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
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
// 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;
}
var SHA1_SIZE = 20;
// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
function oaep_pad(s, n, hash)
{
if (s.length + 2 * SHA1_SIZE + 2 > n)
{
throw "Message too long for RSA";
}
var PS = '', i;
for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
{
PS += '\x00';
}
var DB = rstr_sha1('') + PS + '\x01' + s;
var seed = new Array(SHA1_SIZE);
new SecureRandom().nextBytes(seed);
var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
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, rstr_sha1);
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;
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
alert("Invalid RSA public key");
}
// Perform raw public operation on "x": return x^e (mod n)
function RSADoPublic(x) {
return x.modPowInt(this.e, this.n);
}
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
function RSAEncrypt(text) {
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
function RSAEncryptOAEP(text, hash) {
var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
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";
================================================
FILE: JavaScript/sm2/js/rsa2.js
================================================
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
*/
// Depends on rsa.js and jsbn2.js
// Version 1.1: support utf-8 decoding in pkcs1unpad2
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
function pkcs1unpad2(d,n) {
var b = d.toByteArray();
var i = 0;
while(i < b.length && b[i] == 0) ++i;
if(b.length-i != n-1 || b[i] != 2)
return null;
++i;
while(b[i] != 0)
if(++i >= b.length) return null;
var ret = "";
while(++i < b.length) {
var c = b[i] & 255;
if(c < 128) { // utf-8 decode
ret += String.fromCharCode(c);
}
else if((c > 191) && (c < 224)) {
ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
++i;
}
else {
ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
i += 2;
}
}
return ret;
}
// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_str(seed, len, hash)
{
var mask = '', i = 0;
while (mask.length < len)
{
mask += hash(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]));
i += 1;
}
return mask;
}
var SHA1_SIZE = 20;
// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
function oaep_unpad(d, n, hash)
{
d = d.toByteArray();
var i;
for (i = 0; i < d.length; i += 1)
{
d[i] &= 0xff;
}
while (d.length < n)
{
d.unshift(0);
}
d = String.fromCharCode.apply(String, d);
if (d.length < 2 * SHA1_SIZE + 2)
{
throw "Cipher too short";
}
var maskedSeed = d.substr(1, SHA1_SIZE)
var maskedDB = d.substr(SHA1_SIZE + 1);
var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
var seed = [], i;
for (i = 0; i < maskedSeed.length; i += 1)
{
seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
}
var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
d.length - SHA1_SIZE, rstr_sha1);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1)
{
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB = String.fromCharCode.apply(String, DB);
if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
{
throw "Hash mismatch";
}
DB = DB.substr(SHA1_SIZE);
var first_one = DB.indexOf('\x01');
var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;
if (last_zero + 1 != first_one)
{
throw "Malformed data";
}
return DB.substr(first_one + 1);
}
// Set the private key fields N, e, and d from hex strings
function RSASetPrivate(N,E,D) {
this.isPrivate = true;
if (typeof N !== "string")
{
this.n = N;
this.e = E;
this.d = D;
}
else if(N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
}
else
alert("Invalid RSA private key");
}
// Set the private key fields N, e, d and CRT params from hex strings
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
this.isPrivate = true;
if (N == null) throw "RSASetPrivateEx N == null";
if (E == null) throw "RSASetPrivateEx E == null";
if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
if (E.length == 0) throw "RSASetPrivateEx E.length == 0";
if (N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
this.p = parseBigInt(P,16);
this.q = parseBigInt(Q,16);
this.dmp1 = parseBigInt(DP,16);
this.dmq1 = parseBigInt(DQ,16);
this.coeff = parseBigInt(C,16);
} else {
alert("Invalid RSA private key in RSASetPrivateEx");
}
}
// Generate a new random private key B bits long, using public expt E
function RSAGenerate(B,E) {
var rng = new SecureRandom();
var qs = B>>1;
this.e = parseInt(E,16);
var ee = new BigInteger(E,16);
for(;;) {
for(;;) {
this.p = new BigInteger(B-qs,1,rng);
if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
}
for(;;) {
this.q = new BigInteger(qs,1,rng);
if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
}
if(this.p.compareTo(this.q) <= 0) {
var t = this.p;
this.p = this.q;
this.q = t;
}
var p1 = this.p.subtract(BigInteger.ONE); // p1 = p - 1
var q1 = this.q.subtract(BigInteger.ONE); // q1 = q - 1
var phi = p1.multiply(q1);
if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
this.n = this.p.multiply(this.q); // this.n = p * q
this.d = ee.modInverse(phi); // this.d =
this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1)
this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1)
this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p
break;
}
}
}
// Perform raw private operation on "x": return x^d (mod n)
function RSADoPrivate(x) {
if(this.p == null || this.q == null)
return x.modPow(this.d, this.n);
// TODO: re-calculate any missing CRT params
var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?
while(xp.compareTo(xq) < 0)
xp = xp.add(this.p);
// NOTE:
// xp.subtract(xq) => cp -cq
// xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
// xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecrypt(ctext) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
}
// Return the PKCS#1 OAEP RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecryptOAEP(ctext, hash) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is a Base64-encoded string and the output is a plain string.
//function RSAB64Decrypt(ctext) {
// var h = b64tohex(ctext);
// if(h) return this.decrypt(h); else return null;
//}
// protected
RSAKey.prototype.doPrivate = RSADoPrivate;
// public
RSAKey.prototype.setPrivate = RSASetPrivate;
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
RSAKey.prototype.generate = RSAGenerate;
RSAKey.prototype.decrypt = RSADecrypt;
RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
================================================
FILE: JavaScript/sm2/js/rsapem-1.1.js
================================================
/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
//
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
// to RSAKey class.
//
// version: 1.1.1 (2013-Apr-12)
//
// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
//
// This software is licensed under the terms of the MIT License.
// http://kjur.github.com/jsrsasign/license/
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
//
// Depends on:
//
//
//
// _RSApem_pemToBase64(sPEM)
//
// removing PEM header, PEM footer and space characters including
// new lines from PEM formatted RSA private key string.
//
/**
* @fileOverview
* @name rsapem-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.1
* @license MIT License
*/
function _rsapem_pemToBase64(sPEMPrivateKey) {
var s = sPEMPrivateKey;
s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
s = s.replace("-----END RSA PRIVATE KEY-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
}
function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
var a = new Array();
var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
return a;
}
function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
var v = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
var n = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
var e = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
var d = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
var p = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
var q = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
var a = new Array();
a.push(v, n, e, d, p, q, dp, dq, co);
return a;
}
/**
* read RSA private key from a ASN.1 hexadecimal string
* @name readPrivateKeyFromASN1HexString
* @memberOf RSAKey#
* @function
* @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
* @since 1.1.1
*/
function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
/**
* read PKCS#1 private key from a string
* @name readPrivateKeyFromPEMString
* @memberOf RSAKey#
* @function
* @param {String} keyPEM string of PKCS#1 private key.
*/
function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
var keyB64 = _rsapem_pemToBase64(keyPEM);
var keyHex = b64tohex(keyB64) // depends base64.js
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;
================================================
FILE: JavaScript/sm2/js/rsasign-1.2.js
================================================
/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* rsa-sign.js - adding signing functions to RSAKey class.
*
* version: 1.2.7 (2013 Aug 25)
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license/
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name rsasign-1.2.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version rsasign 1.2.7
* @license MIT License
*/
var _RE_HEXDECONLY = new RegExp("");
_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
// ========================================================================
// Signature Generation
// ========================================================================
function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
var sHashHex = hashFunc(s);
return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
}
function _zeroPaddingOfSignature(hex, bitLength) {
var s = "";
var nZero = bitLength / 4 - hex.length;
for (var i = 0; i < nZero; i++) {
s = s + "0";
}
return s + hex;
}
/**
* sign for a message string with RSA private key.
* @name signString
* @memberOf RSAKey
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signString(s, hashAlg) {
var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
var sHashHex = hashFunc(s);
return this.signWithMessageHash(sHashHex, hashAlg);
}
/**
* sign hash value of message to be signed with RSA private key.
* @name signWithMessageHash
* @memberOf RSAKey
* @function
* @param {String} sHashHex hexadecimal string of hash value of message to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @return returns hexadecimal string of signature value.
* @since rsasign 1.2.6
*/
function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
}
function _rsasign_signStringWithSHA1(s) {
return _rsasign_signString.call(this, s, 'sha1');
}
function _rsasign_signStringWithSHA256(s) {
return _rsasign_signString.call(this, s, 'sha256');
}
// PKCS#1 (PSS) mask generation function
function pss_mgf1_str(seed, len, hash) {
var mask = '', i = 0;
while (mask.length < len) {
mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]))));
i += 1;
}
return mask;
}
/**
* sign for a message string with RSA private key by PKCS#1 PSS signing.
* @name signStringPSS
* @memberOf RSAKey
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signStringPSS(s, hashAlg, sLen) {
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
var hHash = hashFunc(rstrtohex(s));
if (sLen === undefined) sLen = -1;
return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
}
/**
* sign hash value of message with RSA private key by PKCS#1 PSS signing.
* @name signWithMessageHashPSS
* @memberOf RSAKey
* @function
* @param {String} hHash hexadecimal hash value of message to be signed.
* @param {String} hashAlg hash algorithm name for signing.
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns hexadecimal string of signature value.
* @since rsasign 1.2.6
*/
function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
var mHash = hextorstr(hHash);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); }
if (sLen === -1 || sLen === undefined) {
sLen = hLen; // same as hash length
} else if (sLen === -2) {
sLen = emLen - hLen - 2; // maximum
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var salt = '';
if (sLen > 0) {
salt = new Array(sLen);
new SecureRandom().nextBytes(salt);
salt = String.fromCharCode.apply(String, salt);
}
var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
var PS = [];
for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
PS[i] = 0x00;
}
var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
var maskedDB = [];
for (i = 0; i < DB.length; i += 1) {
maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
maskedDB[0] &= ~mask;
for (i = 0; i < hLen; i++) {
maskedDB.push(H.charCodeAt(i));
}
maskedDB.push(0xbc);
return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
this.n.bitLength());
}
// ========================================================================
// Signature Verification
// ========================================================================
function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
var rsa = new RSAKey();
rsa.setPublic(hN, hE);
var biDecryptedSig = rsa.doPublic(biSig);
return biDecryptedSig;
}
function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
return hDigestInfo;
}
function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
var len = head.length;
if (hDigestInfo.substring(0, len) == head) {
var a = [algName, hDigestInfo.substring(len)];
return a;
}
}
return [];
}
function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
var biSig = parseBigInt(hSig, 16);
var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
this.n.toString(16),
this.e.toString(16));
return result;
}
/**
* verifies a sigature for a message string with RSA public key.
* @name verifyString
* @memberOf RSAKey#
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of siganture.
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
*/
function _rsasign_verifyString(sMsg, hSig) {
hSig = hSig.replace(_RE_HEXDECONLY, '');
hSig = hSig.replace(/[ \n]+/g, "");
var biSig = parseBigInt(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) return 0;
var biDecryptedSig = this.doPublic(biSig);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
/**
* verifies a sigature for a message string with RSA public key.
* @name verifyWithMessageHash
* @memberOf RSAKey
* @function
* @param {String} sHashHex hexadecimal hash value of message to be verified.
* @param {String} hSig hexadecimal string of siganture.
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
* @since rsasign 1.2.6
*/
function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
hSig = hSig.replace(_RE_HEXDECONLY, '');
hSig = hSig.replace(/[ \n]+/g, "");
var biSig = parseBigInt(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) return 0;
var biDecryptedSig = this.doPublic(biSig);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
return (diHashValue == sHashHex);
}
/**
* verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.
* @name verifyStringPSS
* @memberOf RSAKey
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of signature value
* @param {String} hashAlg hash algorithm name
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
* @return returns true if valid, otherwise false
*/
function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
var hHash = hashFunc(rstrtohex(sMsg));
if (sLen === undefined) sLen = -1;
return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
}
/**
* verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.
* @name verifyWithMessageHashPSS
* @memberOf RSAKey
* @function
* @param {String} hHash hexadecimal hash value of message string to be verified.
* @param {String} hSig hexadecimal string of signature value
* @param {String} hashAlg hash algorithm name
* @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
* There are two special values:
*
*
-1: sets the salt length to the digest length
*
-2: sets the salt length to maximum permissible value
* (i.e. keybytelen - hashbytelen - 2)
*
* DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
* @return returns true if valid, otherwise false
* @since rsasign 1.2.6
*/
function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
var biSig = new BigInteger(hSig, 16);
if (biSig.bitLength() > this.n.bitLength()) {
return false;
}
var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
var mHash = hextorstr(hHash);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
if (sLen === -1 || sLen === undefined) {
sLen = hLen; // same as hash length
} else if (sLen === -2) {
sLen = emLen - hLen - 2; // recover
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var em = this.doPublic(biSig).toByteArray();
for (i = 0; i < em.length; i += 1) {
em[i] &= 0xff;
}
while (em.length < emLen) {
em.unshift(0);
}
if (em[emLen -1] !== 0xbc) {
throw "encoded message does not end in 0xbc";
}
em = String.fromCharCode.apply(String, em);
var maskedDB = em.substr(0, emLen - hLen - 1);
var H = em.substr(maskedDB.length, hLen);
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
if ((maskedDB.charCodeAt(0) & mask) !== 0) {
throw "bits beyond keysize not zero";
}
var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1) {
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB[0] &= ~mask;
var checkLen = emLen - hLen - sLen - 2;
for (i = 0; i < checkLen; i += 1) {
if (DB[i] !== 0x00) {
throw "leftmost octets not zero";
}
}
if (DB[checkLen] !== 0x01) {
throw "0x01 marker not found";
}
return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
String.fromCharCode.apply(String, DB.slice(-sLen)))));
}
RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
RSAKey.prototype.signString = _rsasign_signString;
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.sign = _rsasign_signString;
RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
RSAKey.prototype.signPSS = _rsasign_signStringPSS;
RSAKey.SALT_LEN_HLEN = -1;
RSAKey.SALT_LEN_MAX = -2;
RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verify = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
RSAKey.SALT_LEN_RECOVER = -2;
/**
* @name RSAKey
* @class key of RSA public key algorithm
* @description Tom Wu's RSA Key class and extension
*/
================================================
FILE: JavaScript/sm2/js/sha1.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Reusable object
var W = [];
/**
* SHA-1 hash algorithm.
*/
var SHA1 = C_algo.SHA1 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476,
0xc3d2e1f0
]);
},
_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];
// Computation
for (var i = 0; i < 80; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = (n << 1) | (n >>> 31);
}
var t = ((a << 5) | (a >>> 27)) + e + W[i];
if (i < 20) {
t += ((b & c) | (~b & d)) + 0x5a827999;
} else if (i < 40) {
t += (b ^ c ^ d) + 0x6ed9eba1;
} else if (i < 60) {
t += ((b & c) | (b & d) | (c & d)) - 0x70e44324;
} else /* if (i < 80) */ {
t += (b ^ c ^ d) - 0x359d3e2a;
}
e = d;
d = c;
c = (b << 30) | (b >>> 2);
b = a;
a = t;
}
// 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;
},
_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.SHA1('message');
* var hash = CryptoJS.SHA1(wordArray);
*/
C.SHA1 = Hasher._createHelper(SHA1);
/**
* 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.HmacSHA1(message, key);
*/
C.HmacSHA1 = Hasher._createHmacHelper(SHA1);
}());
================================================
FILE: JavaScript/sm2/js/sha256.js
================================================
/*
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));
================================================
FILE: JavaScript/sm2/js/sm2-guomi.js
================================================
function SM2Cipher(cipherMode) {
this.ct = 1;
this.p2 = null;
this.sm3keybase = null;
this.sm3c3 = null;
this.key = new Array(32);
this.keyOff = 0;
if (typeof(cipherMode) != 'undefined') {
this.cipherMode = cipherMode
} else {
this.cipherMode = SM2CipherMode.C1C3C2
}
}
SM2Cipher.prototype = {
Reset: function() {
this.sm3keybase = new SM3Digest();
this.sm3c3 = new SM3Digest();
var xWords = this.GetWords(this.p2.getX().toBigInteger().toRadix(16));
var yWords = this.GetWords(this.p2.getY().toBigInteger().toRadix(16));
this.sm3keybase.BlockUpdate(xWords, 0, xWords.length);
this.sm3c3.BlockUpdate(xWords, 0, xWords.length);
this.sm3keybase.BlockUpdate(yWords, 0, yWords.length);
this.ct = 1;
this.NextKey()
},
NextKey: function() {
var sm3keycur = new SM3Digest(this.sm3keybase);
sm3keycur.Update((this.ct >> 24 & 0x00ff));
sm3keycur.Update((this.ct >> 16 & 0x00ff));
sm3keycur.Update((this.ct >> 8 & 0x00ff));
sm3keycur.Update((this.ct & 0x00ff));
sm3keycur.DoFinal(this.key, 0);
this.keyOff = 0;
this.ct++
},
InitEncipher: function(userKey) {
var k = null;
var c1 = null;
var ec = new KJUR.crypto.ECDSA({
"curve": "sm2"
});
var keypair = ec.generateKeyPairHex();
k = new BigInteger(keypair.ecprvhex, 16);
var pubkeyHex = keypair.ecpubhex;
c1 = ECPointFp.decodeFromHex(ec.ecparams['curve'], pubkeyHex);
this.p2 = userKey.multiply(k);
this.Reset();
return c1
},
EncryptBlock: function(data) {
this.sm3c3.BlockUpdate(data, 0, data.length);
for (var i = 0; i < data.length; i++) {
if (this.keyOff == this.key.length) {
this.NextKey()
}
data[i] ^= this.key[this.keyOff++]
}
},
InitDecipher: function(userD, c1) {
this.p2 = c1.multiply(userD);
this.Reset()
},
DecryptBlock: function(data) {
for (var i = 0; i < data.length; i++) {
if (this.keyOff == this.key.length) {
this.NextKey()
}
data[i] ^= this.key[this.keyOff++]
}
this.sm3c3.BlockUpdate(data, 0, data.length)
},
Dofinal: function(c3) {
var yWords = this.GetWords(this.p2.getY().toBigInteger().toRadix(16));
this.sm3c3.BlockUpdate(yWords, 0, yWords.length);
this.sm3c3.DoFinal(c3, 0);
this.Reset()
},
Encrypt: function(pubKey, plaintext) {
var data = new Array(plaintext.length);
Array.Copy(plaintext, 0, data, 0, plaintext.length);
var c1 = this.InitEncipher(pubKey);
this.EncryptBlock(data);
var c3 = new Array(32);
this.Dofinal(c3);
var hexString = c1.getX().toBigInteger().toRadix(16) + c1.getY().toBigInteger().toRadix(16) + this.GetHex(data).toString() + this.GetHex(c3).toString();
if (this.cipherMode == SM2CipherMode.C1C3C2) {
hexString = c1.getX().toBigInteger().toRadix(16) + c1.getY().toBigInteger().toRadix(16) + this.GetHex(c3).toString() + this.GetHex(data).toString()
}
return hexString
},
GetWords: function(hexStr) {
var words = [];
var hexStrLength = hexStr.length;
for (var i = 0; i < hexStrLength; i += 2) {
words[words.length] = parseInt(hexStr.substr(i, 2), 16)
}
return words
},
GetHex: function(arr) {
var words = [];
var j = 0;
for (var i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j]) << (24 - (i % 8) * 4);
j++
}
var wordArray = new CryptoJS.lib.WordArray.init(words, arr.length);
return wordArray
},
Decrypt: function(privateKey, ciphertext) {
var hexString = ciphertext;
var c1X = hexString.substr(0, 64);
var c1Y = hexString.substr(0 + c1X.length, 64);
var encrypData = hexString.substr(c1X.length + c1Y.length, hexString.length - c1X.length - c1Y.length - 64);
var c3 = hexString.substr(hexString.length - 64);
if (this.cipherMode == SM2CipherMode.C1C3C2) {
c3 = hexString.substr(c1X.length + c1Y.length, 64);
encrypData = hexString.substr(c1X.length + c1Y.length + 64)
}
var data = this.GetWords(encrypData);
var c1 = this.CreatePoint(c1X, c1Y);
this.InitDecipher(privateKey, c1);
this.DecryptBlock(data);
var c3_ = new Array(32);
this.Dofinal(c3_);
var isDecrypt = this.GetHex(c3_).toString() == c3;
if (isDecrypt) {
var wordArray = this.GetHex(data);
var decryptData = CryptoJS.enc.Utf8.stringify(wordArray);
return decryptData
} else {
return ''
}
},
CreatePoint: function(x, y) {
var ec = new KJUR.crypto.ECDSA({
"curve": "sm2"
});
var ecc_curve = ec.ecparams['curve'];
var pubkeyHex = '04' + x + y;
var point = ECPointFp.decodeFromHex(ec.ecparams['curve'], pubkeyHex);
return point
}
};
window.SM2CipherMode = {
C1C2C3: '0',
C1C3C2: '1'
};
================================================
FILE: JavaScript/sm2/js/sm2.js
================================================
function SM2Cipher(cipherMode){this.ct=1;this.p2=null;this.sm3keybase=null;this.sm3c3=null;this.key=new Array(32);this.keyOff=0;if(typeof(cipherMode)!='undefined'){this.cipherMode=cipherMode}else{this.cipherMode=SM2CipherMode.C1C3C2}}SM2Cipher.prototype={Reset:function(){this.sm3keybase=new SM3Digest();this.sm3c3=new SM3Digest();var xWords=this.GetWords(this.p2.getX().toBigInteger().toRadix(16));var yWords=this.GetWords(this.p2.getY().toBigInteger().toRadix(16));this.sm3keybase.BlockUpdate(xWords,0,xWords.length);this.sm3c3.BlockUpdate(xWords,0,xWords.length);this.sm3keybase.BlockUpdate(yWords,0,yWords.length);this.ct=1;this.NextKey()},NextKey:function(){var sm3keycur=new SM3Digest(this.sm3keybase);sm3keycur.Update((this.ct>>24&0x00ff));sm3keycur.Update((this.ct>>16&0x00ff));sm3keycur.Update((this.ct>>8&0x00ff));sm3keycur.Update((this.ct&0x00ff));sm3keycur.DoFinal(this.key,0);this.keyOff=0;this.ct++},InitEncipher:function(userKey){var k=null;var c1=null;var ec=new KJUR.crypto.ECDSA({"curve":"sm2"});var keypair=ec.generateKeyPairHex();k=new BigInteger(keypair.ecprvhex,16);var pubkeyHex=keypair.ecpubhex;c1=ECPointFp.decodeFromHex(ec.ecparams['curve'],pubkeyHex);this.p2=userKey.multiply(k);this.Reset();return c1},EncryptBlock:function(data){this.sm3c3.BlockUpdate(data,0,data.length);for(var i=0;i>>3]|=parseInt(arr[j])<<(24-(i%8)*4);j++}var wordArray=new CryptoJS.lib.WordArray.init(words,arr.length);return wordArray},Decrypt:function(privateKey,ciphertext){var hexString=ciphertext;var c1X=hexString.substr(0,64);var c1Y=hexString.substr(0+c1X.length,64);var encrypData=hexString.substr(c1X.length+c1Y.length,hexString.length-c1X.length-c1Y.length-64);var c3=hexString.substr(hexString.length-64);if(this.cipherMode==SM2CipherMode.C1C3C2){c3=hexString.substr(c1X.length+c1Y.length,64);encrypData=hexString.substr(c1X.length+c1Y.length+64)}var data=this.GetWords(encrypData);var c1=this.CreatePoint(c1X,c1Y);this.InitDecipher(privateKey,c1);this.DecryptBlock(data);var c3_=new Array(32);this.Dofinal(c3_);var isDecrypt=this.GetHex(c3_).toString()==c3;if(isDecrypt){var wordArray=this.GetHex(data);var decryptData=CryptoJS.enc.Utf8.stringify(wordArray);return decryptData}else{return''}},CreatePoint:function(x,y){var ec=new KJUR.crypto.ECDSA({"curve":"sm2"});var ecc_curve=ec.ecparams['curve'];var pubkeyHex='04'+x+y;var point=ECPointFp.decodeFromHex(ec.ecparams['curve'],pubkeyHex);return point}};window.SM2CipherMode={C1C2C3:'0',C1C3C2:'1'};
================================================
FILE: JavaScript/sm2/js/sm3-guomi.js
================================================
(function() {
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
var W = [];
var SM3 = C_algo.SM3 = Hasher.extend({
_doReset: function() {
this._hash = new WordArray.init([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
},
_doProcessBlock: function(M, offset) {
var H = this._hash.words;
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
for (var i = 0; i < 80; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0
} else {
var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = (n << 1) | (n >>> 31)
}
var t = ((a << 5) | (a >>> 27)) + e + W[i];
if (i < 20) {
t += ((b & c) | (~b & d)) + 0x5a827999
} else if (i < 40) {
t += (b ^ c ^ d) + 0x6ed9eba1
} else if (i < 60) {
t += ((b & c) | (b & d) | (c & d)) - 0x70e44324
} else {
t += (b ^ c ^ d) - 0x359d3e2a
}
e = d;
d = c;
c = (b << 30) | (b >>> 2);
b = a;
a = t
}
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
},
_doFinalize: function() {
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
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;
this._process();
return this._hash
},
clone: function() {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone
}
});
C.SM3 = Hasher._createHelper(SM3);
C.HmacSM3 = Hasher._createHmacHelper(SM3)
}());
function SM3Digest() {
this.BYTE_LENGTH = 64;
this.xBuf = new Array();
this.xBufOff = 0;
this.byteCount = 0;
this.DIGEST_LENGTH = 32;
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e];
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, -628488704, -1452330820, 0x163138aa, -477237683, -1325724082];
this.v = new Array(8);
this.v_ = new Array(8);
this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
this.X = new Array(68);
this.xOff = 0;
this.T_00_15 = 0x79cc4519;
this.T_16_63 = 0x7a879d8a;
if (arguments.length > 0) {
this.InitDigest(arguments[0])
} else {
this.Init()
}
}
SM3Digest.prototype = {
Init: function() {
this.xBuf = new Array(4);
this.Reset()
},
InitDigest: function(t) {
this.xBuf = new Array(t.xBuf.length);
Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
this.xBufOff = t.xBufOff;
this.byteCount = t.byteCount;
Array.Copy(t.X, 0, this.X, 0, t.X.length);
this.xOff = t.xOff;
Array.Copy(t.v, 0, this.v, 0, t.v.length)
},
GetDigestSize: function() {
return this.DIGEST_LENGTH
},
Reset: function() {
this.byteCount = 0;
this.xBufOff = 0;
Array.Clear(this.xBuf, 0, this.xBuf.length);
Array.Copy(this.v0, 0, this.v, 0, this.v0.length);
this.xOff = 0;
Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
},
GetByteLength: function() {
return this.BYTE_LENGTH
},
ProcessBlock: function() {
var i;
var ww = this.X;
var ww_ = new Array(64);
for (i = 16; i < 68; i++) {
ww[i] = this.P1(ww[i - 16] ^ ww[i - 9] ^ (this.ROTATE(ww[i - 3], 15))) ^ (this.ROTATE(ww[i - 13], 7)) ^ ww[i - 6]
}
for (i = 0; i < 64; i++) {
ww_[i] = ww[i] ^ ww[i + 4]
}
var vv = this.v;
var vv_ = this.v_;
Array.Copy(vv, 0, vv_, 0, this.v0.length);
var SS1, SS2, TT1, TT2, aaa;
for (i = 0; i < 16; i++) {
aaa = this.ROTATE(vv_[0], 12);
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_00_15, i));
SS1 = this.ROTATE(SS1, 7);
SS2 = SS1 ^ aaa;
TT1 = Int32.parse(Int32.parse(this.FF_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
TT2 = Int32.parse(Int32.parse(this.GG_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
vv_[3] = vv_[2];
vv_[2] = this.ROTATE(vv_[1], 9);
vv_[1] = vv_[0];
vv_[0] = TT1;
vv_[7] = vv_[6];
vv_[6] = this.ROTATE(vv_[5], 19);
vv_[5] = vv_[4];
vv_[4] = this.P0(TT2)
}
for (i = 16; i < 64; i++) {
aaa = this.ROTATE(vv_[0], 12);
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_16_63, i));
SS1 = this.ROTATE(SS1, 7);
SS2 = SS1 ^ aaa;
TT1 = Int32.parse(Int32.parse(this.FF_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
TT2 = Int32.parse(Int32.parse(this.GG_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
vv_[3] = vv_[2];
vv_[2] = this.ROTATE(vv_[1], 9);
vv_[1] = vv_[0];
vv_[0] = TT1;
vv_[7] = vv_[6];
vv_[6] = this.ROTATE(vv_[5], 19);
vv_[5] = vv_[4];
vv_[4] = this.P0(TT2)
}
for (i = 0; i < 8; i++) {
vv[i] ^= Int32.parse(vv_[i])
}
this.xOff = 0;
Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
},
ProcessWord: function(in_Renamed, inOff) {
var n = in_Renamed[inOff] << 24;
n |= (in_Renamed[++inOff] & 0xff) << 16;
n |= (in_Renamed[++inOff] & 0xff) << 8;
n |= (in_Renamed[++inOff] & 0xff);
this.X[this.xOff] = n;
if (++this.xOff == 16) {
this.ProcessBlock()
}
},
ProcessLength: function(bitLength) {
if (this.xOff > 14) {
this.ProcessBlock()
}
this.X[14] = (this.URShiftLong(bitLength, 32));
this.X[15] = (bitLength & (0xffffffff))
},
IntToBigEndian: function(n, bs, off) {
bs[off] = Int32.parseByte(this.URShift(n, 24));
bs[++off] = Int32.parseByte(this.URShift(n, 16));
bs[++off] = Int32.parseByte(this.URShift(n, 8));
bs[++off] = Int32.parseByte(n)
},
DoFinal: function(out_Renamed, outOff) {
this.Finish();
for (var i = 0; i < 8; i++) {
this.IntToBigEndian(this.v[i], out_Renamed, outOff + i * 4)
}
this.Reset();
return this.DIGEST_LENGTH
},
Update: function(input) {
this.xBuf[this.xBufOff++] = input;
if (this.xBufOff == this.xBuf.length) {
this.ProcessWord(this.xBuf, 0);
this.xBufOff = 0
}
this.byteCount++
},
BlockUpdate: function(input, inOff, length) {
while ((this.xBufOff != 0) && (length > 0)) {
this.Update(input[inOff]);
inOff++;
length--
}
while (length > this.xBuf.length) {
this.ProcessWord(input, inOff);
inOff += this.xBuf.length;
length -= this.xBuf.length;
this.byteCount += this.xBuf.length
}
while (length > 0) {
this.Update(input[inOff]);
inOff++;
length--
}
},
Finish: function() {
var bitLength = (this.byteCount << 3);
this.Update((128));
while (this.xBufOff != 0) this.Update((0));
this.ProcessLength(bitLength);
this.ProcessBlock()
},
ROTATE: function(x, n) {
return (x << n) | (this.URShift(x, (32 - n)))
},
P0: function(X) {
return ((X) ^ this.ROTATE((X), 9) ^ this.ROTATE((X), 17))
},
P1: function(X) {
return ((X) ^ this.ROTATE((X), 15) ^ this.ROTATE((X), 23))
},
FF_00_15: function(X, Y, Z) {
return (X ^ Y ^ Z)
},
FF_16_63: function(X, Y, Z) {
return ((X & Y) | (X & Z) | (Y & Z))
},
GG_00_15: function(X, Y, Z) {
return (X ^ Y ^ Z)
},
GG_16_63: function(X, Y, Z) {
return ((X & Y) | (~X & Z))
},
URShift: function(number, bits) {
if (number > Int32.maxValue || number < Int32.minValue) {
number = Int32.parse(number)
}
if (number >= 0) {
return number >> bits
} else {
return (number >> bits) + (2 << ~bits)
}
},
URShiftLong: function(number, bits) {
var returnV;
var big = new BigInteger();
big.fromInt(number);
if (big.signum() >= 0) {
returnV = big.shiftRight(bits).intValue()
} else {
var bigAdd = new BigInteger();
bigAdd.fromInt(2);
var shiftLeftBits = ~bits;
var shiftLeftNumber = '';
if (shiftLeftBits < 0) {
var shiftRightBits = 64 + shiftLeftBits;
for (var i = 0; i < shiftRightBits; i++) {
shiftLeftNumber += '0'
}
var shiftLeftNumberBigAdd = new BigInteger();
shiftLeftNumberBigAdd.fromInt(number >> bits);
var shiftLeftNumberBig = new BigInteger("10" + shiftLeftNumber, 2);
shiftLeftNumber = shiftLeftNumberBig.toRadix(10);
var r = shiftLeftNumberBig.add(shiftLeftNumberBigAdd);
returnV = r.toRadix(10)
} else {
shiftLeftNumber = bigAdd.shiftLeft((~bits)).intValue();
returnV = (number >> bits) + shiftLeftNumber
}
}
return returnV
},
GetZ: function(g, pubKeyHex) {
var userId = CryptoJS.enc.Utf8.parse("1234567812345678");
var len = userId.words.length * 4 * 8;
this.Update((len >> 8 & 0x00ff));
this.Update((len & 0x00ff));
var userIdWords = this.GetWords(userId.toString());
this.BlockUpdate(userIdWords, 0, userIdWords.length);
var aWords = this.GetWords(g.curve.a.toBigInteger().toRadix(16));
var bWords = this.GetWords(g.curve.b.toBigInteger().toRadix(16));
var gxWords = this.GetWords(g.getX().toBigInteger().toRadix(16));
var gyWords = this.GetWords(g.getY().toBigInteger().toRadix(16));
var pxWords = this.GetWords(pubKeyHex.substr(0, 64));
var pyWords = this.GetWords(pubKeyHex.substr(64, 64));
this.BlockUpdate(aWords, 0, aWords.length);
this.BlockUpdate(bWords, 0, bWords.length);
this.BlockUpdate(gxWords, 0, gxWords.length);
this.BlockUpdate(gyWords, 0, gyWords.length);
this.BlockUpdate(pxWords, 0, pxWords.length);
this.BlockUpdate(pyWords, 0, pyWords.length);
var md = new Array(this.GetDigestSize());
this.DoFinal(md, 0);
return md
},
GetWords: function(hexStr) {
var words = [];
var hexStrLength = hexStr.length;
for (var i = 0; i < hexStrLength; i += 2) {
words[words.length] = parseInt(hexStr.substr(i, 2), 16)
}
return words
},
GetHex: function(arr) {
var words = [];
var j = 0;
for (var i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j]) << (24 - (i % 8) * 4);
j++
}
var wordArray = new CryptoJS.lib.WordArray.init(words, arr.length);
return wordArray
}
};
Array.Clear = function(destinationArray, destinationIndex, length) {
for (elm in destinationArray) {
destinationArray[elm] = null
}
};
Array.Copy = function(sourceArray, sourceIndex, destinationArray, destinationIndex, length) {
var cloneArray = sourceArray.slice(sourceIndex, sourceIndex + length);
for (var i = 0; i < cloneArray.length; i++) {
destinationArray[destinationIndex] = cloneArray[i];
destinationIndex++
}
};
window.Int32 = {
minValue: -parseInt('10000000000000000000000000000000', 2),
maxValue: parseInt('1111111111111111111111111111111', 2),
parse: function(n) {
if (n < this.minValue) {
var bigInteger = new Number(-n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return (result + 1)
} else if (n > this.maxValue) {
var bigInteger = Number(n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return -(result + 1)
} else {
return n
}
},
parseByte: function(n) {
if (n < 0) {
var bigInteger = new Number(-n);
var bigIntegerRadix = bigInteger.toString(2);
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8);
var reBigIntegerRadix = '';
for (var i = 0; i < subBigIntegerRadix.length; i++) {
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
}
var result = parseInt(reBigIntegerRadix, 2);
return (result + 1)
} else if (n > 255) {
var bigInteger = Number(n);
var bigIntegerRadix = bigInteger.toString(2);
return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8), 2)
} else {
return n
}
}
};
================================================
FILE: JavaScript/sm2/js/sm3-sm2-1.0.js
================================================
/*! sm3-sm2-1.0.js (c) Jonllen Peng | http://www.jonllen.com/
*/
/*
* sm3-sm2-1.0.js
*
* Copyright (c) 2014 Jonllen Peng (www.jonllen.com)
*/
/**
* @fileOverview
* @name sm3-sm2-1.0.js
* @author Jonllen (www.jonllen.com)
* @version 1.0.0 (2014-06-18)
*/
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
/**
* class for SM2 key generation, sm3WithSM2 signing and verifcation
* @name KJUR.crypto.SM3withSM2
* @class class for SM2 key generation, SM2 signing and verifcation
* @description
*
* CAUTION: Most of the case, you don't need to use this class except
* for generating an SM2 key pair. Please use {@link KJUR.crypto.Signature} class instead.
*
*
* This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
* Currently this class supports following named curves and their aliases.
*
*
secp256r1, NIST P-256, P-256, prime256v1 (*)
*
secp256k1 (*)
*
secp384r1, NIST P-384, P-384 (*)
*
sm2
*
*
*/
KJUR.crypto.SM3withSM2 = function(params) {
var curveName = "sm2"; // curve name default
var ecparams = null;
var prvKeyHex = null;
var pubKeyHex = null;
var rng = new SecureRandom();
var P_OVER_FOUR = null;
this.type = "SM2";
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;
}
/**
* 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 = KJUR.crypto.ECDSA({'curve': 'sm2'});
* var keypair = ec.generateKeyPairHex();
* var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
* var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
*/
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.SM3withSM2
* @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 = KJUR.crypto.SM3withSM2({'curve': 'sm2'});
* 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);
// k BigInteger
var k = null;
var kp = null;
var r = null;
var s = null;
var userD = d;
do
{
do
{
var keypair = this.generateKeyPairHex();
k = new BigInteger(keypair.ecprvhex, 16);
var pubkeyHex = keypair.ecpubhex;
kp = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
// r
r = e.add(kp.getX().toBigInteger());
r = r.mod(n);
}
while (r.equals(BigInteger.ZERO) || r.add(k).equals(n));
// (1 + dA)~-1
var da_1 = userD.add(BigInteger.ONE);
da_1 = da_1.modInverse(n);
// s
s = r.multiply(userD);
s = k.subtract(s).mod(n);
s = da_1.multiply(s).mod(n);
}
while (s.equals(BigInteger.ZERO));
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.SM3withSM2
* @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 = KJUR.crypto.SM3withSM2({'curve': 'sm2'});
* 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'];
var t = r.add(s).mod(n);
if (t.equals(BigInteger.ZERO))
return false;
var x1y1 = G.multiply(s);
x1y1 = x1y1.add(Q.multiply(t));
var R = e.add(x1y1.getX().toBigInteger()).mod(n);
return r.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};
};
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']);
}
};
================================================
FILE: JavaScript/sm2/js/sm3.js
================================================
(function(){var C=CryptoJS;var C_lib=C.lib;var WordArray=C_lib.WordArray;var Hasher=C_lib.Hasher;var C_algo=C.algo;var W=[];var SM3=C_algo.SM3=Hasher.extend({_doReset:function(){this._hash=new WordArray.init([0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e])},_doProcessBlock:function(M,offset){var H=this._hash.words;var a=H[0];var b=H[1];var c=H[2];var d=H[3];var e=H[4];for(var i=0;i<80;i++){if(i<16){W[i]=M[offset+i]|0}else{var n=W[i-3]^W[i-8]^W[i-14]^W[i-16];W[i]=(n<<1)|(n>>>31)}var t=((a<<5)|(a>>>27))+e+W[i];if(i<20){t+=((b&c)|(~b&d))+0x5a827999}else if(i<40){t+=(b^c^d)+0x6ed9eba1}else if(i<60){t+=((b&c)|(b&d)|(c&d))-0x70e44324}else{t+=(b^c^d)-0x359d3e2a}e=d;d=c;c=(b<<30)|(b>>>2);b=a;a=t}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},_doFinalize:function(){var data=this._data;var dataWords=data.words;var nBitsTotal=this._nDataBytes*8;var nBitsLeft=data.sigBytes*8;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;this._process();return this._hash},clone:function(){var clone=Hasher.clone.call(this);clone._hash=this._hash.clone();return clone}});C.SM3=Hasher._createHelper(SM3);C.HmacSM3=Hasher._createHmacHelper(SM3)}());function SM3Digest(){this.BYTE_LENGTH=64;this.xBuf=new Array();this.xBufOff=0;this.byteCount=0;this.DIGEST_LENGTH=32;this.v0=[0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e];this.v0=[0x7380166f,0x4914b2b9,0x172442d7,-628488704,-1452330820,0x163138aa,-477237683,-1325724082];this.v=new Array(8);this.v_=new Array(8);this.X0=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.X=new Array(68);this.xOff=0;this.T_00_15=0x79cc4519;this.T_16_63=0x7a879d8a;if(arguments.length>0){this.InitDigest(arguments[0])}else{this.Init()}}SM3Digest.prototype={Init:function(){this.xBuf=new Array(4);this.Reset()},InitDigest:function(t){this.xBuf=new Array(t.xBuf.length);Array.Copy(t.xBuf,0,this.xBuf,0,t.xBuf.length);this.xBufOff=t.xBufOff;this.byteCount=t.byteCount;Array.Copy(t.X,0,this.X,0,t.X.length);this.xOff=t.xOff;Array.Copy(t.v,0,this.v,0,t.v.length)},GetDigestSize:function(){return this.DIGEST_LENGTH},Reset:function(){this.byteCount=0;this.xBufOff=0;Array.Clear(this.xBuf,0,this.xBuf.length);Array.Copy(this.v0,0,this.v,0,this.v0.length);this.xOff=0;Array.Copy(this.X0,0,this.X,0,this.X0.length)},GetByteLength:function(){return this.BYTE_LENGTH},ProcessBlock:function(){var i;var ww=this.X;var ww_=new Array(64);for(i=16;i<68;i++){ww[i]=this.P1(ww[i-16]^ww[i-9]^(this.ROTATE(ww[i-3],15)))^(this.ROTATE(ww[i-13],7))^ww[i-6]}for(i=0;i<64;i++){ww_[i]=ww[i]^ww[i+4]}var vv=this.v;var vv_=this.v_;Array.Copy(vv,0,vv_,0,this.v0.length);var SS1,SS2,TT1,TT2,aaa;for(i=0;i<16;i++){aaa=this.ROTATE(vv_[0],12);SS1=Int32.parse(Int32.parse(aaa+vv_[4])+this.ROTATE(this.T_00_15,i));SS1=this.ROTATE(SS1,7);SS2=SS1^aaa;TT1=Int32.parse(Int32.parse(this.FF_00_15(vv_[0],vv_[1],vv_[2])+vv_[3])+SS2)+ww_[i];TT2=Int32.parse(Int32.parse(this.GG_00_15(vv_[4],vv_[5],vv_[6])+vv_[7])+SS1)+ww[i];vv_[3]=vv_[2];vv_[2]=this.ROTATE(vv_[1],9);vv_[1]=vv_[0];vv_[0]=TT1;vv_[7]=vv_[6];vv_[6]=this.ROTATE(vv_[5],19);vv_[5]=vv_[4];vv_[4]=this.P0(TT2)}for(i=16;i<64;i++){aaa=this.ROTATE(vv_[0],12);SS1=Int32.parse(Int32.parse(aaa+vv_[4])+this.ROTATE(this.T_16_63,i));SS1=this.ROTATE(SS1,7);SS2=SS1^aaa;TT1=Int32.parse(Int32.parse(this.FF_16_63(vv_[0],vv_[1],vv_[2])+vv_[3])+SS2)+ww_[i];TT2=Int32.parse(Int32.parse(this.GG_16_63(vv_[4],vv_[5],vv_[6])+vv_[7])+SS1)+ww[i];vv_[3]=vv_[2];vv_[2]=this.ROTATE(vv_[1],9);vv_[1]=vv_[0];vv_[0]=TT1;vv_[7]=vv_[6];vv_[6]=this.ROTATE(vv_[5],19);vv_[5]=vv_[4];vv_[4]=this.P0(TT2)}for(i=0;i<8;i++){vv[i]^=Int32.parse(vv_[i])}this.xOff=0;Array.Copy(this.X0,0,this.X,0,this.X0.length)},ProcessWord:function(in_Renamed,inOff){var n=in_Renamed[inOff]<<24;n|=(in_Renamed[++inOff]&0xff)<<16;n|=(in_Renamed[++inOff]&0xff)<<8;n|=(in_Renamed[++inOff]&0xff);this.X[this.xOff]=n;if(++this.xOff==16){this.ProcessBlock()}},ProcessLength:function(bitLength){if(this.xOff>14){this.ProcessBlock()}this.X[14]=(this.URShiftLong(bitLength,32));this.X[15]=(bitLength&(0xffffffff))},IntToBigEndian:function(n,bs,off){bs[off]=Int32.parseByte(this.URShift(n,24));bs[++off]=Int32.parseByte(this.URShift(n,16));bs[++off]=Int32.parseByte(this.URShift(n,8));bs[++off]=Int32.parseByte(n)},DoFinal:function(out_Renamed,outOff){this.Finish();for(var i=0;i<8;i++){this.IntToBigEndian(this.v[i],out_Renamed,outOff+i*4)}this.Reset();return this.DIGEST_LENGTH},Update:function(input){this.xBuf[this.xBufOff++]=input;if(this.xBufOff==this.xBuf.length){this.ProcessWord(this.xBuf,0);this.xBufOff=0}this.byteCount++},BlockUpdate:function(input,inOff,length){while((this.xBufOff!=0)&&(length>0)){this.Update(input[inOff]);inOff++;length--}while(length>this.xBuf.length){this.ProcessWord(input,inOff);inOff+=this.xBuf.length;length-=this.xBuf.length;this.byteCount+=this.xBuf.length}while(length>0){this.Update(input[inOff]);inOff++;length--}},Finish:function(){var bitLength=(this.byteCount<<3);this.Update((128));while(this.xBufOff!=0)this.Update((0));this.ProcessLength(bitLength);this.ProcessBlock()},ROTATE:function(x,n){return(x<Int32.maxValue||number=0){return number>>bits}else{return(number>>bits)+(2<<~bits)}},URShiftLong:function(number,bits){var returnV;var big=new BigInteger();big.fromInt(number);if(big.signum()>=0){returnV=big.shiftRight(bits).intValue()}else{var bigAdd=new BigInteger();bigAdd.fromInt(2);var shiftLeftBits=~bits;var shiftLeftNumber='';if(shiftLeftBits<0){var shiftRightBits=64+shiftLeftBits;for(var i=0;i>bits);var shiftLeftNumberBig=new BigInteger("10"+shiftLeftNumber,2);shiftLeftNumber=shiftLeftNumberBig.toRadix(10);var r=shiftLeftNumberBig.add(shiftLeftNumberBigAdd);returnV=r.toRadix(10)}else{shiftLeftNumber=bigAdd.shiftLeft((~bits)).intValue();returnV=(number>>bits)+shiftLeftNumber}}return returnV},GetZ:function(g,pubKeyHex){var userId=CryptoJS.enc.Utf8.parse("1234567812345678");var len=userId.words.length*4*8;this.Update((len>>8&0x00ff));this.Update((len&0x00ff));var userIdWords=this.GetWords(userId.toString());this.BlockUpdate(userIdWords,0,userIdWords.length);var aWords=this.GetWords(g.curve.a.toBigInteger().toRadix(16));var bWords=this.GetWords(g.curve.b.toBigInteger().toRadix(16));var gxWords=this.GetWords(g.getX().toBigInteger().toRadix(16));var gyWords=this.GetWords(g.getY().toBigInteger().toRadix(16));var pxWords=this.GetWords(pubKeyHex.substr(0,64));var pyWords=this.GetWords(pubKeyHex.substr(64,64));this.BlockUpdate(aWords,0,aWords.length);this.BlockUpdate(bWords,0,bWords.length);this.BlockUpdate(gxWords,0,gxWords.length);this.BlockUpdate(gyWords,0,gyWords.length);this.BlockUpdate(pxWords,0,pxWords.length);this.BlockUpdate(pyWords,0,pyWords.length);var md=new Array(this.GetDigestSize());this.DoFinal(md,0);return md},GetWords:function(hexStr){var words=[];var hexStrLength=hexStr.length;for(var i=0;i>>3]|=parseInt(arr[j])<<(24-(i%8)*4);j++}var wordArray=new CryptoJS.lib.WordArray.init(words,arr.length);return wordArray}};Array.Clear=function(destinationArray,destinationIndex,length){for(elm in destinationArray){destinationArray[elm]=null}};Array.Copy=function(sourceArray,sourceIndex,destinationArray,destinationIndex,length){var cloneArray=sourceArray.slice(sourceIndex,sourceIndex+length);for(var i=0;ithis.maxValue){var bigInteger=Number(n);var bigIntegerRadix=bigInteger.toString(2);var subBigIntegerRadix=bigIntegerRadix.substr(bigIntegerRadix.length-31,31);var reBigIntegerRadix='';for(var i=0;i255){var bigInteger=Number(n);var bigIntegerRadix=bigInteger.toString(2);return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length-8,8),2)}else{return n}}};
================================================
FILE: JavaScript/sm2/js/tripledes.js
================================================
/*
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 () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var BlockCipher = C_lib.BlockCipher;
var C_algo = C.algo;
// Permuted Choice 1 constants
var PC1 = [
57, 49, 41, 33, 25, 17, 9, 1,
58, 50, 42, 34, 26, 18, 10, 2,
59, 51, 43, 35, 27, 19, 11, 3,
60, 52, 44, 36, 63, 55, 47, 39,
31, 23, 15, 7, 62, 54, 46, 38,
30, 22, 14, 6, 61, 53, 45, 37,
29, 21, 13, 5, 28, 20, 12, 4
];
// Permuted Choice 2 constants
var PC2 = [
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
];
// Cumulative bit shift constants
var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28];
// SBOXes and round permutation constants
var SBOX_P = [
{
0x0: 0x808200,
0x10000000: 0x8000,
0x20000000: 0x808002,
0x30000000: 0x2,
0x40000000: 0x200,
0x50000000: 0x808202,
0x60000000: 0x800202,
0x70000000: 0x800000,
0x80000000: 0x202,
0x90000000: 0x800200,
0xa0000000: 0x8200,
0xb0000000: 0x808000,
0xc0000000: 0x8002,
0xd0000000: 0x800002,
0xe0000000: 0x0,
0xf0000000: 0x8202,
0x8000000: 0x0,
0x18000000: 0x808202,
0x28000000: 0x8202,
0x38000000: 0x8000,
0x48000000: 0x808200,
0x58000000: 0x200,
0x68000000: 0x808002,
0x78000000: 0x2,
0x88000000: 0x800200,
0x98000000: 0x8200,
0xa8000000: 0x808000,
0xb8000000: 0x800202,
0xc8000000: 0x800002,
0xd8000000: 0x8002,
0xe8000000: 0x202,
0xf8000000: 0x800000,
0x1: 0x8000,
0x10000001: 0x2,
0x20000001: 0x808200,
0x30000001: 0x800000,
0x40000001: 0x808002,
0x50000001: 0x8200,
0x60000001: 0x200,
0x70000001: 0x800202,
0x80000001: 0x808202,
0x90000001: 0x808000,
0xa0000001: 0x800002,
0xb0000001: 0x8202,
0xc0000001: 0x202,
0xd0000001: 0x800200,
0xe0000001: 0x8002,
0xf0000001: 0x0,
0x8000001: 0x808202,
0x18000001: 0x808000,
0x28000001: 0x800000,
0x38000001: 0x200,
0x48000001: 0x8000,
0x58000001: 0x800002,
0x68000001: 0x2,
0x78000001: 0x8202,
0x88000001: 0x8002,
0x98000001: 0x800202,
0xa8000001: 0x202,
0xb8000001: 0x808200,
0xc8000001: 0x800200,
0xd8000001: 0x0,
0xe8000001: 0x8200,
0xf8000001: 0x808002
},
{
0x0: 0x40084010,
0x1000000: 0x4000,
0x2000000: 0x80000,
0x3000000: 0x40080010,
0x4000000: 0x40000010,
0x5000000: 0x40084000,
0x6000000: 0x40004000,
0x7000000: 0x10,
0x8000000: 0x84000,
0x9000000: 0x40004010,
0xa000000: 0x40000000,
0xb000000: 0x84010,
0xc000000: 0x80010,
0xd000000: 0x0,
0xe000000: 0x4010,
0xf000000: 0x40080000,
0x800000: 0x40004000,
0x1800000: 0x84010,
0x2800000: 0x10,
0x3800000: 0x40004010,
0x4800000: 0x40084010,
0x5800000: 0x40000000,
0x6800000: 0x80000,
0x7800000: 0x40080010,
0x8800000: 0x80010,
0x9800000: 0x0,
0xa800000: 0x4000,
0xb800000: 0x40080000,
0xc800000: 0x40000010,
0xd800000: 0x84000,
0xe800000: 0x40084000,
0xf800000: 0x4010,
0x10000000: 0x0,
0x11000000: 0x40080010,
0x12000000: 0x40004010,
0x13000000: 0x40084000,
0x14000000: 0x40080000,
0x15000000: 0x10,
0x16000000: 0x84010,
0x17000000: 0x4000,
0x18000000: 0x4010,
0x19000000: 0x80000,
0x1a000000: 0x80010,
0x1b000000: 0x40000010,
0x1c000000: 0x84000,
0x1d000000: 0x40004000,
0x1e000000: 0x40000000,
0x1f000000: 0x40084010,
0x10800000: 0x84010,
0x11800000: 0x80000,
0x12800000: 0x40080000,
0x13800000: 0x4000,
0x14800000: 0x40004000,
0x15800000: 0x40084010,
0x16800000: 0x10,
0x17800000: 0x40000000,
0x18800000: 0x40084000,
0x19800000: 0x40000010,
0x1a800000: 0x40004010,
0x1b800000: 0x80010,
0x1c800000: 0x0,
0x1d800000: 0x4010,
0x1e800000: 0x40080010,
0x1f800000: 0x84000
},
{
0x0: 0x104,
0x100000: 0x0,
0x200000: 0x4000100,
0x300000: 0x10104,
0x400000: 0x10004,
0x500000: 0x4000004,
0x600000: 0x4010104,
0x700000: 0x4010000,
0x800000: 0x4000000,
0x900000: 0x4010100,
0xa00000: 0x10100,
0xb00000: 0x4010004,
0xc00000: 0x4000104,
0xd00000: 0x10000,
0xe00000: 0x4,
0xf00000: 0x100,
0x80000: 0x4010100,
0x180000: 0x4010004,
0x280000: 0x0,
0x380000: 0x4000100,
0x480000: 0x4000004,
0x580000: 0x10000,
0x680000: 0x10004,
0x780000: 0x104,
0x880000: 0x4,
0x980000: 0x100,
0xa80000: 0x4010000,
0xb80000: 0x10104,
0xc80000: 0x10100,
0xd80000: 0x4000104,
0xe80000: 0x4010104,
0xf80000: 0x4000000,
0x1000000: 0x4010100,
0x1100000: 0x10004,
0x1200000: 0x10000,
0x1300000: 0x4000100,
0x1400000: 0x100,
0x1500000: 0x4010104,
0x1600000: 0x4000004,
0x1700000: 0x0,
0x1800000: 0x4000104,
0x1900000: 0x4000000,
0x1a00000: 0x4,
0x1b00000: 0x10100,
0x1c00000: 0x4010000,
0x1d00000: 0x104,
0x1e00000: 0x10104,
0x1f00000: 0x4010004,
0x1080000: 0x4000000,
0x1180000: 0x104,
0x1280000: 0x4010100,
0x1380000: 0x0,
0x1480000: 0x10004,
0x1580000: 0x4000100,
0x1680000: 0x100,
0x1780000: 0x4010004,
0x1880000: 0x10000,
0x1980000: 0x4010104,
0x1a80000: 0x10104,
0x1b80000: 0x4000004,
0x1c80000: 0x4000104,
0x1d80000: 0x4010000,
0x1e80000: 0x4,
0x1f80000: 0x10100
},
{
0x0: 0x80401000,
0x10000: 0x80001040,
0x20000: 0x401040,
0x30000: 0x80400000,
0x40000: 0x0,
0x50000: 0x401000,
0x60000: 0x80000040,
0x70000: 0x400040,
0x80000: 0x80000000,
0x90000: 0x400000,
0xa0000: 0x40,
0xb0000: 0x80001000,
0xc0000: 0x80400040,
0xd0000: 0x1040,
0xe0000: 0x1000,
0xf0000: 0x80401040,
0x8000: 0x80001040,
0x18000: 0x40,
0x28000: 0x80400040,
0x38000: 0x80001000,
0x48000: 0x401000,
0x58000: 0x80401040,
0x68000: 0x0,
0x78000: 0x80400000,
0x88000: 0x1000,
0x98000: 0x80401000,
0xa8000: 0x400000,
0xb8000: 0x1040,
0xc8000: 0x80000000,
0xd8000: 0x400040,
0xe8000: 0x401040,
0xf8000: 0x80000040,
0x100000: 0x400040,
0x110000: 0x401000,
0x120000: 0x80000040,
0x130000: 0x0,
0x140000: 0x1040,
0x150000: 0x80400040,
0x160000: 0x80401000,
0x170000: 0x80001040,
0x180000: 0x80401040,
0x190000: 0x80000000,
0x1a0000: 0x80400000,
0x1b0000: 0x401040,
0x1c0000: 0x80001000,
0x1d0000: 0x400000,
0x1e0000: 0x40,
0x1f0000: 0x1000,
0x108000: 0x80400000,
0x118000: 0x80401040,
0x128000: 0x0,
0x138000: 0x401000,
0x148000: 0x400040,
0x158000: 0x80000000,
0x168000: 0x80001040,
0x178000: 0x40,
0x188000: 0x80000040,
0x198000: 0x1000,
0x1a8000: 0x80001000,
0x1b8000: 0x80400040,
0x1c8000: 0x1040,
0x1d8000: 0x80401000,
0x1e8000: 0x400000,
0x1f8000: 0x401040
},
{
0x0: 0x80,
0x1000: 0x1040000,
0x2000: 0x40000,
0x3000: 0x20000000,
0x4000: 0x20040080,
0x5000: 0x1000080,
0x6000: 0x21000080,
0x7000: 0x40080,
0x8000: 0x1000000,
0x9000: 0x20040000,
0xa000: 0x20000080,
0xb000: 0x21040080,
0xc000: 0x21040000,
0xd000: 0x0,
0xe000: 0x1040080,
0xf000: 0x21000000,
0x800: 0x1040080,
0x1800: 0x21000080,
0x2800: 0x80,
0x3800: 0x1040000,
0x4800: 0x40000,
0x5800: 0x20040080,
0x6800: 0x21040000,
0x7800: 0x20000000,
0x8800: 0x20040000,
0x9800: 0x0,
0xa800: 0x21040080,
0xb800: 0x1000080,
0xc800: 0x20000080,
0xd800: 0x21000000,
0xe800: 0x1000000,
0xf800: 0x40080,
0x10000: 0x40000,
0x11000: 0x80,
0x12000: 0x20000000,
0x13000: 0x21000080,
0x14000: 0x1000080,
0x15000: 0x21040000,
0x16000: 0x20040080,
0x17000: 0x1000000,
0x18000: 0x21040080,
0x19000: 0x21000000,
0x1a000: 0x1040000,
0x1b000: 0x20040000,
0x1c000: 0x40080,
0x1d000: 0x20000080,
0x1e000: 0x0,
0x1f000: 0x1040080,
0x10800: 0x21000080,
0x11800: 0x1000000,
0x12800: 0x1040000,
0x13800: 0x20040080,
0x14800: 0x20000000,
0x15800: 0x1040080,
0x16800: 0x80,
0x17800: 0x21040000,
0x18800: 0x40080,
0x19800: 0x21040080,
0x1a800: 0x0,
0x1b800: 0x21000000,
0x1c800: 0x1000080,
0x1d800: 0x40000,
0x1e800: 0x20040000,
0x1f800: 0x20000080
},
{
0x0: 0x10000008,
0x100: 0x2000,
0x200: 0x10200000,
0x300: 0x10202008,
0x400: 0x10002000,
0x500: 0x200000,
0x600: 0x200008,
0x700: 0x10000000,
0x800: 0x0,
0x900: 0x10002008,
0xa00: 0x202000,
0xb00: 0x8,
0xc00: 0x10200008,
0xd00: 0x202008,
0xe00: 0x2008,
0xf00: 0x10202000,
0x80: 0x10200000,
0x180: 0x10202008,
0x280: 0x8,
0x380: 0x200000,
0x480: 0x202008,
0x580: 0x10000008,
0x680: 0x10002000,
0x780: 0x2008,
0x880: 0x200008,
0x980: 0x2000,
0xa80: 0x10002008,
0xb80: 0x10200008,
0xc80: 0x0,
0xd80: 0x10202000,
0xe80: 0x202000,
0xf80: 0x10000000,
0x1000: 0x10002000,
0x1100: 0x10200008,
0x1200: 0x10202008,
0x1300: 0x2008,
0x1400: 0x200000,
0x1500: 0x10000000,
0x1600: 0x10000008,
0x1700: 0x202000,
0x1800: 0x202008,
0x1900: 0x0,
0x1a00: 0x8,
0x1b00: 0x10200000,
0x1c00: 0x2000,
0x1d00: 0x10002008,
0x1e00: 0x10202000,
0x1f00: 0x200008,
0x1080: 0x8,
0x1180: 0x202000,
0x1280: 0x200000,
0x1380: 0x10000008,
0x1480: 0x10002000,
0x1580: 0x2008,
0x1680: 0x10202008,
0x1780: 0x10200000,
0x1880: 0x10202000,
0x1980: 0x10200008,
0x1a80: 0x2000,
0x1b80: 0x202008,
0x1c80: 0x200008,
0x1d80: 0x0,
0x1e80: 0x10000000,
0x1f80: 0x10002008
},
{
0x0: 0x100000,
0x10: 0x2000401,
0x20: 0x400,
0x30: 0x100401,
0x40: 0x2100401,
0x50: 0x0,
0x60: 0x1,
0x70: 0x2100001,
0x80: 0x2000400,
0x90: 0x100001,
0xa0: 0x2000001,
0xb0: 0x2100400,
0xc0: 0x2100000,
0xd0: 0x401,
0xe0: 0x100400,
0xf0: 0x2000000,
0x8: 0x2100001,
0x18: 0x0,
0x28: 0x2000401,
0x38: 0x2100400,
0x48: 0x100000,
0x58: 0x2000001,
0x68: 0x2000000,
0x78: 0x401,
0x88: 0x100401,
0x98: 0x2000400,
0xa8: 0x2100000,
0xb8: 0x100001,
0xc8: 0x400,
0xd8: 0x2100401,
0xe8: 0x1,
0xf8: 0x100400,
0x100: 0x2000000,
0x110: 0x100000,
0x120: 0x2000401,
0x130: 0x2100001,
0x140: 0x100001,
0x150: 0x2000400,
0x160: 0x2100400,
0x170: 0x100401,
0x180: 0x401,
0x190: 0x2100401,
0x1a0: 0x100400,
0x1b0: 0x1,
0x1c0: 0x0,
0x1d0: 0x2100000,
0x1e0: 0x2000001,
0x1f0: 0x400,
0x108: 0x100400,
0x118: 0x2000401,
0x128: 0x2100001,
0x138: 0x1,
0x148: 0x2000000,
0x158: 0x100000,
0x168: 0x401,
0x178: 0x2100400,
0x188: 0x2000001,
0x198: 0x2100000,
0x1a8: 0x0,
0x1b8: 0x2100401,
0x1c8: 0x100401,
0x1d8: 0x400,
0x1e8: 0x2000400,
0x1f8: 0x100001
},
{
0x0: 0x8000820,
0x1: 0x20000,
0x2: 0x8000000,
0x3: 0x20,
0x4: 0x20020,
0x5: 0x8020820,
0x6: 0x8020800,
0x7: 0x800,
0x8: 0x8020000,
0x9: 0x8000800,
0xa: 0x20800,
0xb: 0x8020020,
0xc: 0x820,
0xd: 0x0,
0xe: 0x8000020,
0xf: 0x20820,
0x80000000: 0x800,
0x80000001: 0x8020820,
0x80000002: 0x8000820,
0x80000003: 0x8000000,
0x80000004: 0x8020000,
0x80000005: 0x20800,
0x80000006: 0x20820,
0x80000007: 0x20,
0x80000008: 0x8000020,
0x80000009: 0x820,
0x8000000a: 0x20020,
0x8000000b: 0x8020800,
0x8000000c: 0x0,
0x8000000d: 0x8020020,
0x8000000e: 0x8000800,
0x8000000f: 0x20000,
0x10: 0x20820,
0x11: 0x8020800,
0x12: 0x20,
0x13: 0x800,
0x14: 0x8000800,
0x15: 0x8000020,
0x16: 0x8020020,
0x17: 0x20000,
0x18: 0x0,
0x19: 0x20020,
0x1a: 0x8020000,
0x1b: 0x8000820,
0x1c: 0x8020820,
0x1d: 0x20800,
0x1e: 0x820,
0x1f: 0x8000000,
0x80000010: 0x20000,
0x80000011: 0x800,
0x80000012: 0x8020020,
0x80000013: 0x20820,
0x80000014: 0x20,
0x80000015: 0x8020000,
0x80000016: 0x8000000,
0x80000017: 0x8000820,
0x80000018: 0x8020820,
0x80000019: 0x8000020,
0x8000001a: 0x8000800,
0x8000001b: 0x0,
0x8000001c: 0x20800,
0x8000001d: 0x820,
0x8000001e: 0x20020,
0x8000001f: 0x8020800
}
];
// Masks that select the SBOX input
var SBOX_MASK = [
0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000,
0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f
];
/**
* DES block cipher algorithm.
*/
var DES = C_algo.DES = BlockCipher.extend({
_doReset: function () {
// Shortcuts
var key = this._key;
var keyWords = key.words;
// Select 56 bits according to PC1
var keyBits = [];
for (var i = 0; i < 56; i++) {
var keyBitPos = PC1[i] - 1;
keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1;
}
// Assemble 16 subkeys
var subKeys = this._subKeys = [];
for (var nSubKey = 0; nSubKey < 16; nSubKey++) {
// Create subkey
var subKey = subKeys[nSubKey] = [];
// Shortcut
var bitShift = BIT_SHIFTS[nSubKey];
// Select 48 bits according to PC2
for (var i = 0; i < 24; i++) {
// Select from the left 28 key bits
subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6);
// Select from the right 28 key bits
subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6);
}
// Since each subkey is applied to an expanded 32-bit input,
// the subkey can be broken into 8 values scaled to 32-bits,
// which allows the key to be used without expansion
subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31);
for (var i = 1; i < 7; i++) {
subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3);
}
subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27);
}
// Compute inverse subkeys
var invSubKeys = this._invSubKeys = [];
for (var i = 0; i < 16; i++) {
invSubKeys[i] = subKeys[15 - i];
}
},
encryptBlock: function (M, offset) {
this._doCryptBlock(M, offset, this._subKeys);
},
decryptBlock: function (M, offset) {
this._doCryptBlock(M, offset, this._invSubKeys);
},
_doCryptBlock: function (M, offset, subKeys) {
// Get input
this._lBlock = M[offset];
this._rBlock = M[offset + 1];
// Initial permutation
exchangeLR.call(this, 4, 0x0f0f0f0f);
exchangeLR.call(this, 16, 0x0000ffff);
exchangeRL.call(this, 2, 0x33333333);
exchangeRL.call(this, 8, 0x00ff00ff);
exchangeLR.call(this, 1, 0x55555555);
// Rounds
for (var round = 0; round < 16; round++) {
// Shortcuts
var subKey = subKeys[round];
var lBlock = this._lBlock;
var rBlock = this._rBlock;
// Feistel function
var f = 0;
for (var i = 0; i < 8; i++) {
f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0];
}
this._lBlock = rBlock;
this._rBlock = lBlock ^ f;
}
// Undo swap from last round
var t = this._lBlock;
this._lBlock = this._rBlock;
this._rBlock = t;
// Final permutation
exchangeLR.call(this, 1, 0x55555555);
exchangeRL.call(this, 8, 0x00ff00ff);
exchangeRL.call(this, 2, 0x33333333);
exchangeLR.call(this, 16, 0x0000ffff);
exchangeLR.call(this, 4, 0x0f0f0f0f);
// Set output
M[offset] = this._lBlock;
M[offset + 1] = this._rBlock;
},
keySize: 64/32,
ivSize: 64/32,
blockSize: 64/32
});
// Swap bits across the left and right words
function exchangeLR(offset, mask) {
var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask;
this._rBlock ^= t;
this._lBlock ^= t << offset;
}
function exchangeRL(offset, mask) {
var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask;
this._lBlock ^= t;
this._rBlock ^= t << offset;
}
/**
* Shortcut functions to the cipher's object interface.
*
* @example
*
* var ciphertext = CryptoJS.DES.encrypt(message, key, cfg);
* var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg);
*/
C.DES = BlockCipher._createHelper(DES);
/**
* Triple-DES block cipher algorithm.
*/
var TripleDES = C_algo.TripleDES = BlockCipher.extend({
_doReset: function () {
// Shortcuts
var key = this._key;
var keyWords = key.words;
// Create DES instances
this._des1 = DES.createEncryptor(WordArray.create(keyWords.slice(0, 2)));
this._des2 = DES.createEncryptor(WordArray.create(keyWords.slice(2, 4)));
this._des3 = DES.createEncryptor(WordArray.create(keyWords.slice(4, 6)));
},
encryptBlock: function (M, offset) {
this._des1.encryptBlock(M, offset);
this._des2.decryptBlock(M, offset);
this._des3.encryptBlock(M, offset);
},
decryptBlock: function (M, offset) {
this._des3.decryptBlock(M, offset);
this._des2.encryptBlock(M, offset);
this._des1.decryptBlock(M, offset);
},
keySize: 192/32,
ivSize: 64/32,
blockSize: 64/32
});
/**
* Shortcut functions to the cipher's object interface.
*
* @example
*
* var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg);
* var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg);
*/
C.TripleDES = BlockCipher._createHelper(TripleDES);
}());
================================================
FILE: JavaScript/sm2/js/x509-1.1.js
================================================
/*! x509-1.1.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* x509.js - X509 class to read subject public key from certificate.
*
* Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name x509-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version x509 1.1.2 (2013-Oct-06)
* @since jsrsasign 1.x.x
* @license MIT License
*/
/*
* Depends:
* base64.js
* rsa.js
* asn1hex.js
*/
/**
* X.509 certificate class.
* @class X.509 certificate class
* @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
* @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
* @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
* @property {String} hex hexacedimal string for X.509 certificate.
* @author Kenji Urushima
* @version 1.0.1 (08 May 2012)
* @see 'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/
*/
function X509() {
this.subjectPublicKeyRSA = null;
this.subjectPublicKeyRSA_hN = null;
this.subjectPublicKeyRSA_hE = null;
this.hex = null;
// ===== get basic fields from hex =====================================
/**
* get hexadecimal string of serialNumber field of certificate.
* @name getSerialNumberHex
* @memberOf X509#
* @function
*/
this.getSerialNumberHex = function() {
return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
};
/**
* get hexadecimal string of issuer field of certificate.
* @name getIssuerHex
* @memberOf X509#
* @function
*/
this.getIssuerHex = function() {
return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
};
/**
* get string of issuer field of certificate.
* @name getIssuerString
* @memberOf X509#
* @function
*/
this.getIssuerString = function() {
return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
};
/**
* get hexadecimal string of subject field of certificate.
* @name getSubjectHex
* @memberOf X509#
* @function
*/
this.getSubjectHex = function() {
return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
};
/**
* get string of subject field of certificate.
* @name getSubjectString
* @memberOf X509#
* @function
*/
this.getSubjectString = function() {
return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
};
/**
* get notBefore field string of certificate.
* @name getNotBefore
* @memberOf X509#
* @function
*/
this.getNotBefore = function() {
var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
s = s.replace(/(..)/g, "%$1");
s = decodeURIComponent(s);
return s;
};
/**
* get notAfter field string of certificate.
* @name getNotAfter
* @memberOf X509#
* @function
*/
this.getNotAfter = function() {
var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
s = s.replace(/(..)/g, "%$1");
s = decodeURIComponent(s);
return s;
};
// ===== read certificate public key ==========================
// ===== read certificate =====================================
/**
* read PEM formatted X.509 certificate from string.
* @name readCertPEM
* @memberOf X509#
* @function
* @param {String} sCertPEM string for PEM formatted X.509 certificate
*/
this.readCertPEM = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
var rsa = new RSAKey();
rsa.setPublic(a[0], a[1]);
this.subjectPublicKeyRSA = rsa;
this.subjectPublicKeyRSA_hN = a[0];
this.subjectPublicKeyRSA_hE = a[1];
this.hex = hCert;
};
this.readCertPEMWithoutRSAInit = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
this.subjectPublicKeyRSA_hN = a[0];
this.subjectPublicKeyRSA_hE = a[1];
this.hex = hCert;
};
};
X509.pemToBase64 = function(sCertPEM) {
var s = sCertPEM;
s = s.replace("-----BEGIN CERTIFICATE-----", "");
s = s.replace("-----END CERTIFICATE-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
};
X509.pemToHex = function(sCertPEM) {
var b64Cert = X509.pemToBase64(sCertPEM);
var hCert = b64tohex(b64Cert);
return hCert;
};
// NOTE: Without BITSTRING encapsulation.
X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
var pInfo = X509.getSubjectPublicKeyInfoPosFromCertHex(hCert);
if (pInfo == -1) return -1;
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo);
if (a.length != 2) return -1;
var pBitString = a[1];
if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
return pBitStringV + 2;
};
// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
// NOTE: v1 and v3 supported
X509.getSubjectPublicKeyInfoPosFromCertHex = function(hCert) {
var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert);
if (a.length < 1) return -1;
if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
if (a.length < 6) return -1;
return a[6];
} else {
if (a.length < 5) return -1;
return a[5];
}
};
X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
if (a.length != 2) return [];
var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
if (hN != null && hE != null) {
return [hN, hE];
} else {
return [];
}
};
X509.getHexTbsCertificateFromCert = function(hCert) {
var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
return pTbsCert;
};
X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
var hCert = X509.pemToHex(sCertPEM);
var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
return a;
};
X509.hex2dn = function(hDN) {
var s = "";
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
for (var i = 0; i < a.length; i++) {
var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
s = s + "/" + X509.hex2rdn(hRDN);
}
return s;
};
X509.hex2rdn = function(hRDN) {
var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
var type = "";
try { type = X509.DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
hValue = hValue.replace(/(..)/g, "%$1");
var value = decodeURIComponent(hValue);
return type + "=" + value;
};
X509.DN_ATTRHEX = {
"0603550406": "C",
"060355040a": "O",
"060355040b": "OU",
"0603550403": "CN",
"0603550405": "SN",
"0603550408": "ST",
"0603550407": "L",
};
/**
* get RSAKey/ECDSA public key object from PEM certificate string
* @name getPublicKeyFromCertPEM
* @memberOf X509
* @function
* @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
* @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
* @since x509 1.1.1
* @description
* NOTE: DSA is also supported since x509 1.1.2.
*/
X509.getPublicKeyFromCertPEM = function(sCertPEM) {
var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);
if (info.algoid == "2a864886f70d010101") { // RSA
var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
var key = new RSAKey();
key.setPublic(aRSA.n, aRSA.e);
return key;
} else if (info.algoid == "2a8648ce3d0201") { // ECC
var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
key.setPublicKeyHex(info.keyhex);
return key;
} else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
y = y.substr(2);
var key = new KJUR.crypto.DSA();
key.setPublic(new BigInteger(p, 16),
new BigInteger(q, 16),
new BigInteger(g, 16),
new BigInteger(y, 16));
return key;
} else {
throw "unsupported key";
}
};
/**
* get public key information from PEM certificate
* @name getPublicKeyInfoPropOfCertPEM
* @memberOf X509
* @function
* @param {String} sCertPEM string of PEM formatted certificate
* @return {Hash} hash of information for public key
* @since x509 1.1.1
* @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
*
keyhex - hexadecimal string of key in the certificate
*
* @since x509 1.1.1
*/
X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
var result = {};
result.algparam = null;
var hCert = X509.pemToHex(sCertPEM);
// 1. Certificate ASN.1
var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0);
if (a1.length != 3)
throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert
// 2. tbsCertificate
if (hCert.substr(a1[0], 2) != "30")
throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq
var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]);
// 3. subjectPublicKeyInfo
if (a2.length < 7)
throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]);
if (a3.length != 2)
throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey
// 4. AlgId
var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);
if (a4.length != 2)
throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId
result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);
if (hCert.substr(a4[1], 2) == "06") { // EC
result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
} else if (hCert.substr(a4[1], 2) == "30") { // DSA
result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
}
// 5. Public Key Hex
if (hCert.substr(a3[1], 02) != "03")
throw "malformed X.509 certificate PEM (code:006)"; // not bitstring
var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
result.keyhex = unusedBitAndKeyHex.substr(2);
return result;
};
/*
X509.prototype.readCertPEM = _x509_readCertPEM;
X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
X509.prototype.getIssuerHex = _x509_getIssuerHex;
X509.prototype.getSubjectHex = _x509_getSubjectHex;
X509.prototype.getIssuerString = _x509_getIssuerString;
X509.prototype.getSubjectString = _x509_getSubjectString;
X509.prototype.getNotBefore = _x509_getNotBefore;
X509.prototype.getNotAfter = _x509_getNotAfter;
*/
================================================
FILE: JavaScript/sm2/js/yahoo-min.js
================================================
/*
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(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var b=arguments,g=null,e,c,f;for(e=0;e":">",'"':""","'":"'","/":"/","`":"`"},d=["toString","valueOf"],e={isArray:function(j){return a.toString.apply(j)===c;},isBoolean:function(j){return typeof j==="boolean";},isFunction:function(j){return(typeof j==="function")||a.toString.apply(j)===h;},isNull:function(j){return j===null;},isNumber:function(j){return typeof j==="number"&&isFinite(j);},isObject:function(j){return(j&&(typeof j==="object"||f.isFunction(j)))||false;},isString:function(j){return typeof j==="string";},isUndefined:function(j){return typeof j==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(l,k){var j,n,m;for(j=0;j"'\/`]/g,function(k){return g[k];});},extend:function(m,n,l){if(!n||!m){throw new Error("extend failed, please check that "+"all dependencies are included.");}var k=function(){},j;k.prototype=n.prototype;m.prototype=new k();m.prototype.constructor=m;m.superclass=n.prototype;if(n.prototype.constructor==a.constructor){n.prototype.constructor=n;}if(l){for(j in l){if(f.hasOwnProperty(l,j)){m.prototype[j]=l[j];}}f._IEEnumFix(m.prototype,l);}},augmentObject:function(n,m){if(!m||!n){throw new Error("Absorb failed, verify dependencies.");}var j=arguments,l,o,k=j[2];if(k&&k!==true){for(l=2;l ";if(!f.isObject(j)){return j+"";}else{if(j instanceof Date||("nodeType" in j&&"tagName" in j)){return j;}else{if(f.isFunction(j)){return k;}}}p=(f.isNumber(p))?p:3;if(f.isArray(j)){r.push("[");for(l=0,n=j.length;l0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}if(r.length>1){r.pop();}r.push("]");}else{r.push("{");for(l in j){if(f.hasOwnProperty(j,l)){r.push(l+m);if(f.isObject(j[l])){r.push((p>0)?f.dump(j[l],p-1):t);}else{r.push(j[l]);}r.push(q);}}if(r.length>1){r.pop();}r.push("}");}return r.join("");},substitute:function(x,y,E,l){var D,C,B,G,t,u,F=[],p,z=x.length,A="dump",r=" ",q="{",m="}",n,w;for(;;){D=x.lastIndexOf(q,z);if(D<0){break;}C=x.indexOf(m,D);if(D+1>C){break;}p=x.substring(D+1,C);G=p;u=null;B=G.indexOf(r);if(B>-1){u=G.substring(B+1);G=G.substring(0,B);}t=y[G];if(E){t=E(G,t,u);}if(f.isObject(t)){if(f.isArray(t)){t=f.dump(t,parseInt(u,10));}else{u=u||"";n=u.indexOf(A);if(n>-1){u=u.substring(4);}w=t.toString();if(w===i||n>-1){t=f.dump(t,parseInt(u,10));}else{t=w;}}}else{if(!f.isString(t)&&!f.isNumber(t)){t="~-"+F.length+"-~";F[F.length]=p;}}x=x.substring(0,D)+t+x.substring(C+1);if(l===false){z=D-1;}}for(D=F.length-1;D>=0;D=D-1){x=x.replace(new RegExp("~-"+D+"-~"),"{"+F[D]+"}","g");}return x;},trim:function(j){try{return j.replace(/^\s+|\s+$/g,"");}catch(k){return j;
}},merge:function(){var n={},k=arguments,j=k.length,m;for(m=0;mSM2 sample
SM2 sample
generating SM2 keypair, signing and verifying SM3withSM2 signature