deriveECKey.js

Summary

Derive a EC subkey from a a main key


Class Summary
DeriveECKeySample  

/**
 *  ---------
 * |.##> <##.|  SmartCard-HSM Support Scripts
 * |#       #|
 * |#       #|  Copyright (c) 2011-2015 CardContact Software & System Consulting
 * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
 *  ---------
 *
 * Consult your license package for usage terms and conditions.
 *
 * @fileoverview Derive a EC subkey from a a main key
 */

CVC = require("scsh/eac/CVC").CVC;
SmartCardHSM = require("scsh/sc-hsm/SmartCardHSM").SmartCardHSM;
SmartCardHSMKeySpecGenerator = require("scsh/sc-hsm/SmartCardHSM").SmartCardHSMKeySpecGenerator;
HSMKeyStore = require("scsh/sc-hsm/HSMKeyStore").HSMKeyStore;



/**
 * Example that shows how EC keys can be derived from a common master key
 *
 * This examples requires a SmartCard-HSM 4K (V3.0). It does not use meta information for derived keys,
 * but removes keys after use.
 */
function DeriveECKeySample(card) {
	this.card = card;
	this.crypto = new Crypto();

	this.sc = new SmartCardHSM(this.card);
	var devAutCert = this.sc.readBinary(SmartCardHSM.C_DevAut);
	this.chain = SmartCardHSM.validateCertificateChain(this.crypto, devAutCert);
	if (this.chain == null) {
		throw new GPError(module.id, GPError.DEVICE_ERROR, 0, "SmartCard-HSM authentication failed");
	}
	this.sc.openSecureChannel(this.crypto, this.chain.publicKey, Key.AES);

	this.ks = new HSMKeyStore(this.sc);
	this.masterKeys = [];
}



/**
 * Perform user authentication
 */
DeriveECKeySample.prototype.login = function(pin) {
	var sw = this.sc.verifyUserPIN(new ByteString(pin, ASCII));

	if (sw != 0x9000) {
		print(SmartCardHSM.describePINStatus(sw, "User PIN"));
	}

	return sw == 0x9000;
}



/**
 * Generate an EC master key
 */
DeriveECKeySample.prototype.generateMaster = function(curve, label) {
	if (this.ks.hasKey(label)) {
		this.ks.deleteKey(label);
	}

	var mem = this.sc.getFreeMemory();
	this.sc.card.sendSecMsgApdu(Card.ALL, 0x80, 0x50, 0x00, 0x00, new ByteString("00", HEX));

	var dp = new Key();
	dp.setComponent(Key.ECC_CURVE_OID, new ByteString(curve, OID));

	var gen = new SmartCardHSMKeySpecGenerator(Crypto.EC, dp);
	gen.algorithms = new ByteString("7098", HEX);

	print("Generating key " + label + " / Free memory " + mem);
	var req = this.ks.generateKeyPair(label, gen);

	var prk = this.ks.getKey(label);
	this.ks.storeEndEntityCertificate(prk, req.getBytes());

	var puk = req.getPublicKey();

	this.masterKeys[label] = { id: prk.id, puk: puk };
}



/**
 * Derive sub EC key and perform test signature
 */
DeriveECKeySample.prototype.deriveKey = function(master, id, offset) {
	var mem = this.sc.getFreeMemory();
	print("Derive key with offset " + offset.toString(HEX) + " / Free memory " + mem);
	this.sc.card.sendSecMsgApdu(Card.ALL, 0x00, 0xE4, 0x02, 0x00, ByteString.valueOf(0xCC00 + id), [0x9000, 0x6A82]);

	var prk = this.ks.getKey(master);
	var bin = this.ks.getCertificate(master);
	var cvc = new CVC(bin);

	var Q = cvc.getPublicKey();

	var algid = new ByteString("98", HEX);
	var dd = algid.concat(offset);

	// Derive Key
	var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x76, prk.id, id, dd, [0x9000] );

	// Recalculate the new public key
	var Q_new = new Key();
	Q_new.setType(Key.PUBLIC);
	Q_new.setComponent(Key.ECC_CURVE_OID, new ByteString("secp256k1", OID));
	Q_new.setComponent(Key.ECC_QX, Q_new.getComponent(Key.ECC_GX));
	Q_new.setComponent(Key.ECC_QY, Q_new.getComponent(Key.ECC_GY));

	// Q = Q_new * idx + Q
	this.crypto.deriveKey(Q_new, Crypto.EC_MULTIPLY_ADD, offset, Q);

	var msg = new ByteString("Hello World", ASCII);
	var hash = this.crypto.digest(Crypto.SHA_256, msg);

	var signature = this.sc.sign(id, 0x70, hash, [0x9000] );
	assert(this.crypto.verify(Q, Crypto.ECDSA_SHA256, msg, signature));
}



var card = new Card(_scsh3.reader);

card.reset(Card.RESET_COLD);

var t = new DeriveECKeySample(card);

t.login("648219");

var masterkeys = 7;
var subkeys = 8;
var loops = 1;

var starttime = new Date();

print("Started at " + starttime);

for (var l = 0; l < loops; l++) {
	for (var m = 0; m < masterkeys; m++) {
		var ml = "ECMaster" + (m + 1);
		t.generateMaster("secp256k1", ml);

		for (var i = 0; i < subkeys; i++) {
			var offset = new ByteString("65468573", HEX);
			offset = offset.concat(ByteString.valueOf(l)).concat(ByteString.valueOf(m)).concat(ByteString.valueOf(i));
			var id = m * subkeys + i + masterkeys + 1;
			t.deriveKey(ml, id, offset);
		}
	}
}

var stoptime = new Date();

print("Ended at " + stoptime);

var duration = stoptime.valueOf() - starttime.valueOf();

print("Duration " + duration + " ms");


Documentation generated by JSDoc on Sat Feb 24 15:17:19 2024