EAC2CVCertificateGenerator.js
Summary
EAC2CVCertificateGenerator - Simple CV certificate generator class
based on "Advanced Security Mechanisms for Machine Readable Travel Documents", Version 2.0
TODO: For now we only support ECC crypto
Class Summary
|
EAC2CVCertificateGenerator |
Class implementing a generator for CV certificates according to EAC 1.1 and EAC 2.0 specifications. |
load("tools/eccutils.js");
if (typeof(__ScriptingServer) == "undefined") {
load("cvc.js");
}
function EAC2CVCertificateGenerator(crypto) {
this.crypto = crypto;
}
EAC2CVCertificateGenerator.encodeUncompressedECPoint = function(x,y) {
bb = new ByteBuffer();
bb.append(new ByteString("04", HEX));
bb.append(new ByteString(x, HEX));
bb.append(new ByteString(y, HEX));
return bb.toByteString();
}
EAC2CVCertificateGenerator.decodeUncompressedECPoint = function(uncompressedPoint) {
var length = uncompressedPoint.length - 1;
var sizeOfCoordinate = length / 2;
var xValue = uncompressedPoint.bytes(1, sizeOfCoordinate);
var yValue = uncompressedPoint.bytes(1 + sizeOfCoordinate, sizeOfCoordinate);
return { x:xValue, y:yValue };
}
EAC2CVCertificateGenerator.itos = function(value, digits) {
if (digits > 20) {
throw new Error("Digits must be <= 20");
}
var str = "" + value;
str = "0000000000000000000".substr(19 - (digits - str.length)).concat(str);
return str;
}
EAC2CVCertificateGenerator.dtos = function(d) {
var s = EAC2CVCertificateGenerator.itos(d.getFullYear() % 100, 2) +
EAC2CVCertificateGenerator.itos(d.getMonth() + 1, 2) +
EAC2CVCertificateGenerator.itos(d.getDate(), 2);
return s;
}
EAC2CVCertificateGenerator.prototype.setProfileIdentifier = function(profileID) {
this.profileIdentifier = profileID;
}
EAC2CVCertificateGenerator.prototype.setCAR = function(CAR) {
if (CAR instanceof ByteString) {
this.CAR = CAR;
} else if (CAR instanceof PublicKeyReference) {
this.CAR = CAR.getBytes();
} else {
this.CAR = new ByteString(CAR.toString(), ASCII);
}
}
EAC2CVCertificateGenerator.prototype.setCHR = function(CHR) {
if (CHR instanceof ByteString) {
this.CHR = CHR;
} else if (CHR instanceof PublicKeyReference) {
this.CHR = CHR.getBytes();
} else {
this.CHR = new ByteString(CHR.toString(), ASCII);
}
}
EAC2CVCertificateGenerator.prototype.setEffectiveDate = function(effectiveDate) {
if (effectiveDate instanceof Date) {
this.effectiveDate = EAC2CVCertificateGenerator.dtos(effectiveDate);
} else {
this.effectiveDate = effectiveDate;
}
}
EAC2CVCertificateGenerator.prototype.setExpiryDate = function(expiryDate) {
if (expiryDate instanceof Date) {
this.expiryDate = EAC2CVCertificateGenerator.dtos(expiryDate);
} else {
this.expiryDate = expiryDate;
}
}
EAC2CVCertificateGenerator.prototype.setChatOID = function(oid) {
this.chatOID = oid;
}
EAC2CVCertificateGenerator.prototype.setChatAuthorizationLevel = function(authLevel) {
this.chatAuthorizationLevel = authLevel;
}
EAC2CVCertificateGenerator.prototype.setTAAlgorithmIdentifier = function(oid) {
this.taOID = oid;
}
EAC2CVCertificateGenerator.prototype.setExtensions = function(extensions) {
this.extensions = extensions;
}
EAC2CVCertificateGenerator.prototype.setPublicKey = function(publicKey) {
this.publicKey = publicKey;
}
EAC2CVCertificateGenerator.prototype.setIncludeDomainParameters = function(value) {
this.includeDomainParameters = value;
}
EAC2CVCertificateGenerator.prototype.getCAR = function() {
var t = new ASN1("Certification Authority Reference", 0x42, this.CAR);
return t;
}
EAC2CVCertificateGenerator.prototype.getCHR = function() {
var t = new ASN1("Certification Holder Reference", 0x5F20, this.CHR);
return t;
}
EAC2CVCertificateGenerator.convertDate = function(date) {
var temp = new ByteString(date, ASCII);
var bb = new ByteBuffer();
var singleByte;
for (var i = 0; i < temp.length; i++) {
bb.append(temp.byteAt(i) - 0x30);
}
return bb.toByteString();
}
EAC2CVCertificateGenerator.prototype.getEffectiveDate = function() {
var t = new ASN1("Certificate Effective Date", 0x5F25,
EAC2CVCertificateGenerator.convertDate(this.effectiveDate));
return t;
}
EAC2CVCertificateGenerator.prototype.getExpiryDate = function() {
var t = new ASN1("Certificate Expiration Date", 0x5F24,
EAC2CVCertificateGenerator.convertDate(this.expiryDate));
return t;
}
EAC2CVCertificateGenerator.prototype.getCHAT = function() {
var t = new ASN1("Certificate Holder Authorization Template", 0x7F4C);
var oid = new ASN1("Object Identifier", ASN1.OBJECT_IDENTIFIER, this.chatOID);
var authLevel = new ASN1("Authorization Level", 0x53, this.chatAuthorizationLevel);
t.add(oid);
t.add(authLevel);
return t;
}
EAC2CVCertificateGenerator.prototype.stripLeadingZeros = function(value) {
var i = 0;
for (; (i < value.length) && (value.byteAt(i) == 0); i++);
return value.right(value.length - i);
}
EAC2CVCertificateGenerator.prototype.getPublicKey = function() {
var t = new ASN1("Public Key", 0x7F49);
t.add(new ASN1("Object Identifier", 0x06, this.taOID));
if (typeof(this.publicKey.getComponent(Key.ECC_P)) != "undefined") {
if (this.includeDomainParameters == true) {
t.add(new ASN1("Prime Modulus", 0x81, this.publicKey.getComponent(Key.ECC_P)));
t.add(new ASN1("First coefficient a", 0x82, this.publicKey.getComponent(Key.ECC_A)));
t.add(new ASN1("Second coefficient b", 0x83, this.publicKey.getComponent(Key.ECC_B)));
t.add(new ASN1("Base Point G", 0x84, EAC2CVCertificateGenerator.encodeUncompressedECPoint(this.publicKey.getComponent(Key.ECC_GX), this.publicKey.getComponent(Key.ECC_GY))));
t.add(new ASN1("Order of the base point", 0x85, this.publicKey.getComponent(Key.ECC_N)));
}
t.add(new ASN1("Public Point y", 0x86, EAC2CVCertificateGenerator.encodeUncompressedECPoint(this.publicKey.getComponent(Key.ECC_QX), this.publicKey.getComponent(Key.ECC_QY))));
if (this.includeDomainParameters == true) {
t.add(new ASN1("Cofactor f", 0x87, this.stripLeadingZeros(this.publicKey.getComponent(Key.ECC_H))));
}
} else {
t.add(new ASN1("Composite Modulus", 0x81, this.publicKey.getComponent(Key.MODULUS)));
t.add(new ASN1("Public Exponent", 0x82, this.publicKey.getComponent(Key.EXPONENT)));
}
return t;
}
EAC2CVCertificateGenerator.prototype.getProfileIdentifier = function() {
var bb = new ByteBuffer();
bb.append(this.profileIdentifier);
var t = new ASN1("Certificate Profile Identifier", 0x5F29, bb.toByteString());
return t;
}
EAC2CVCertificateGenerator.prototype.getExtensions = function() {
var t = new ASN1("Certificate Extensions", 0x65);
for (var i = 0; i < this.extensions.length; i++)
t.add(this.extensions[i]);
return t;
}
EAC2CVCertificateGenerator.prototype.getCertificateBody = function() {
var t = new ASN1("Certificate Body", 0x7F4E);
t.add(this.getProfileIdentifier());
t.add(this.getCAR());
t.add(this.getPublicKey());
t.add(this.getCHR());
t.add(this.getCHAT());
t.add(this.getEffectiveDate());
t.add(this.getExpiryDate());
if (this.extensions) {
t.add(this.getExtensions());
}
return t;
}
EAC2CVCertificateGenerator.prototype.generateCVCertificate = function(signingKey, outertaOID) {
var certificate = new ASN1("CV Certificate", 0x7F21);
var body = this.getCertificateBody();
if (typeof(outertaOID) == "undefined") {
outertaOID = this.taOID;
}
var mech = CVC.getSignatureMech(outertaOID);
var signature = this.crypto.sign(signingKey, mech, body.getBytes());
if (CVC.isECDSA(outertaOID)) {
var keylen = signingKey.getSize() >> 3;
var signatureValue = new ASN1("Signature", 0x5F37, ECCUtils.unwrapSignature(signature, keylen));
} else {
var signatureValue = new ASN1("Signature", 0x5F37, signature);
}
certificate.add(body);
certificate.add(signatureValue);
return new CVC(certificate);
}
Documentation generated by
JSDoc on Tue Sep 3 22:29:38 2013