deriveECKey.js
Summary
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;
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 = [];
}
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;
}
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 };
}
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);
var rsp = this.card.sendSecMsgApdu(Card.ALL, 0x80, 0x76, prk.id, id, dd, [0x9000] );
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));
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