/* * CompleteRevocationRefs.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.Serializable; import java.util.Date; import java.util.ArrayList; import es.uji.security.crypto.openxades.digidoc.utils.ConvertUtils; import es.uji.security.util.Base64; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * Models the ETSI CompleteRevocationRefs element This contains some data from the OCSP response and * it's digest * * @author Veiko Sinivee * @version 1.0 */ public class CompleteRevocationRefs implements Serializable { /** <OCSPIdentifier> URI attribute */ private String m_uri; /** <ResponderId> element */ private String m_responderId; /** ProducedAt element */ private Date m_producedAt; /** digesta lgorithm uri/id */ private String m_digestAlgorithm; /** digest value */ private byte[] m_digestValue; /** parent object - UnsignedProperties ref */ private UnsignedProperties m_unsignedProps; /** * Creates new CompleteRevocationRefs Initializes everything to null */ public CompleteRevocationRefs() { m_uri = null; m_responderId = null; m_producedAt = null; m_digestAlgorithm = null; m_digestValue = null; m_unsignedProps = null; } /** * Creates new CompleteRevocationRefs * * @param uri * notary uri value * @param respId * responder id * @param producedAt * OCSP producedAt timestamp * @param digAlg * notary digest algorithm * @param digest * notary digest * @throws DigiDocException * for validation errors */ public CompleteRevocationRefs(String uri, String respId, Date producedAt, String digAlg, byte[] digest) throws DigiDocException { setUri(uri); setResponderId(respId); setProducedAt(producedAt); setDigestAlgorithm(digAlg); setDigestValue(digest); } /** * Creates new CompleteRevocationRefs by using data from an existing Notary object * * @param not * Notary object * @throws DigiDocException * for validation errors */ public CompleteRevocationRefs(Notary not) throws DigiDocException { setUri("#" + not.getId()); setResponderId(not.getResponderId()); setProducedAt(not.getProducedAt()); setDigestAlgorithm(SignedDoc.SHA1_DIGEST_ALGORITHM); byte[] digest = null; try { byte[] ocspData = not.getOcspResponseData(); digest = SignedDoc.digest(ocspData); // System.out.println("OCSP data len: " + ocspData.length); // System.out.println("Calculated digest: " + Base64Util.encode(digest, 0)); } catch (Exception ex) { DigiDocException.handleException(ex, DigiDocException.ERR_CALCULATE_DIGEST); } setDigestValue(digest); } /** * Accessor for UnsignedProperties attribute * * @return value of UnsignedProperties attribute */ public UnsignedProperties getUnsignedProperties() { return m_unsignedProps; } /** * Mutator for UnsignedProperties attribute * * @param uprops * value of UnsignedProperties attribute */ public void setUnsignedProperties(UnsignedProperties uprops) { m_unsignedProps = uprops; } /** * Accessor for uri attribute * * @return value of uri attribute */ public String getUri() { return m_uri; } /** * Mutator for uri attribute * * @param str * new value for uri attribute * @throws DigiDocException * for validation errors */ public void setUri(String str) throws DigiDocException { DigiDocException ex = validateUri(str); if (ex != null) throw ex; m_uri = str; } /** * Helper method to validate an uri * * @param str * input data * @return exception or null for ok */ private DigiDocException validateUri(String str) { DigiDocException ex = null; if (str == null) ex = new DigiDocException(DigiDocException.ERR_REVREFS_URI, "Notary uri must be in form: #<notary-id>", null); return ex; } /** * Accessor for responderId attribute * * @return value of responderId attribute */ public String getResponderId() { return m_responderId; } /** * Mutator for responderId attribute * * @param str * new value for responderId attribute * @throws DigiDocException * for validation errors */ public void setResponderId(String str) throws DigiDocException { DigiDocException ex = validateResponderId(str); if (ex != null) throw ex; m_responderId = str; } /** * Returns reponder-ids CN * * @returns reponder-ids CN or null */ public String getResponderCommonName() { String name = null; if (m_responderId != null) { int idx1 = m_responderId.indexOf("CN="); if (idx1 != -1) { idx1 += 2; while (idx1 < m_responderId.length() && !Character.isLetter(m_responderId.charAt(idx1))) idx1++; int idx2 = idx1; while (idx2 < m_responderId.length() && m_responderId.charAt(idx2) != ',' && m_responderId.charAt(idx2) != '/') idx2++; name = m_responderId.substring(idx1, idx2); } } return name; } /** * Helper method to validate a ResponderId * * @param str * input data * @return exception or null for ok */ private DigiDocException validateResponderId(String str) { DigiDocException ex = null; if (str == null) ex = new DigiDocException(DigiDocException.ERR_REVREFS_RESP_ID, "ResponderId cannot be empty!", null); return ex; } /** * Accessor for producedAt attribute * * @return value of producedAt attribute */ public Date getProducedAt() { return m_producedAt; } /** * Mutator for producedAt attribute * * @param str * new value for producedAt attribute * @throws DigiDocException * for validation errors */ public void setProducedAt(Date d) throws DigiDocException { DigiDocException ex = validateProducedAt(d); if (ex != null) throw ex; m_producedAt = d; } /** * Helper method to validate producedAt timestamp * * @param str * input data * @return exception or null for ok */ private DigiDocException validateProducedAt(Date d) { DigiDocException ex = null; if (d == null) ex = new DigiDocException(DigiDocException.ERR_REVREFS_PRODUCED_AT, "ProducedAt timestamp cannot be empty!", null); return ex; } /** * Accessor for digestAlgorithm attribute * * @return value of digestAlgorithm attribute */ public String getDigestAlgorithm() { return m_digestAlgorithm; } /** * Mutator for digestAlgorithm attribute * * @param str * new value for digestAlgorithm attribute * @throws DigiDocException * for validation errors */ public void setDigestAlgorithm(String str) throws DigiDocException { DigiDocException ex = validateDigestAlgorithm(str); if (ex != null) throw ex; m_digestAlgorithm = str; } /** * Helper method to validate a digest algorithm * * @param str * input data * @return exception or null for ok */ private DigiDocException validateDigestAlgorithm(String str) { DigiDocException ex = null; if (str == null || !str.equals(SignedDoc.SHA1_DIGEST_ALGORITHM)) ex = new DigiDocException(DigiDocException.ERR_CERT_DIGEST_ALGORITHM, "Currently supports only SHA1 digest algorithm", null); return ex; } /** * Accessor for digestValue attribute * * @return value of digestValue attribute */ public byte[] getDigestValue() { return m_digestValue; } /** * Mutator for digestValue attribute * * @param data * new value for digestValue attribute * @throws DigiDocException * for validation errors */ public void setDigestValue(byte[] data) throws DigiDocException { DigiDocException ex = validateDigestValue(data); if (ex != null) throw ex; m_digestValue = data; } /** * Helper method to validate a digest value * * @param data * input data * @return exception or null for ok */ private DigiDocException validateDigestValue(byte[] data) { DigiDocException ex = null; if (data == null || data.length != SignedDoc.SHA1_DIGEST_LENGTH) ex = new DigiDocException(DigiDocException.ERR_DIGEST_LENGTH, "SHA1 digest data is allways 20 bytes of length", null); return ex; } /** * Helper method to validate the whole CompleteRevocationRefs object * * @return a possibly empty list of DigiDocException objects */ public ArrayList validate() { ArrayList errs = new ArrayList(); DigiDocException ex = validateUri(m_uri); if (ex != null) errs.add(ex); ex = validateResponderId(m_responderId); if (ex != null) errs.add(ex); ex = validateProducedAt(m_producedAt); if (ex != null) errs.add(ex); ex = validateDigestAlgorithm(m_digestAlgorithm); if (ex != null) errs.add(ex); ex = validateDigestValue(m_digestValue); if (ex != null) errs.add(ex); return errs; } /** * Converts the CompleteRevocationRefs to XML form * * @return XML representation of CompleteRevocationRefs */ public byte[] toXML() throws DigiDocException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { bos.write(ConvertUtils.str2data("<CompleteRevocationRefs>\n")); bos.write(ConvertUtils.str2data("<OCSPRefs>\n<OCSPRef>\n")); bos.write(ConvertUtils.str2data("<OCSPIdentifier URI=\"")); bos.write(ConvertUtils.str2data(m_uri)); bos.write(ConvertUtils.str2data("\">\n<ResponderID>")); bos.write(ConvertUtils.str2data(m_responderId)); bos.write(ConvertUtils.str2data("</ResponderID>\n<ProducedAt>")); bos.write(ConvertUtils.str2data(ConvertUtils.date2string(m_producedAt, m_unsignedProps .getSignature().getSignedDoc()))); bos .write(ConvertUtils .str2data("</ProducedAt>\n</OCSPIdentifier>\n<DigestAlgAndValue>\n<DigestMethod Algorithm=\"")); bos.write(ConvertUtils.str2data(m_digestAlgorithm)); bos.write(ConvertUtils.str2data("\"></DigestMethod>\n<DigestValue>")); bos.write(ConvertUtils.str2data(Base64.encodeBytes(m_digestValue))); bos.write(ConvertUtils.str2data("</DigestValue>\n</DigestAlgAndValue>")); bos.write(ConvertUtils.str2data("</OCSPRef>\n</OCSPRefs>\n")); bos.write(ConvertUtils.str2data("</CompleteRevocationRefs>")); } catch (IOException ex) { DigiDocException.handleException(ex, DigiDocException.ERR_XML_CONVERT); } return bos.toByteArray(); } /** * Returns the stringified form of CompleteRevocationRefs * * @return CompleteRevocationRefs string representation */ public String toString() { String str = null; try { str = new String(toXML()); } catch (Exception ex) { } return str; } }