/*
* eID Applet Project.
* Copyright (C) 2008-2009 FedICT.
* Copyright (C) 2014 e-Contract.be BVBA.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version
* 3.0 as published by the Free Software Foundation.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, see
* http://www.gnu.org/licenses/.
*/
package be.fedict.eid.applet.shared;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import be.fedict.eid.applet.shared.annotation.HttpBody;
import be.fedict.eid.applet.shared.annotation.HttpHeader;
import be.fedict.eid.applet.shared.annotation.MessageDiscriminator;
import be.fedict.eid.applet.shared.annotation.NotNull;
import be.fedict.eid.applet.shared.annotation.PostConstruct;
import be.fedict.eid.applet.shared.annotation.ProtocolStateAllowed;
import be.fedict.eid.applet.shared.annotation.ResponsesAllowed;
import be.fedict.eid.applet.shared.protocol.ProtocolState;
/**
* Signature Certificates/Identity Data Transfer Object.
*
* @author Frank Cornelis
*
*/
@ResponsesAllowed({ SignRequestMessage.class, FinishedMessage.class })
@ProtocolStateAllowed(ProtocolState.SIGN_CERTS)
public class SignCertificatesDataMessage extends AbstractProtocolMessage {
@HttpHeader(TYPE_HTTP_HEADER)
@MessageDiscriminator
public static final String TYPE = SignCertificatesDataMessage.class.getSimpleName();
@HttpHeader(HTTP_HEADER_PREFIX + "SignCertFileSize")
@NotNull
public Integer signCertFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "CaCertFileSize")
@NotNull
public Integer caCertFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "RootCaCertFileSize")
@NotNull
public Integer rootCertFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "IdentityFileSize")
public Integer identityFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "AddressFileSize")
public Integer addressFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "PhotoFileSize")
public Integer photoFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "IdentitySignatureFileSize")
public Integer identitySignatureFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "AddressSignatureFileSize")
public Integer addressSignatureFileSize;
@HttpHeader(HTTP_HEADER_PREFIX + "NationalRegistryCertFileSize")
public Integer rrnCertFileSize;
@HttpBody
@NotNull
public byte[] body;
/**
* Default constructor.
*/
public SignCertificatesDataMessage() {
super();
}
/**
* Main Constructor.
*
* @param signCertFile
* @param citizenCaCertFile
* @param rootCaCertFile
* @param identityFile
* optional
* @param addressFile
* optional
* @param photoFile
* optional
* @param identitySignFile
* optional
* @param addressSignFile
* optional
* @param nrnCertFile
* optional
* @throws IOException
*/
public SignCertificatesDataMessage(byte[] signCertFile, byte[] citizenCaCertFile, byte[] rootCaCertFile,
byte[] identityFile, byte[] addressFile, byte[] photoFile, byte[] identitySignFile, byte[] addressSignFile,
byte[] nrnCertFile) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(signCertFile);
this.signCertFileSize = signCertFile.length;
baos.write(citizenCaCertFile);
this.caCertFileSize = citizenCaCertFile.length;
baos.write(rootCaCertFile);
this.rootCertFileSize = rootCaCertFile.length;
if (null != identityFile) {
baos.write(identityFile);
this.identityFileSize = identityFile.length;
}
if (null != addressFile) {
baos.write(addressFile);
this.addressFileSize = addressFile.length;
}
if (null != photoFile) {
baos.write(photoFile);
this.photoFileSize = photoFile.length;
}
if (null != identitySignFile) {
baos.write(identitySignFile);
this.identitySignatureFileSize = identitySignFile.length;
}
if (null != addressSignFile) {
baos.write(addressSignFile);
this.addressSignatureFileSize = addressSignFile.length;
}
if (null != nrnCertFile) {
baos.write(nrnCertFile);
this.rrnCertFileSize = nrnCertFile.length;
}
this.body = baos.toByteArray();
}
public SignCertificatesDataMessage(X509Certificate[] signCertChain)
throws IOException, CertificateEncodingException {
this(signCertChain[0].getEncoded(), signCertChain[1].getEncoded(), signCertChain[2].getEncoded(), null, null,
null, null, null, null);
}
private byte[] copy(byte[] source, int idx, int count) {
byte[] result = new byte[count];
System.arraycopy(source, idx, result, 0, count);
return result;
}
@PostConstruct
public void postConstruct() {
int idx = 0;
byte[] signCertFile = copy(this.body, idx, this.signCertFileSize);
idx += this.signCertFileSize;
X509Certificate signCert = getCertificate(signCertFile);
byte[] citizenCaCertFile = copy(this.body, idx, this.caCertFileSize);
idx += this.caCertFileSize;
X509Certificate citizenCaCert = getCertificate(citizenCaCertFile);
byte[] rootCaCertFile = copy(this.body, idx, this.rootCertFileSize);
idx += this.rootCertFileSize;
this.rootCertificate = getCertificate(rootCaCertFile);
this.certificateChain = new LinkedList<X509Certificate>();
this.certificateChain.add(signCert);
this.certificateChain.add(citizenCaCert);
this.certificateChain.add(this.rootCertificate);
if (null != this.identityFileSize) {
this.identityData = copy(this.body, idx, this.identityFileSize);
idx += this.identityFileSize;
}
if (null != this.addressFileSize) {
this.addressData = copy(this.body, idx, this.addressFileSize);
idx += this.addressFileSize;
}
if (null != this.photoFileSize) {
this.photoData = copy(this.body, idx, this.photoFileSize);
idx += this.photoFileSize;
}
if (null != this.identitySignatureFileSize) {
this.identitySignatureData = copy(this.body, idx, this.identitySignatureFileSize);
idx += this.identitySignatureFileSize;
}
if (null != this.addressSignatureFileSize) {
this.addressSignatureData = copy(this.body, idx, this.addressSignatureFileSize);
idx += this.addressSignatureFileSize;
}
if (null != this.rrnCertFileSize) {
byte[] nrnCertData = copy(this.body, idx, this.rrnCertFileSize);
idx += this.rrnCertFileSize;
this.rrnCertificate = getCertificate(nrnCertData);
}
}
public byte[] identityData;
public byte[] addressData;
public byte[] photoData;
public byte[] identitySignatureData;
public byte[] addressSignatureData;
public X509Certificate rrnCertificate;
public X509Certificate rootCertificate;
private X509Certificate getCertificate(byte[] certData) {
CertificateFactory certificateFactory;
try {
certificateFactory = CertificateFactory.getInstance("X.509");
} catch (CertificateException e) {
throw new RuntimeException("cert factory error: " + e.getMessage(), e);
}
try {
X509Certificate certificate = (X509Certificate) certificateFactory
.generateCertificate(new ByteArrayInputStream(certData));
return certificate;
} catch (CertificateException e) {
/*
* Can happen in case of missing certificates. Missing certificates
* are represented by means of 1300 null bytes.
*/
return null;
}
}
public List<X509Certificate> certificateChain;
}