/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 1999-2026 CardContact Systems GmbH
 * |'##> <##'|  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
 *
 * @fileoverview Public Key File Format
 */

var File = require("scsh/file/File").File;
var SmartCardHSM = require("scsh/sc-hsm/SmartCardHSM").SmartCardHSM;
var CVC = require("scsh/eac/CVC").CVC;



/**
 * Create a Public Key File object.
 *
 * @class Read and write encoded SmartCard-HSM public keys.
 * @constructor
 * @param {String} arg the file to read from
 * @param {CVC[]} arg the certificate chain with the public key first.
 */
function PublicKeyFile(arg) {
	if (typeof(arg == "string")) {
		var f = new File(arg);
		var bin = f.readAllAsBinary();
		this.parse(bin);
	} else {
		this.chain = arg;
	}
}

exports.PublicKeyFile = PublicKeyFile;



PublicKeyFile.prototype.getChain = function() {
	return this.chain;
}



/**
 * Parse the binary file content as TLV structure and validate the certificate chain.
 *
 * @param {ByteString} content the file content.
 */
PublicKeyFile.prototype.parse = function(content) {
	if (content.byteAt(0) != 0x30) {
		throw new GPError(module.id, GPError.INVALID_DATA, 0, "File does not contain a public key with certificates");
	}

	var a = new ASN1(content);

	if (a.get(0).tag == ASN1.OBJECT_IDENTIFIER) {
		var oid = new ByteString("CardContact 4 3 1", OID);
		assert(a.get(0).value.equals(oid), "Invalid file format");
		var pk = new CVC(a.find(0x63).get(0));
		var devcert = new CVC(a.find(0x62).get(0));
		var dicacert = new CVC(a.find(0x61).get(0));
	} else {
		var pk = new CVC(a.get(0));
		var devcert = new CVC(a.get(1));
		var dicacert = new CVC(a.get(2));
	}

	var crypto = new Crypto();
	assert(dicacert.verifyWithCVC(crypto, SmartCardHSM.rootCerts[dicacert.getCAR()]));
	assert(devcert.verifyWith(crypto, dicacert.getPublicKey(SmartCardHSM.rootCerts.UTSRCACC100001.getPublicKey()), dicacert.getPublicKeyOID()));

	this.chain = [ pk, devcert, dicacert ];
}



/**
 * Encode the certificate chain in TLV encoding.
 *
 * @type ByteString
 * @return the encoded content for the file
 */
PublicKeyFile.prototype.encode = function() {

	var asn = new ASN1(ASN1.SEQUENCE,
			new ASN1(ASN1.OBJECT_IDENTIFIER, new ByteString("CardContact 4 3 1", OID)),
			new ASN1(0x61, this.chain[2].getASN1()),
			new ASN1(0x62, this.chain[1].getASN1()),
			new ASN1(0x63, this.chain[0].getASN1())
	);

//	print(asn);
	return asn.getBytes();
}
