Red Hat Application Migration Toolkit
package ee.sk.digidoc; import ee.sk.digidoc.Base64Util; import ee.sk.digidoc.CertID; import ee.sk.digidoc.CertValue; import ee.sk.digidoc.CompleteCertificateRefs; import ee.sk.digidoc.CompleteRevocationRefs; import ee.sk.digidoc.DataFile; import ee.sk.digidoc.DigiDocException; import ee.sk.digidoc.KeyInfo; import ee.sk.digidoc.Manifest; import ee.sk.digidoc.ManifestFileEntry; import ee.sk.digidoc.Reference; import ee.sk.digidoc.Signature; import ee.sk.digidoc.SignatureProductionPlace; import ee.sk.digidoc.SignedInfo; import ee.sk.digidoc.UnsignedProperties; import ee.sk.digidoc.factory.DigiDocFactory; import ee.sk.digidoc.factory.DigiDocGenFactory; import ee.sk.digidoc.factory.DigiDocVerifyFactory; import ee.sk.digidoc.factory.DigiDocXmlGenFactory; import ee.sk.utils.ConfigManager; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.net.URL; import java.security.MessageDigest; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Hashtable; import java.util.zip.CRC32; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.log4j.Logger; public class SignedDoc implements Serializable { private static final long serialVersionUID = 1L; private String m_format; private String m_version; private ArrayList m_dataFiles; private ArrayList m_signatures; private Manifest m_manifest; private String m_mimeType; private String m_nsXmlDsig; private String m_nsXades; private String m_nsAsic; private String m_profile; private String m_comment; private Hashtable m_sigFormats; private long m_size; private String m_path; private String m_file; private static Logger m_logger = Logger.getLogger(SignedDoc.class); public static final String FORMAT_SK_XML = "SK-XML"; public static final String FORMAT_DIGIDOC_XML = "DIGIDOC-XML"; public static final String FORMAT_BDOC = "BDOC"; public static final String FORMAT_BDOC_MIME = "application/vnd.bdoc"; public static final String VERSION_1_0 = "1.0"; public static final String VERSION_1_1 = "1.1"; public static final String VERSION_1_2 = "1.2"; public static final String VERSION_1_3 = "1.3"; public static final String BDOC_VERSION_1_0 = "1.0"; public static final String BDOC_VERSION_1_1 = "1.1"; public static final String BDOC_VERSION_2_1 = "2.1"; public static final String BDOC_PROFILE_BES = "BES"; public static final String BDOC_PROFILE_T = "T"; public static final String BDOC_PROFILE_CL = "C-L"; public static final String BDOC_PROFILE_TM = "TM"; public static final String BDOC_PROFILE_TS = "TS"; public static final String BDOC_PROFILE_TMA = "TM-A"; public static final String BDOC_PROFILE_TSA = "TS-A"; public static final String SHA1_DIGEST_ALGORITHM = "http://www.w3.org/2000/09/xmldsig#sha1"; public static final String SHA1_DIGEST_TYPE = "SHA-1"; public static final String SHA1_DIGEST_TYPE_BAD = "SHA-1-00"; public static final String SHA256_DIGEST_ALGORITHM_1 = "http://www.w3.org/2001/04/xmlenc#sha256"; public static final String SHA256_DIGEST_ALGORITHM_2 = "http://www.w3.org/2001/04/xmldsig-more#sha256"; public static final String SHA256_DIGEST_TYPE = "SHA-256"; public static final String SHA224_DIGEST_TYPE = "SHA-224"; public static final String SHA224_DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#sha224"; public static final String SHA384_DIGEST_TYPE = "SHA-384"; public static final String SHA384_DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#sha384"; public static final String SHA512_DIGEST_TYPE = "SHA-512"; public static final String SHA512_DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmlenc#sha512"; public static final int SHA1_DIGEST_LENGTH = 20; public static final int SHA224_DIGEST_LENGTH = 28; public static final int SHA256_DIGEST_LENGTH = 32; public static final int SHA512_DIGEST_LENGTH = 64; public static final String CANONICALIZATION_METHOD_20010315 = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; public static final String CANONICALIZATION_METHOD_1_1 = "http://www.w3.org/2006/12/xml-c14n11"; public static final String TRANSFORM_20001026 = "http://www.w3.org/TR/2000/CR-xml-c14n-20001026"; public static final String RSA_SHA1_SIGNATURE_METHOD = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; public static final String RSA_SHA224_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224"; public static final String RSA_SHA256_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; public static final String RSA_SHA384_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"; public static final String RSA_SHA512_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; public static final String ECDSA_SHA1_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"; public static final String ECDSA_SHA224_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224"; public static final String ECDSA_SHA256_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"; public static final String ECDSA_SHA384_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"; public static final String ECDSA_SHA512_SIGNATURE_METHOD = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; public static final String DIGIDOC_DETATCHED_TRANSFORM = "http://www.sk.ee/2002/10/digidoc#detatched-document-signature"; public static final String ENVELOPED_TRANSFORM = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"; public static final String SIGNEDPROPERTIES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; public static String xmlns_xmldsig = "http://www.w3.org/2000/09/xmldsig#"; public static String xmlns_etsi = "http://uri.etsi.org/01903/v1.1.1#"; public static String xmlns_digidoc13 = "http://www.sk.ee/DigiDoc/v1.3.0#"; public static String xmlns_asic = "http://uri.etsi.org/02918/v1.2.1#"; public static final String LIB_NAME = "JDigiDoc"; public static final String LIB_VERSION = "3.9.0-726"; public static String xmlns_xades_123 = "http://uri.etsi.org/01903/v1.3.2#"; public static final String SIG_FILE_NAME = "META-INF/signature"; public static final String SIG_FILE_NAME_20 = "META-INF/signatures"; public static final String MIMET_FILE_NAME = "mimetype"; public static final String MIMET_FILE_CONTENT_10 = "application/vnd.bdoc-1.0"; public static final String MIMET_FILE_CONTENT_11 = "application/vnd.bdoc-1.1"; public static final String MIMET_FILE_CONTENT_20 = "application/vnd.etsi.asic-e+zip"; public static final String MANIF_DIR_META_INF = "META-INF"; public static final String MANIF_FILE_NAME = "META-INF/manifest.xml"; public static final String MIME_SIGNATURE_BDOC_ = "signature/bdoc-"; private static final String PEM_HDR1 = "-----BEGIN CERTIFICATE-----\n"; private static final String PEM_HDR2 = "\n-----END CERTIFICATE-----"; public SignedDoc() { this.m_format = null; this.m_version = null; this.m_dataFiles = null; this.m_signatures = null; this.m_manifest = null; this.m_mimeType = null; this.m_nsXmlDsig = null; this.m_nsXades = null; this.m_nsAsic = null; this.m_file = null; this.m_path = null; this.m_comment = null; } public SignedDoc(String format, String version) throws DigiDocException { this.setFormatAndVersion(format, version); this.m_dataFiles = null; this.m_signatures = null; this.m_manifest = null; this.m_mimeType = null; this.m_nsXmlDsig = null; this.m_nsXades = null; this.m_comment = null; if(format.equals("BDOC")) { this.m_manifest = new Manifest(); ManifestFileEntry fe = new ManifestFileEntry(this.getManifestEntry(version), "/"); this.m_manifest.addFileEntry(fe); this.setDefaultNsPref("BDOC"); } } public void setDefaultNsPref(String format) { if(format.equals("BDOC")) { this.m_nsXmlDsig = "ds"; this.m_nsXades = "xades"; this.m_nsAsic = "asic"; } if(format.equals("DIGIDOC-XML") || format.equals("SK-XML")) { this.m_nsXmlDsig = null; this.m_nsXades = null; this.m_nsAsic = null; } } private String getManifestEntry(String ver) { return ver.equals("1.0")?"application/vnd.bdoc-1.0":(ver.equals("1.1")?"application/vnd.bdoc-1.1":"application/vnd.etsi.asic-e+zip"); } public ManifestFileEntry findManifestEntryByPath(String fullPath) { return this.m_manifest.findFileEntryByPath(fullPath); } public String getFormat() { return this.m_format; } public void setFormat(String str) throws DigiDocException { DigiDocException ex = this.validateFormat(str); if(ex != null) { throw ex; } else { this.m_format = str; } } public ArrayList getDataFiles() { return this.m_dataFiles; } public void setDataFiles(ArrayList l) { this.m_dataFiles = l; } public ArrayList getSignatures() { return this.m_signatures; } public long getSize() { return this.m_size; } public void setSize(long l) { this.m_size = l; } public String getFile() { return this.m_file; } public void setFile(String fname) { this.m_file = fname; } public String getPath() { return this.m_path; } public void setPath(String p) { this.m_path = p; } public String getComment() { return this.m_comment; } public void setComment(String s) { this.m_comment = s; } public void addSignatureProfile(String sigId, String profile) { if(this.m_sigFormats == null) { this.m_sigFormats = new Hashtable(); } if(m_logger.isDebugEnabled()) { m_logger.debug("Register signature: " + sigId + " profile: " + profile); } this.m_sigFormats.put(sigId, profile); } public String findSignatureProfile(String sigId) { return this.m_sigFormats != null?(String)this.m_sigFormats.get(sigId):null; } public String getXmlDsigNs() { return this.m_nsXmlDsig; } public void setXmlDsigNs(String str) { this.m_nsXmlDsig = str; } public String getXadesNs() { return this.m_nsXades; } public void setXadesNs(String str) { this.m_nsXades = str; } public String getAsicNs() { return this.m_nsAsic; } public void setAsicNs(String str) { this.m_nsAsic = str; } public String getProfile() { return this.m_profile; } public void setProfile(String s) { this.m_profile = s; } private DigiDocException validateFormat(String str) { DigiDocException ex = null; if(str == null) { ex = new DigiDocException(13, "Format attribute is mandatory!", (Throwable)null); } else { if(!str.equals("BDOC") && !str.equals("SK-XML") && !str.equals("DIGIDOC-XML")) { ex = new DigiDocException(13, "Currently supports only SK-XML, DIGIDOC-XML and BDOC formats", (Throwable)null); } if(str.equals("BDOC")) { if(this.m_manifest == null) { this.m_manifest = new Manifest(); } if(this.m_manifest.findFileEntryByPath("/") == null) { ManifestFileEntry fe = new ManifestFileEntry(this.getManifestEntry(this.m_version), "/"); this.m_manifest.addFileEntry(fe); } this.setDefaultNsPref("BDOC"); } } return ex; } public String getVersion() { return this.m_version; } public void setVersion(String str) throws DigiDocException { DigiDocException ex = this.validateVersion(str); if(ex != null) { throw ex; } else { this.m_version = str; } } private DigiDocException validateVersion(String str) { DigiDocException ex = null; if(str == null) { ex = new DigiDocException(13, "Version attribute is mandatory!", (Throwable)null); } else if(this.m_format != null) { if(this.m_format.equals("SK-XML") && !str.equals("1.0")) { ex = new DigiDocException(13, "Format SK-XML supports only version 1.0", (Throwable)null); } if(this.m_format.equals("DIGIDOC-XML") && !str.equals("1.1") && !str.equals("1.2") && !str.equals("1.3")) { ex = new DigiDocException(13, "Format DIGIDOC-XML supports only versions 1.1, 1.2, 1.3", (Throwable)null); } if(this.m_format.equals("BDOC") && !str.equals("2.1")) { ex = new DigiDocException(13, "Format BDOC supports only versions 2.1", (Throwable)null); } } return ex; } public void setFormatAndVersion(String sFormat, String sVersion) throws DigiDocException { this.m_format = sFormat; this.m_version = sVersion; DigiDocException ex = this.validateFormatAndVersion(); if(ex != null) { throw ex; } } public DigiDocException validateFormatAndVersion() { Object ex = null; if(this.m_format != null && this.m_version != null) { if(!this.m_format.equals("DIGIDOC-XML") && !this.m_format.equals("SK-XML")) { if(!this.m_format.equals("BDOC")) { return new DigiDocException(13, "Invalid format attribute!", (Throwable)null); } if(!this.m_version.equals("2.1")) { return new DigiDocException(13, "Format BDOC supports only versions 2.1", (Throwable)null); } } else if(!this.m_version.equals("1.3")) { return new DigiDocException(13, "Only format DIGIDOC-XML version 1.3 is supported!", (Throwable)null); } return null; } else { return new DigiDocException(13, "Format and version attributes are mandatory!", (Throwable)null); } } public Manifest getManifest() { return this.m_manifest; } public void setManifest(Manifest m) { this.m_manifest = m; } public String getMimeType() { return this.m_mimeType; } public void setMimeType(String str) { this.m_mimeType = str; } public int countDataFiles() { return this.m_dataFiles == null?0:this.m_dataFiles.size(); } public void cleanupDfCache() { for(int i = 0; this.m_dataFiles != null && i < this.m_dataFiles.size(); ++i) { DataFile df = (DataFile)this.m_dataFiles.get(i); df.cleanupDfCache(); } } public InputStream findDataFileAsStream(String dfName) { try { if(this.m_file != null) { StringBuffer ex = new StringBuffer(); if(this.m_path != null) { ex.append(this.m_path); ex.append(File.separator); } ex.append(this.m_file); File fZip = new File(ex.toString()); if(fZip.isFile() && fZip.canRead()) { ZipFile zis = new ZipFile(fZip); ZipArchiveEntry ze = zis.getEntry(dfName); if(ze != null) { return zis.getInputStream(ze); } } } } catch (Exception var6) { m_logger.error("Error reading bdoc: " + var6); } return null; } public String getNewDataFileId() { int nDf = 0; String id = "D" + nDf; boolean bExists = false; do { bExists = false; for(int d = 0; d < this.countDataFiles(); ++d) { DataFile df = this.getDataFile(d); if(df.getId().equals(id)) { ++nDf; id = "D" + nDf; bExists = true; } } } while(bExists); return id; } public DataFile addDataFile(File inputFile, String mime, String contentType) throws DigiDocException { DigiDocException ex1 = this.validateFormatAndVersion(); if(ex1 != null) { throw ex1; } else { boolean bExists = false; for(int df = 0; df < this.countDataFiles(); ++df) { DataFile df1 = this.getDataFile(df); if(df1.getFileName().equals(inputFile.getName())) { bExists = true; } } if(bExists) { m_logger.error("Duplicate DataFile name: " + inputFile.getName()); throw new DigiDocException(28, "Duplicate DataFile filename: " + inputFile.getName(), (Throwable)null); } else { DataFile var8 = new DataFile(this.getNewDataFileId(), contentType, inputFile.getAbsolutePath(), mime, this); if(inputFile.canRead()) { var8.setSize(inputFile.length()); } this.addDataFile(var8); if(this.m_format.equals("BDOC")) { var8.setId(inputFile.getName()); } return var8; } } } public void writeToFile(File outputFile) throws DigiDocException { try { FileOutputStream ex = new FileOutputStream(outputFile); this.writeToStream(ex); ex.close(); } catch (DigiDocException var3) { throw var3; } catch (Exception var4) { DigiDocException.handleException(var4, 11); } } public void writeToStream(OutputStream os) throws DigiDocException { DigiDocException ex1 = this.validateFormatAndVersion(); if(ex1 != null) { throw ex1; } else { try { DigiDocXmlGenFactory ex = new DigiDocXmlGenFactory(this); if(this.m_format.equals("BDOC")) { ZipArchiveOutputStream i = new ZipArchiveOutputStream(os); i.setEncoding("UTF-8"); if(m_logger.isDebugEnabled()) { m_logger.debug("OS: " + (os != null?"OK":"NULL") + " zos: " + (i != null?"OK":"NULL")); } if(m_logger.isDebugEnabled()) { m_logger.debug("Writing: mimetype"); } ZipArchiveEntry sig = new ZipArchiveEntry("mimetype"); if(this.m_comment == null) { this.m_comment = DigiDocGenFactory.getUserInfo(this.m_format, this.m_version); } sig.setComment(this.m_comment); sig.setMethod(0); CRC32 crc = new CRC32(); if(this.m_version.equals("1.0")) { sig.setSize((long)"application/vnd.bdoc-1.0".getBytes().length); crc.update("application/vnd.bdoc-1.0".getBytes()); } if(this.m_version.equals("1.1")) { sig.setSize((long)"application/vnd.bdoc-1.1".getBytes().length); crc.update("application/vnd.bdoc-1.1".getBytes()); } if(this.m_version.equals("2.1")) { sig.setSize((long)"application/vnd.etsi.asic-e+zip".getBytes().length); crc.update("application/vnd.etsi.asic-e+zip".getBytes()); } sig.setCrc(crc.getValue()); i.putArchiveEntry(sig); if(this.m_version.equals("1.0")) { i.write("application/vnd.bdoc-1.0".getBytes()); } if(this.m_version.equals("1.1")) { i.write("application/vnd.bdoc-1.1".getBytes()); } if(this.m_version.equals("2.1")) { i.write("application/vnd.etsi.asic-e+zip".getBytes()); } i.closeArchiveEntry(); if(m_logger.isDebugEnabled()) { m_logger.debug("Writing: META-INF/manifest.xml"); } new ZipArchiveEntry("META-INF"); sig = new ZipArchiveEntry("META-INF/manifest.xml"); sig.setComment(DigiDocGenFactory.getUserInfo(this.m_format, this.m_version)); i.putArchiveEntry(sig); i.write(this.m_manifest.toXML()); i.closeArchiveEntry(); int i1; for(i1 = 0; i1 < this.countDataFiles(); ++i1) { DataFile sig1 = this.getDataFile(i1); if(m_logger.isDebugEnabled()) { m_logger.debug("Writing DF: " + sig1.getFileName() + " content: " + sig1.getContentType() + " df-cache: " + (sig1.getDfCacheFile() != null?sig1.getDfCacheFile().getAbsolutePath():"NONE")); } InputStream sFileName = null; if(sig1.hasAccessToDataFile()) { sFileName = sig1.getBodyAsStream(); } else { sFileName = this.findDataFileAsStream(sig1.getFileName()); } if(sFileName != null) { File sSig = new File(sig1.getFileName()); String sdata = sSig.getName(); sig = new ZipArchiveEntry(sdata); if(sig1.getComment() == null) { sig1.setComment(DigiDocGenFactory.getUserInfo(this.m_format, this.m_version)); } sig.setComment(sig1.getComment()); sig.setSize(sSig.length()); sig.setTime(sSig.lastModified()); i.putArchiveEntry(sig); byte[] data = new byte[2048]; boolean nRead = false; int nTotal = 0; crc = new CRC32(); int var24; while((var24 = sFileName.read(data)) > 0) { i.write(data, 0, var24); nTotal += var24; crc.update(data, 0, var24); } sig.setSize((long)nTotal); sig.setCrc(crc.getValue()); i.closeArchiveEntry(); sFileName.close(); } } for(i1 = 0; i1 < this.countSignatures(); ++i1) { Signature var20 = this.getSignature(i1); String var21 = var20.getPath(); if(var21 == null) { if(this.m_version.equals("2.1")) { var21 = "META-INF/signatures" + (i1 + 1) + ".xml"; } else { var21 = "META-INF/signature" + (i1 + 1) + ".xml"; } } if(!var21.startsWith("META-INF")) { var21 = "META-INF/" + var21; } if(m_logger.isDebugEnabled()) { m_logger.debug("Writing SIG: " + var21 + " orig: " + (var20.getOrigContent() != null?"OK":"NULL")); } sig = new ZipArchiveEntry(var21); if(var20.getComment() == null) { var20.setComment(DigiDocGenFactory.getUserInfo(this.m_format, this.m_version)); } sig.setComment(var20.getComment()); String var22 = var20.toString(); if(var22 == null || !var22.startsWith("<?xml")) { (new StringBuilder()).append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n").append(var22).toString(); } byte[] var23 = var20.getOrigContent(); if(var23 == null) { var23 = ex.signatureToXML(var20); } if(m_logger.isDebugEnabled()) { m_logger.debug("Writing SIG: " + var21 + " xml:\n---\n " + (var23 != null?new String(var23, "UTF-8"):"NULL") + "\n---\n "); } sig.setSize((long)var23.length); crc = new CRC32(); crc.update(var23); sig.setCrc(crc.getValue()); i.putArchiveEntry(sig); i.write(var23); i.closeArchiveEntry(); } i.close(); } else if(this.m_format.equals("DIGIDOC-XML")) { os.write(this.xmlHeader().getBytes()); int var17; for(var17 = 0; var17 < this.countDataFiles(); ++var17) { DataFile var18 = this.getDataFile(var17); var18.writeToFile(os); os.write("\n".getBytes()); } for(var17 = 0; var17 < this.countSignatures(); ++var17) { Signature var19 = this.getSignature(var17); if(var19.getOrigContent() != null) { os.write(var19.getOrigContent()); } else { os.write(ex.signatureToXML(var19)); } os.write("\n".getBytes()); } os.write(this.xmlTrailer().getBytes()); } } catch (DigiDocException var15) { throw var15; } catch (Exception var16) { DigiDocException.handleException(var16, 11); } } } public void addDataFile(DataFile df) throws DigiDocException { if(this.countSignatures() > 0) { throw new DigiDocException(14, "Cannot add DataFiles when signatures exist!", (Throwable)null); } else { boolean bExists = false; for(int sFile = 0; sFile < this.countDataFiles(); ++sFile) { DataFile fe = this.getDataFile(sFile); if(fe.getFileName().equals(df.getFileName())) { bExists = true; } } if(bExists) { m_logger.error("Duplicate DataFile name: " + df.getFileName()); throw new DigiDocException(28, "Duplicate DataFile filename: " + df.getFileName(), (Throwable)null); } else { if(this.m_format.equals("BDOC") && this.findManifestEntryByPath(df.getFileName()) == null) { df.setContentType("BINARY"); String var5 = df.getFileName(); if(var5 != null && var5.indexOf(47) != -1 || var5.indexOf(92) != -1) { File var6 = new File(var5); var5 = var6.getName(); } ManifestFileEntry var7 = new ManifestFileEntry(df.getMimeType(), var5); this.m_manifest.addFileEntry(var7); } if(this.m_dataFiles == null) { this.m_dataFiles = new ArrayList(); } if(df.getId() == null) { df.setId(this.getNewDataFileId()); } this.m_dataFiles.add(df); } } } public DataFile getDataFile(int idx) { return this.m_dataFiles != null && idx >= 0 && idx < this.m_dataFiles.size()?(DataFile)this.m_dataFiles.get(idx):null; } public DataFile getLastDataFile() { return this.m_dataFiles != null && this.m_dataFiles.size() > 0?(DataFile)this.m_dataFiles.get(this.m_dataFiles.size() - 1):null; } public void removeDataFile(int idx) throws DigiDocException { if(this.countSignatures() > 0) { throw new DigiDocException(14, "Cannot remove DataFiles when signatures exist!", (Throwable)null); } else { DataFile df = this.getDataFile(idx); if(df != null) { this.m_dataFiles.remove(idx); if(this.m_manifest != null) { this.m_manifest.removeFileEntryWithPath(df.getFileName()); } } else { throw new DigiDocException(29, "Invalid DataFile index!", (Throwable)null); } } } public DataFile findDataFileById(String id) { for(int i = 0; this.m_dataFiles != null && i < this.m_dataFiles.size(); ++i) { DataFile df = (DataFile)this.m_dataFiles.get(i); if(df.getId() != null && id != null && df.getId().equals(id)) { return df; } } return null; } public int countSignatures() { return this.m_signatures == null?0:this.m_signatures.size(); } public String getNewSignatureId() { int nS = 0; String id = "S" + nS; boolean bExists = false; do { bExists = false; for(int i = 0; i < this.countSignatures(); ++i) { Signature sig = this.getSignature(i); if(sig.getId().equals(id)) { ++nS; id = "S" + nS; bExists = true; } } } while(bExists); return id; } public Signature findSignatureById(String sigId) { for(int i = 0; i < this.countSignatures(); ++i) { Signature sig = this.getSignature(i); if(sig.getId().equals(sigId)) { return sig; } } return null; } public Signature findSignatureByPath(String path) { for(int i = 0; i < this.countSignatures(); ++i) { Signature sig = this.getSignature(i); if(sig.getPath() != null && sig.getPath().equals(path)) { return sig; } } return null; } public Signature prepareSignature(X509Certificate cert, String[] claimedRoles, SignatureProductionPlace adr) throws DigiDocException { DigiDocException ex1 = this.validateFormatAndVersion(); if(ex1 != null) { throw ex1; } else { return DigiDocGenFactory.prepareXadesBES(this, this.m_profile, cert, claimedRoles, adr, (String)null, (String)null, (String)null); } } public Signature prepareXadesTSignature(X509Certificate cert, String sigDatId, byte[] sigDatHash) throws DigiDocException { Signature sig = new Signature(this); sig.setId(this.getNewSignatureId()); SignedInfo si = new SignedInfo(sig, "http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); Reference ref = new Reference(si, "#" + sigDatId, "http://www.w3.org/2000/09/xmldsig#sha1", sigDatHash, "http://www.w3.org/TR/2000/CR-xml-c14n-20001026"); si.addReference(ref); sig.setSignedInfo(si); KeyInfo ki = new KeyInfo(cert); sig.setKeyInfo(ki); ki.setSignature(sig); CertValue cval = new CertValue((String)null, cert, 1, sig); sig.addCertValue(cval); CertID cid = new CertID(sig, cert, 1); sig.addCertID(cid); this.addSignature(sig); UnsignedProperties usp = new UnsignedProperties(sig, (CompleteCertificateRefs)null, (CompleteRevocationRefs)null); sig.setUnsignedProperties(usp); return sig; } public void addSignature(Signature sig) { if(this.m_signatures == null) { this.m_signatures = new ArrayList(); } this.m_signatures.add(sig); if(this.m_format != null && this.m_format.equals("BDOC")) { Signature sig1 = null; if(sig.getPath() != null) { sig1 = this.findSignatureByPath(sig.getPath()); } if(sig1 == null) { if(this.m_version.equals("2.1")) { sig.setPath("META-INF/signatures" + this.m_signatures.size() + ".xml"); } else { sig.setPath("META-INF/signature" + this.m_signatures.size() + ".xml"); } if(!this.m_version.equals("2.1")) { ManifestFileEntry fe = new ManifestFileEntry("signature/bdoc-" + this.m_version + "/" + sig.getProfile(), "META-INF/signature" + this.m_signatures.size() + ".xml"); this.m_manifest.addFileEntry(fe); if(m_logger.isDebugEnabled()) { m_logger.debug("Register in manifest new signature: " + sig.getId()); } } } } } public void readSignature(InputStream is) throws DigiDocException { DigiDocFactory ddfac = ConfigManager.instance().getDigiDocFactory(); ddfac.readSignature(this, is); } public Signature getSignature(int idx) { return this.m_signatures != null && idx >= 0 && idx < this.m_signatures.size()?(Signature)this.m_signatures.get(idx):null; } public void removeSignature(int idx) throws DigiDocException { if(this.m_signatures != null && idx >= 0 && idx < this.m_signatures.size()) { this.m_signatures.remove(idx); } else { throw new DigiDocException(36, "Invalid signature index: " + idx, (Throwable)null); } } public Signature getLastSignature() { return this.m_signatures != null && this.m_signatures.size() > 0?(Signature)this.m_signatures.get(this.m_signatures.size() - 1):null; } public void removeLastSiganture() { if(this.m_signatures.size() > 0) { this.m_signatures.remove(this.m_signatures.size() - 1); } } public int removeSignaturesWithoutValue() { int nRemove = 0; boolean bOk = true; do { bOk = true; for(int i = 0; this.m_signatures != null && i < this.m_signatures.size() && bOk; ++i) { Signature sig = (Signature)this.m_signatures.get(i); if(sig.getSignatureValue() == null || sig.getSignatureValue().getValue() == null || sig.getSignatureValue().getValue().length == 0) { this.m_signatures.remove(sig); if(m_logger.isDebugEnabled()) { m_logger.debug("Remove invalid sig: " + sig.getId()); } bOk = false; ++nRemove; } } } while(!bOk); return nRemove; } public ArrayList validate(boolean bStrong) { ArrayList errs = new ArrayList(); DigiDocException ex = this.validateFormat(this.m_format); if(ex != null) { errs.add(ex); } ex = this.validateVersion(this.m_version); if(ex != null) { errs.add(ex); } if(this.m_format != null && this.m_version != null && (this.m_format.equals("SK-XML") || this.m_format.equals("DIGIDOC-XML") && (this.m_version.equals("1.1") || this.m_version.equals("1.2")) || this.m_format.equals("BDOC") && (this.m_version.equals("1.0") || this.m_version.equals("1.1")))) { if(m_logger.isDebugEnabled()) { m_logger.debug("Old and unsupported format: " + this.m_format + " version: " + this.m_version); } ex = new DigiDocException(177, "Old and unsupported format: " + this.m_format + " version: " + this.m_version, (Throwable)null); errs.add(ex); } if(this.m_profile != null && (this.m_profile.equals("T") || this.m_profile.equals("TS") || this.m_profile.equals("TS-A"))) { if(m_logger.isDebugEnabled()) { m_logger.debug("T, TS and TSA profiles are currently not supported!"); } ex = new DigiDocException(81, "T, TS and TSA profiles are currently not supported!", (Throwable)null); errs.add(ex); } try { if(this.getFormat() != null && this.getFormat().equals("BDOC")) { DigiDocVerifyFactory.verifyManifestEntries(this, errs); } int ex2; ArrayList j; for(ex2 = 0; ex2 < this.countDataFiles(); ++ex2) { DataFile sig1 = this.getDataFile(ex2); j = sig1.validate(bStrong); if(!j.isEmpty()) { errs.addAll(j); } } Signature var9; for(ex2 = 0; ex2 < this.countSignatures(); ++ex2) { var9 = this.getSignature(ex2); j = var9.validate(); if(!j.isEmpty()) { errs.addAll(j); } } for(ex2 = 0; ex2 < this.countSignatures(); ++ex2) { var9 = this.getSignature(ex2); for(int var10 = 0; var10 < this.countSignatures(); ++var10) { Signature sig2 = this.getSignature(var10); if(this.getFormat() != null && this.getFormat().equals("BDOC") && sig2.getId() != null && var9.getId() != null && !sig2.getId().equals(var9.getId()) && sig2.getPath() != null && var9.getPath() != null && sig2.getPath().equals(var9.getPath())) { if(m_logger.isDebugEnabled()) { m_logger.debug("Signatures: " + var9.getId() + " and " + sig2.getId() + " are in same file: " + var9.getPath()); } ex = new DigiDocException(75, "More than one signature in signatures.xml file is unsupported", (Throwable)null); errs.add(ex); } } } } catch (DigiDocException var8) { errs.add(var8); } return errs; } public static boolean hasFatalErrs(ArrayList lerrs) { for(int i = 0; lerrs != null && i < lerrs.size(); ++i) { DigiDocException ex = (DigiDocException)lerrs.get(i); if(ex.getCode() == 75) { return true; } } return false; } public ArrayList verify(boolean checkDate, boolean demandConfirmation) { ArrayList errs = this.validate(true); if(hasFatalErrs(errs)) { return errs; } else { for(int i = 0; i < this.countSignatures(); ++i) { Signature sig = this.getSignature(i); ArrayList e = sig.verify(this, checkDate, demandConfirmation); if(!e.isEmpty()) { errs.addAll(e); } } if(this.countSignatures() == 0) { errs.add(new DigiDocException(98, "This document is not signed!", (Throwable)null)); } return errs; } } private String xmlHeader() { StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); if(this.m_format.equals("DIGIDOC-XML")) { sb.append("<SignedDoc format=\""); sb.append(this.m_format); sb.append("\" version=\""); sb.append(this.m_version); sb.append("\""); if(this.m_version.equals("1.3")) { sb.append(" xmlns=\""); sb.append(xmlns_digidoc13); sb.append("\""); } sb.append(">\n"); } return sb.toString(); } private String xmlTrailer() { return this.m_format.equals("DIGIDOC-XML")?"\n</SignedDoc>":""; } public String toXML() throws DigiDocException { StringBuffer sb = new StringBuffer(this.xmlHeader()); int i; String str; for(i = 0; i < this.countDataFiles(); ++i) { DataFile sig = this.getDataFile(i); str = sig.toString(); sb.append(str); sb.append("\n"); } for(i = 0; i < this.countSignatures(); ++i) { Signature var5 = this.getSignature(i); str = var5.toString(); sb.append(str); sb.append("\n"); } sb.append(this.xmlTrailer()); return sb.toString(); } public String toString() { String str = null; try { str = this.toXML(); } catch (Exception var3) { ; } return str; } public static byte[] digest(byte[] data) throws DigiDocException { return digestOfType(data, "SHA-1"); } public static byte[] digestOfType(byte[] data, String digType) throws DigiDocException { byte[] dig = null; try { MessageDigest ex = MessageDigest.getInstance(digType, "BC"); ex.update(data); dig = ex.digest(); } catch (Exception var4) { DigiDocException.handleException(var4, 54); } return dig; } private static String getDnPart(String sDn, String sField, String sOid) { if(sDn != null && sDn.length() > 0) { String s = sField + "="; boolean bQ = false; int n1 = sDn.toUpperCase().indexOf(s.toUpperCase()); if(n1 == -1 && sOid != null) { s = "OID." + sOid + "="; n1 = sDn.toUpperCase().indexOf(s.toUpperCase()); } if(n1 >= 0) { n1 += s.length(); if(sDn.charAt(n1) == 34) { bQ = true; ++n1; } int n2 = sDn.indexOf(bQ?"\", ":", ", n1); if(n2 == -1) { n2 = sDn.length(); } if(n2 > n1 && n2 <= sDn.length()) { return sDn.substring(n1, n2); } } } return null; } public static String getSubjectFirstName(X509Certificate cert) { String dn = getDN(cert); String name = null; String cn = getDnPart(dn, "CN", (String)null); if(cn != null) { int idx1; for(idx1 = 0; idx1 < cn.length() && cn.charAt(idx1) != 44; ++idx1) { ; } if(idx1 < cn.length()) { ++idx1; } int idx2; for(idx2 = idx1; idx2 < cn.length() && cn.charAt(idx2) != 44 && cn.charAt(idx2) != 47; ++idx2) { ; } name = cn.substring(idx1, idx2); } return name; } public static String getSubjectLastName(X509Certificate cert) { String dn = getDN(cert); String name = null; String cn = getDnPart(dn, "CN", (String)null); if(cn != null) { int idx1; for(idx1 = 0; idx1 < cn.length() && !Character.isLetter(cn.charAt(idx1)); ++idx1) { ; } int idx2; for(idx2 = idx1; idx2 < cn.length() && cn.charAt(idx2) != 44 && dn.charAt(idx2) != 47; ++idx2) { ; } name = cn.substring(idx1, idx2); } return name; } public static String getSubjectPersonalCode(X509Certificate cert) { String dn = getDN(cert); String code = getDnPart(dn, "SERIALNUMBER", "2.5.4.5"); if(code != null) { return code; } else { String cn = getDnPart(dn, "CN", (String)null); if(cn != null) { int idx1; for(idx1 = 0; idx1 < cn.length() && !Character.isDigit(cn.charAt(idx1)); ++idx1) { ; } int idx2; for(idx2 = idx1; idx2 < cn.length() && Character.isDigit(cn.charAt(idx2)); ++idx2) { ; } if(idx2 > idx1 + 7) { code = cn.substring(idx1, idx2); } } return code; } } private static String getDN(X509Certificate cert) { return cert.getSubjectX500Principal().getName("RFC1779"); } public static String getCommonName(String dn) { return getDnPart(dn, "CN", (String)null); } public static X509Certificate readCertificate(byte[] data) throws DigiDocException { X509Certificate cert = null; try { ByteArrayInputStream ex = new ByteArrayInputStream(data); CertificateFactory cf = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)cf.generateCertificate(ex); ex.close(); return cert; } catch (Exception var4) { m_logger.error("Error reading certificate: " + var4); return null; } } public static byte[] readFile(File inFile) throws IOException, FileNotFoundException { Object data = null; FileInputStream is = new FileInputStream(inFile); DataInputStream dis = new DataInputStream(is); byte[] data1 = new byte[dis.available()]; dis.readFully(data1); dis.close(); is.close(); return data1; } public static X509Certificate readCertificate(File certFile) throws DigiDocException { X509Certificate cert = null; try { FileInputStream ex = new FileInputStream(certFile); CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)certificateFactory.generateCertificate(ex); ex.close(); } catch (Exception var4) { DigiDocException.handleException(var4, 10); } return cert; } public static boolean writeCertificate(X509Certificate cert, File certFile) throws DigiDocException { try { FileOutputStream ex = new FileOutputStream(certFile); ex.write("-----BEGIN CERTIFICATE-----\n".getBytes()); ex.write(Base64Util.encode(cert.getEncoded()).getBytes()); ex.write("\n-----END CERTIFICATE-----".getBytes()); ex.close(); } catch (Exception var3) { DigiDocException.handleException(var3, 10); } return false; } public static X509Certificate readCertificate(String certLocation) throws DigiDocException { X509Certificate cert = null; try { Object ex = null; URL url = null; if(certLocation.startsWith("http")) { url = new URL(certLocation); ex = url.openStream(); } else if(certLocation.startsWith("jar://")) { ClassLoader certificateFactory = ConfigManager.instance().getClass().getClassLoader(); ex = certificateFactory.getResourceAsStream(certLocation.substring(6)); } else { ex = new FileInputStream(certLocation); } CertificateFactory certificateFactory1 = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)certificateFactory1.generateCertificate((InputStream)ex); ((InputStream)ex).close(); } catch (Exception var5) { DigiDocException.handleException(var5, 10); } return cert; } public static boolean compareDigests(byte[] dig1, byte[] dig2) { boolean ok = dig1 != null && dig2 != null && dig1.length == dig2.length; for(int i = 0; ok && i < dig1.length; ++i) { if(dig1[i] != dig2[i]) { ok = false; } } return ok; } public static byte[] hex2bin(String hexString) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { for(int ex = 0; hexString != null && ex < hexString.length(); ex += 2) { String tmp = hexString.substring(ex, ex + 2); Integer x = new Integer(Integer.parseInt(tmp, 16)); bos.write(x.byteValue()); } } catch (Exception var5) { m_logger.error("Error converting hex string: " + var5); } return bos.toByteArray(); } public static String bin2hex(byte[] arr) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < arr.length; ++i) { String str = Integer.toHexString(arr[i]); if(str.length() == 2) { sb.append(str); } if(str.length() < 2) { sb.append("0"); sb.append(str); } if(str.length() > 2) { sb.append(str.substring(str.length() - 2)); } } return sb.toString(); } }