/*
* KeyInfo.java
* PROJECT: JDigiDoc
* DESCRIPTION: Digi Doc functions for creating
* and reading signed documents.
* AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia
*==================================================
* Copyright (C) AS Sertifitseerimiskeskus
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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.
* GNU Lesser General Public Licence is available at
* http://www.gnu.org/copyleft/lesser.html
*==================================================
*/
package es.uji.security.crypto.openxades.digidoc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import es.uji.security.crypto.openxades.digidoc.utils.ConvertUtils;
import es.uji.security.util.Base64;
/**
* Models the KeyInfo block of an XML-DSIG signature. In DigiDoc library the key info allways
* contains only one subject certificate, e.g. no uplinks and the smaller items like RSA public key
* modulus and export are not kept separately but calculated online from the signers certificate.
* That means they are read-only attributes.
*
* @author Veiko Sinivee
* @version 1.0
*/
public class KeyInfo implements Serializable
{
/** parent object - Signature ref */
private Signature m_signature;
/**
* Creates new KeyInfo
*/
public KeyInfo()
{
m_signature = null;
}
/**
* Creates new KeyInfo
*
* @param cert
* signers certificate
*/
public KeyInfo(X509Certificate cert) throws DigiDocException
{
setSignersCertificate(cert);
}
/**
* Accessor for Signature attribute
*
* @return value of Signature attribute
*/
public Signature getSignature()
{
return m_signature;
}
/**
* Mutator for Signature attribute
*
* @param uprops
* value of Signature attribute
*/
public void setSignature(Signature sig)
{
m_signature = sig;
}
/**
* Accessor for signersCert attribute
*
* @return value of signersCert attribute
*/
public X509Certificate getSignersCertificate()
{
X509Certificate cert = null;
if (m_signature != null)
{
CertValue cval = m_signature.getCertValueOfType(CertValue.CERTVAL_TYPE_SIGNER);
if (cval != null)
{
cert = cval.getCert();
}
}
return cert;
}
/**
* return certificate owners first name
*
* @return certificate owners first name or null
*/
public String getSubjectFirstName()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return SignedDoc.getSubjectFirstName(cert);
else
return null;
}
/**
* return certificate owners subject DN
*
* @return certificate owners subject DN or null
*
*/
public String getSubjectDN()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return cert.getSubjectDN().toString();
else
return null;
}
/**
* return certificate owners last name
*
* @return certificate owners last name or null
*/
public String getSubjectLastName()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return SignedDoc.getSubjectLastName(cert);
else
return null;
}
/**
* return certificate owners personal code
*
* @return certificate owners personal code or null
*/
public String getSubjectPersonalCode()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return SignedDoc.getSubjectPersonalCode(cert);
else
return null;
}
/**
* Mutator for signersCert attribute
*
* @param cert
* new value for signersCert attribute
* @throws DigiDocException
* for validation errors
*/
public void setSignersCertificate(X509Certificate cert) throws DigiDocException
{
DigiDocException ex = validateSignersCertificate(cert);
if (ex != null)
throw ex;
if (m_signature != null)
{
CertValue cval = m_signature.getOrCreateCertValueOfType(CertValue.CERTVAL_TYPE_SIGNER);
cval.setCert(cert);
}
}
/**
* Helper method to validate a signers cert
*
* @param cert
* input data
* @return exception or null for ok
*/
private DigiDocException validateSignersCertificate(X509Certificate cert)
{
DigiDocException ex = null;
if (cert == null)
ex = new DigiDocException(DigiDocException.ERR_SIGNERS_CERT,
"Signers certificate is required", null);
return ex;
}
/**
* return the signers certificates key modulus
*
* @return signers certificates key modulus
*/
public BigInteger getSignerKeyModulus()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return ((RSAPublicKey) cert.getPublicKey()).getModulus();
else
return null;
}
/**
* return the signers certificates key exponent
*
* @return signers certificates key exponent
*/
public BigInteger getSignerKeyExponent()
{
X509Certificate cert = getSignersCertificate();
if (cert != null)
return ((RSAPublicKey) cert.getPublicKey()).getPublicExponent();
else
return null;
}
/**
* Helper method to validate the whole KeyInfo object
*
* @return a possibly empty list of DigiDocException objects
*/
public ArrayList validate()
{
ArrayList errs = new ArrayList();
DigiDocException ex = null;
X509Certificate cert = getSignersCertificate();
if (cert != null)
ex = validateSignersCertificate(cert);
if (ex != null)
errs.add(ex);
return errs;
}
/**
* Converts the KeyInfo to XML form
*
* @return XML representation of KeyInfo
*/
public byte[] toXML() throws DigiDocException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
bos.write(ConvertUtils.str2data("<KeyInfo>\n"));
bos.write(ConvertUtils.str2data("<KeyValue>\n<RSAKeyValue>\n<Modulus>"));
bos.write(ConvertUtils.str2data(Base64.encodeBytes(getSignerKeyModulus().toByteArray())));
bos.write(ConvertUtils.str2data("</Modulus>\n<Exponent>"));
bos.write(ConvertUtils.str2data(Base64.encodeBytes(getSignerKeyExponent().toByteArray())));
bos.write(ConvertUtils.str2data("</Exponent>\n</RSAKeyValue>\n</KeyValue>\n"));
bos.write(ConvertUtils.str2data("<X509Data>"));
CertValue cval = null;
if (m_signature != null)
{
cval = m_signature.getCertValueOfType(CertValue.CERTVAL_TYPE_SIGNER);
if (cval != null)
bos.write(cval.toXML());
}
bos.write(ConvertUtils.str2data("</X509Data>"));
if (getSubjectDN() != null)
{
bos.write(ConvertUtils.str2data("<X509Data><X509SubjectName>"));
if (m_signature != null)
{
if (cval != null)
bos.write(getSubjectDN().getBytes());
}
bos.write(ConvertUtils.str2data("</X509SubjectName></X509Data>"));
}
bos.write(ConvertUtils.str2data("</KeyInfo>"));
}
catch (IOException ex)
{
DigiDocException.handleException(ex, DigiDocException.ERR_XML_CONVERT);
}
return bos.toByteArray();
}
/**
* return the stringified form of KeyInfo
*
* @return KeyInfo string representation
*/
public String toString()
{
String str = null;
try
{
str = new String(toXML());
}
catch (Exception ex)
{
}
return str;
}
}