// Path: commons-eid-consumer/src/main/java/be/bosa/commons/eid/consumer/tlv/TlvParser.java
// public class TlvParser {
// 
// 	private static final Log LOG = LogFactory.getLog(TlvParser.class);
// 
// 	private TlvParser() {
// 	}
// 
// 	/**
// 	 * Parses the given file using the meta-data annotations within the tlvClass
// 	 * parameter.
// 	 */
// 	public static <T> T parse(byte[] file, Class<T> tlvClass) {
// 		try {
// 			return parseThrowing(file, tlvClass);
// 		} catch (Exception ex) {
// 			throw new RuntimeException("error parsing file: " + tlvClass.getName(), ex);
// 		}
// 	}
// 
// 	private static byte[] copy(byte[] source, int idx, int count) {
// 		byte[] result = new byte[count];
// 		System.arraycopy(source, idx, result, 0, count);
// 		return result;
// 	}
// 
// 	private static <T> T parseThrowing(byte[] file, Class<T> tlvClass)
// 			throws InstantiationException, IllegalAccessException, DataConvertorException, UnsupportedEncodingException {
// 		Field[] fields = tlvClass.getDeclaredFields();
// 		Map<Integer, Field> tlvFields = new HashMap<>();
// 		T tlvObject = tlvClass.newInstance();
// 		
// 		for (Field field : fields) {
// 			TlvField tlvFieldAnnotation = field.getAnnotation(TlvField.class);
// 			if (tlvFieldAnnotation != null) {
// 				int tagId = tlvFieldAnnotation.value();
// 				if (tlvFields.containsKey(tagId)) {
// 					throw new IllegalArgumentException("TLV field duplicate: " + tagId);
// 				}
// 				tlvFields.put(tagId, field);
// 			}
// 			OriginalData originalDataAnnotation = field.getAnnotation(OriginalData.class);
// 			if (originalDataAnnotation != null) {
// 				field.setAccessible(true);
// 				field.set(tlvObject, file);
// 			}
// 		}
// 
// 		int idx = 0;
// 		while (idx < file.length - 1) {
// 			int tag = file[idx];
// 			idx++;
// 			byte lengthByte = file[idx];
// 			int length = lengthByte & 0x7f;
// 			while ((lengthByte & 0x80) == 0x80) {
// 				idx++;
// 				lengthByte = file[idx];
// 				length = (length << 7) + (lengthByte & 0x7f);
// 			}
// 			idx++;
// 			if (0 == tag) {
// 				idx += length;
// 				continue;
// 			}
// 			if (tlvFields.containsKey(tag)) {
// 				Field tlvField = tlvFields.get(tag);
// 				Class<?> tlvType = tlvField.getType();
// 				ConvertData convertDataAnnotation = tlvField.getAnnotation(ConvertData.class);
// 				byte[] tlvValue = copy(file, idx, length);
// 				Object fieldValue;
// 				if (null != convertDataAnnotation) {
// 					Class<? extends DataConvertor<?>> dataConvertorClass = convertDataAnnotation.value();
// 					DataConvertor<?> dataConvertor = dataConvertorClass.newInstance();
// 					fieldValue = dataConvertor.convert(tlvValue);
// 				} else if (String.class == tlvType) {
// 					fieldValue = new String(tlvValue, "UTF-8");
// 				} else if (Boolean.TYPE == tlvType) {
// 					fieldValue = true;
// 				} else if (tlvType.isArray() && Byte.TYPE == tlvType.getComponentType()) {
// 					fieldValue = tlvValue;
// 				} else {
// 					throw new IllegalArgumentException("unsupported field type: " + tlvType.getName());
// 				}
// 				if (tlvField.get(tlvObject) != null && !tlvField.getType().isPrimitive()) {
// 					throw new RuntimeException("field was already set: " + tlvField.getName());
// 				}
// 				tlvField.setAccessible(true);
// 				tlvField.set(tlvObject, fieldValue);
// 			} else {
// 				LOG.debug("unknown tag: " + (tag & 0xff) + ", length: " + length);
// 			}
// 			idx += length;
// 		}
// 		return tlvObject;
// 	}
// }


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import be.bosa.commons.eid.consumer.tlv.TlvParser;
import java.io.ByteArrayInputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
	}

	/**
	 * Gives back a parsed identity file after integrity verification.
	 */
	public Identity getVerifiedIdentity(byte[] identityFile, byte[] identitySignatureFile, X509Certificate rrnCertificate)
			throws NoSuchAlgorithmException {
		return getVerifiedIdentity(identityFile, identitySignatureFile, null, rrnCertificate);
	}

	/**
	 * Gives back a parsed identity file after integrity verification including
	 * the eID photo.
	 */
	public Identity getVerifiedIdentity(byte[] identityFile, byte[] identitySignatureFile, byte[] photo, X509Certificate rrnCertificate)
			throws NoSuchAlgorithmException {
		PublicKey publicKey = rrnCertificate.getPublicKey();
		boolean result;
		try {
			result = verifySignature(rrnCertificate.getSigAlgName(),
					identitySignatureFile, publicKey, identityFile);
			if (!result) {
				throw new SecurityException("signature integrity error");
			}
		} catch (Exception ex) {
			throw new SecurityException(
					"identity signature verification error: " + ex.getMessage(),
					ex);
		}

// Path: commons-eid-consumer/src/main/java/be/bosa/commons/eid/consumer/tlv/TlvParser.java
// public class TlvParser {
// 
// 	private static final Log LOG = LogFactory.getLog(TlvParser.class);
// 
// 	private TlvParser() {
// 	}
// 
// 	/**
// 	 * Parses the given file using the meta-data annotations within the tlvClass
// 	 * parameter.
// 	 */
// 	public static <T> T parse(byte[] file, Class<T> tlvClass) {
// 		try {
// 			return parseThrowing(file, tlvClass);
// 		} catch (Exception ex) {
// 			throw new RuntimeException("error parsing file: " + tlvClass.getName(), ex);
// 		}
// 	}
// 
// 	private static byte[] copy(byte[] source, int idx, int count) {
// 		byte[] result = new byte[count];
// 		System.arraycopy(source, idx, result, 0, count);
// 		return result;
// 	}
// 
// 	private static <T> T parseThrowing(byte[] file, Class<T> tlvClass)
// 			throws InstantiationException, IllegalAccessException, DataConvertorException, UnsupportedEncodingException {
// 		Field[] fields = tlvClass.getDeclaredFields();
// 		Map<Integer, Field> tlvFields = new HashMap<>();
// 		T tlvObject = tlvClass.newInstance();
// 		
// 		for (Field field : fields) {
// 			TlvField tlvFieldAnnotation = field.getAnnotation(TlvField.class);
// 			if (tlvFieldAnnotation != null) {
// 				int tagId = tlvFieldAnnotation.value();
// 				if (tlvFields.containsKey(tagId)) {
// 					throw new IllegalArgumentException("TLV field duplicate: " + tagId);
// 				}
// 				tlvFields.put(tagId, field);
// 			}
// 			OriginalData originalDataAnnotation = field.getAnnotation(OriginalData.class);
// 			if (originalDataAnnotation != null) {
// 				field.setAccessible(true);
// 				field.set(tlvObject, file);
// 			}
// 		}
// 
// 		int idx = 0;
// 		while (idx < file.length - 1) {
// 			int tag = file[idx];
// 			idx++;
// 			byte lengthByte = file[idx];
// 			int length = lengthByte & 0x7f;
// 			while ((lengthByte & 0x80) == 0x80) {
// 				idx++;
// 				lengthByte = file[idx];
// 				length = (length << 7) + (lengthByte & 0x7f);
// 			}
// 			idx++;
// 			if (0 == tag) {
// 				idx += length;
// 				continue;
// 			}
// 			if (tlvFields.containsKey(tag)) {
// 				Field tlvField = tlvFields.get(tag);
// 				Class<?> tlvType = tlvField.getType();
// 				ConvertData convertDataAnnotation = tlvField.getAnnotation(ConvertData.class);
// 				byte[] tlvValue = copy(file, idx, length);
// 				Object fieldValue;
// 				if (null != convertDataAnnotation) {
// 					Class<? extends DataConvertor<?>> dataConvertorClass = convertDataAnnotation.value();
// 					DataConvertor<?> dataConvertor = dataConvertorClass.newInstance();
// 					fieldValue = dataConvertor.convert(tlvValue);
// 				} else if (String.class == tlvType) {
// 					fieldValue = new String(tlvValue, "UTF-8");
// 				} else if (Boolean.TYPE == tlvType) {
// 					fieldValue = true;
// 				} else if (tlvType.isArray() && Byte.TYPE == tlvType.getComponentType()) {
// 					fieldValue = tlvValue;
// 				} else {
// 					throw new IllegalArgumentException("unsupported field type: " + tlvType.getName());
// 				}
// 				if (tlvField.get(tlvObject) != null && !tlvField.getType().isPrimitive()) {
// 					throw new RuntimeException("field was already set: " + tlvField.getName());
// 				}
// 				tlvField.setAccessible(true);
// 				tlvField.set(tlvObject, fieldValue);
// 			} else {
// 				LOG.debug("unknown tag: " + (tag & 0xff) + ", length: " + length);
// 			}
// 			idx += length;
// 		}
// 		return tlvObject;
// 	}
// }


// Path: commons-eid-consumer/src/main/java/be/bosa/commons/eid/consumer/BeIDIntegrity.java
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import be.bosa.commons.eid.consumer.tlv.TlvParser;
import java.io.ByteArrayInputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;

	}

	/**
	 * Gives back a parsed identity file after integrity verification.
	 */
	public Identity getVerifiedIdentity(byte[] identityFile, byte[] identitySignatureFile, X509Certificate rrnCertificate)
			throws NoSuchAlgorithmException {
		return getVerifiedIdentity(identityFile, identitySignatureFile, null, rrnCertificate);
	}

	/**
	 * Gives back a parsed identity file after integrity verification including
	 * the eID photo.
	 */
	public Identity getVerifiedIdentity(byte[] identityFile, byte[] identitySignatureFile, byte[] photo, X509Certificate rrnCertificate)
			throws NoSuchAlgorithmException {
		PublicKey publicKey = rrnCertificate.getPublicKey();
		boolean result;
		try {
			result = verifySignature(rrnCertificate.getSigAlgName(),
					identitySignatureFile, publicKey, identityFile);
			if (!result) {
				throw new SecurityException("signature integrity error");
			}
		} catch (Exception ex) {
			throw new SecurityException(
					"identity signature verification error: " + ex.getMessage(),
					ex);
		}

		Identity identity = TlvParser.parse(identityFile, Identity.class);