Overview | File | Class | Tree | Index | Help
PREV NEXT | FRAMES NO FRAMES

## eccutils.js

#### Summary

No overview generated for 'eccutils.js'

Class Summary
ECCUtils |

    /*
     *  ---------
     * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
     * |#       #|
     * |#       #|  Copyright (c) 1999-2006 CardContact Software & System Consulting
     * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
     *  ---------
     *
     *  This file is part of OpenSCDP.
     *
     *  OpenSCDP is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License version 2 as
     *  published by the Free Software Foundation.
     *
     *  OpenSCDP is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *
     *  You should have received a copy of the GNU General Public License
     *  along with OpenSCDP; if not, write to the Free Software
     *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     *
     *  Utility class for Elliptic Curve Cryptography
     */

    function ECCUtils() {
    }

    /**
     * Wrap a ECDSA signature in the format r || s into a TLV encoding as defined by RFC 3279
     *
     * @param signature ByteString containing the concatenation of r and s as unsigned integer values
     * @returns ASN.1 SEQUENCE objects containing two signed integer r and s
     */
    ECCUtils.wrapSignature = function(signature) {
    	var len = signature.length / 2;

    	// r and s are unsigned big integer. We might need to pad a zero for ASN.1 INTEGER which is signed
    	var r = signature.bytes(0, len);
    	if (r.byteAt(0) >= 0x80) {
    		r = ByteString.valueOf(0, 1).concat(r);
    	}

    	var s = signature.bytes(len, len);
    	if (s.byteAt(0) >= 0x80) {
    		s = ByteString.valueOf(0, 1).concat(s);
    	}

    	var t = new ASN1(ASN1.SEQUENCE);
    	t.add(new ASN1(ASN1.INTEGER, r));
    	t.add(new ASN1(ASN1.INTEGER, s));

    	return t.getBytes();
    }

    /**
     * Integer to octet string conversion
     */
    ECCUtils.I2O = function(value, length) {
    	if (value.length > length) {
    		value = value.right(length);
    	}
    	while (value.length < length) {
    		value = ECCUtils.PAD.left((length - value.length - 1 & 15) + 1).concat(value);
    	}
    	return value;
    }
    ECCUtils.PAD = new ByteString("00000000000000000000000000000000", HEX);

    /**
     * Unwrap a ECDSA signature from the TLV encoding according to RFC3279 into the concatenation
     * of the unsigned integer r and s
     *
     * @param signature TLV encoded signature
     * @returns concatenation of r and s
     */
    ECCUtils.unwrapSignature = function(signature, keylen) {
    	var t = new ASN1(signature);
    	if (typeof(keylen) != "undefined") {
    		var r = ECCUtils.I2O(t.get(0).value, keylen);
    		var s = ECCUtils.I2O(t.get(1).value, keylen);
    	} else {
    		var r = t.get(0).value;
    		if (r.byteAt(0) == 00)
    			r = r.bytes(1);

    		var s = t.get(1).value;
    		if (s.byteAt(0) == 00)
    			s = s.bytes(1);
    	}

    	return r.concat(s);
    }

    /**
     * Decode domain parameter from ECParameters
     *
     * <pre>
     *	ECParameters ::= SEQUENCE {
     *		version INTEGER{ecpVer1(1)} (ecpVer1),
     *		fieldID FieldID,
     *		curve Curve,
     *		base ECPoint,
     *		order INTEGER,
     *		cofactor INTEGER OPTIONAL,
     *		...
     *	}
     *
     *	Curve ::= SEQUENCE {
     *		a FieldElement,
     *		b FieldElement,
     *		seed BIT STRING OPTIONAL
     *	}
     *
     *	FieldElement ::= OCTET STRING
     *	ECPoint ::= OCTET STRING
     *	FieldID ::= SEQUENCE {
     *		fieldType OBJECT IDENTIFIER,
     *		parameters ANY DEFINED BY fieldType
     *	}
     *	prime-field OBJECT IDENTIFIER ::= { ansi-x9-62 fieldType(1) 1 }
     *	Prime-p ::= INTEGER
     * </pre>
     */
    ECCUtils.decodeECParameters = function(tlv) {
    	assert(tlv.tag == ASN1.SEQUENCE);

    	var key = new Key();
    	key.setType(Key.PUBLIC);

    	// version
    	assert(tlv.get(0).value.toSigned() == 1);

    	// fieldID
    	assert(tlv.get(1).tag == ASN1.SEQUENCE);
    	assert(tlv.get(1).get(1).tag = ASN1.INTEGER);

    	var prime = tlv.get(1).get(1).value;
    	if (prime.byteAt(0) == 0) {		// Strip leading zero byte
    		prime = prime.bytes(1);
    	}
    	key.setComponent(Key.ECC_P, prime);

    	// curve
    	assert(tlv.get(2).tag == ASN1.SEQUENCE);
    	assert(tlv.get(2).get(0).tag == ASN1.OCTET_STRING);

    	var coeff_A = tlv.get(2).get(0);
    	key.setComponent(Key.ECC_A, coeff_A.value);

    	var coeff_B = tlv.get(2).get(1);
    	key.setComponent(Key.ECC_B, coeff_B.value);

    	// base
    	assert(tlv.get(3).tag == ASN1.OCTET_STRING);
    	var pkbin = tlv.get(3).value;
    	assert(pkbin.byteAt(0) == 4);
    	pkbin = pkbin.bytes(1);

    	key.setComponent(Key.ECC_GX, pkbin.left(pkbin.length >> 1));
    	key.setComponent(Key.ECC_GY, pkbin.right(pkbin.length >> 1));

    	// order
    	assert(tlv.get(4).tag == ASN1.INTEGER);
    	var groupOrder = tlv.get(4).value;
    	if (groupOrder.byteAt(0) == 0) {		// Strip leading zero byte
    		groupOrder = groupOrder.bytes(1);
    	}
    	key.setComponent(Key.ECC_N, groupOrder);

    	// cofactor
    	if (tlv.elements > 5) {
    		assert(tlv.get(5).tag == ASN1.INTEGER);
    		var cofactor = tlv.get(0).value;
    		if (cofactor.byteAt(0) == 0) {		// Strip leading zero byte
    			cofactor = cofactor.bytes(1);
    		}
    		key.setComponent(Key.ECC_H, cofactor);
    	}

    	return key;
    }

    ECCUtils.ECParametersToString = function(key) {
    	var str = "EC Parameter:\n";

    	str += "  prime " + key.getComponent(Key.ECC_P) + "\n";
    	str += "  curve a " + key.getComponent(Key.ECC_A) + "\n";
    	str += "  curve b " + key.getComponent(Key.ECC_B) + "\n";
    	str += "  generator x " + key.getComponent(Key.ECC_GX) + "\n";
    	str += "  generator y " + key.getComponent(Key.ECC_GY) + "\n";
    	str += "  order " + key.getComponent(Key.ECC_N) + "\n";
    	str += "  cofactor " + key.getComponent(Key.ECC_H) + "\n";
    	return str;
    }

    // List of object identifier used in Key.setComponent(ECC_CURVE_OID)

    // Fp curves defined by ANSI X6.92
    ECCUtils.prime192v1 = new ByteString("1.2.840.10045.3.1.1", OID);
    ECCUtils.prime192v2 = new ByteString("1.2.840.10045.3.1.2", OID);
    ECCUtils.prime192v3 = new ByteString("1.2.840.10045.3.1.3", OID);
    ECCUtils.prime239v1 = new ByteString("1.2.840.10045.3.1.4", OID);
    ECCUtils.prime239v2 = new ByteString("1.2.840.10045.3.1.5", OID);
    ECCUtils.prime239v3 = new ByteString("1.2.840.10045.3.1.6", OID);
    ECCUtils.prime256v1 = new ByteString("1.2.840.10045.3.1.7", OID);

    // F2m curves defined by ANSI X6.92
    ECCUtils.c2pnb163v1 = new ByteString("1.2.840.10045.3.0.1", OID);
    ECCUtils.c2pnb163v2 = new ByteString("1.2.840.10045.3.0.2", OID);
    ECCUtils.c2pnb163v3 = new ByteString("1.2.840.10045.3.0.3", OID);
    ECCUtils.c2pnb176w1 = new ByteString("1.2.840.10045.3.0.4", OID);
    ECCUtils.c2tnb191v1 = new ByteString("1.2.840.10045.3.0.5", OID);
    ECCUtils.c2tnb191v2 = new ByteString("1.2.840.10045.3.0.6", OID);
    ECCUtils.c2tnb191v3 = new ByteString("1.2.840.10045.3.0.7", OID);
    ECCUtils.c2pnb208w1 = new ByteString("1.2.840.10045.3.0.10", OID);
    ECCUtils.c2tnb239v1 = new ByteString("1.2.840.10045.3.0.11", OID);
    ECCUtils.c2tnb239v2 = new ByteString("1.2.840.10045.3.0.12", OID);
    ECCUtils.c2tnb239v3 = new ByteString("1.2.840.10045.3.0.13", OID);
    ECCUtils.c2pnb272w1 = new ByteString("1.2.840.10045.3.0.16", OID);
    ECCUtils.c2pnb304w1 = new ByteString("1.2.840.10045.3.0.17", OID);
    ECCUtils.c2tnb359v1 = new ByteString("1.2.840.10045.3.0.18", OID);
    ECCUtils.c2pnb368w1 = new ByteString("1.2.840.10045.3.0.19", OID);
    ECCUtils.c2tnb431r1 = new ByteString("1.2.840.10045.3.0.20", OID);

    // Fp curves defined by SECG
    ECCUtils.secp224r1 = new ByteString("1.3.132.0.33", OID);
    ECCUtils.secp256r1 = ECCUtils.prime256v1;
    ECCUtils.secp384r1 = new ByteString("1.3.132.0.34", OID);
    ECCUtils.secp521r1 = new ByteString("1.3.132.0.35", OID);

    // F2m curves defined by SECG
    ECCUtils.sect163r2 = new ByteString("1.3.132.0.15", OID);
    ECCUtils.sect233r1 = new ByteString("1.3.132.0.27", OID);
    ECCUtils.sect283r1 = new ByteString("1.3.132.0.17", OID);
    ECCUtils.sect409r1 = new ByteString("1.3.132.0.37", OID);
    ECCUtils.sect571r1 = new ByteString("1.3.132.0.39", OID);

    ECCUtils.brainpoolP160r1 = new ByteString("1.3.36.3.3.2.8.1.1.1", OID);
    ECCUtils.brainpoolP160t1 = new ByteString("1.3.36.3.3.2.8.1.1.2", OID);
    ECCUtils.brainpoolP192r1 = new ByteString("1.3.36.3.3.2.8.1.1.3", OID);
    ECCUtils.brainpoolP192t1 = new ByteString("1.3.36.3.3.2.8.1.1.4", OID);
    ECCUtils.brainpoolP224r1 = new ByteString("1.3.36.3.3.2.8.1.1.5", OID);
    ECCUtils.brainpoolP224t1 = new ByteString("1.3.36.3.3.2.8.1.1.6", OID);
    ECCUtils.brainpoolP256r1 = new ByteString("1.3.36.3.3.2.8.1.1.7", OID);
    ECCUtils.brainpoolP256t1 = new ByteString("1.3.36.3.3.2.8.1.1.8", OID);
    ECCUtils.brainpoolP320r1 = new ByteString("1.3.36.3.3.2.8.1.1.9", OID);
    ECCUtils.brainpoolP320t1 = new ByteString("1.3.36.3.3.2.8.1.1.10", OID);
    ECCUtils.brainpoolP384r1 = new ByteString("1.3.36.3.3.2.8.1.1.11", OID);
    ECCUtils.brainpoolP384t1 = new ByteString("1.3.36.3.3.2.8.1.1.12", OID);
    ECCUtils.brainpoolP512r1 = new ByteString("1.3.36.3.3.2.8.1.1.13", OID);
    ECCUtils.brainpoolP512t1 = new ByteString("1.3.36.3.3.2.8.1.1.14", OID);

    /* Test all curve parameter
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime192v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime192v2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime192v3);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime239v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime239v2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime239v3);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.prime256v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb163v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb163v2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb163v3);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb176w1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb191v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb191v2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb191v3);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb208w1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb239v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb239v2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb239v3);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb272w1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb304w1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb359v1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2pnb368w1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.c2tnb431r1);

    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.secp224r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.secp256r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.secp384r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.secp521r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.sect163r2);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.sect233r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.sect283r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.sect409r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.sect571r1);

    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP160r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP160t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP192r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP192t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP224r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP224t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP256r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP256t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP320r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP320t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP384r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP384t1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP512r1);
    var k = new Key();
    k.setComponent(Key.ECC_CURVE_OID, ECCUtils.brainpoolP512t1);
    */

Overview | File | Class | Tree | Index | Help
PREV NEXT | FRAMES NO FRAMES

Documentation generated by JSDoc on Thu Jun 25 17:01:35 2026