293 lines
9.4 KiB
JavaScript
293 lines
9.4 KiB
JavaScript
|
|
/*! 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 <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*
|
||
|
|
* 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);
|
||
|
|
};
|
||
|
|
|