From 13d6dc3a6a5e8bd3c17997351a0e6f087eb301a2 Mon Sep 17 00:00:00 2001 From: tknall Date: Tue, 25 Nov 2008 12:04:30 +0000 Subject: Removing itext from source. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@302 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- src/main/java/com/lowagie/text/pdf/PdfPKCS7.java | 1276 ---------------------- 1 file changed, 1276 deletions(-) delete mode 100644 src/main/java/com/lowagie/text/pdf/PdfPKCS7.java (limited to 'src/main/java/com/lowagie/text/pdf/PdfPKCS7.java') diff --git a/src/main/java/com/lowagie/text/pdf/PdfPKCS7.java b/src/main/java/com/lowagie/text/pdf/PdfPKCS7.java deleted file mode 100644 index d9f3473..0000000 --- a/src/main/java/com/lowagie/text/pdf/PdfPKCS7.java +++ /dev/null @@ -1,1276 +0,0 @@ -/* - * Copyright 2004 by Paulo Soares. - * - * The contents of this file are subject to the Mozilla Public License Version 1.1 - * (the "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the License. - * - * The Original Code is 'iText, a free JAVA-PDF library'. - * - * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by - * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. - * All Rights Reserved. - * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer - * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. - * - * Contributor(s): all the names of the contributors are added in the source code - * where applicable. - * - * Alternatively, the contents of this file may be used under the terms of the - * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the - * provisions of LGPL are applicable instead of those above. If you wish to - * allow use of your version of this file only under the terms of the LGPL - * License and not to allow others to use your version of this file under - * the MPL, indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by the LGPL. - * If you do not delete the provisions above, a recipient may use your version - * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the MPL as stated above or under the terms of the GNU - * Library General Public License as published by the Free Software Foundation; - * either version 2 of the License, or 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 Library general Public License for more - * details. - * - * If you didn't download this code from the following link, you should check if - * you aren't using an obsolete version: - * http://www.lowagie.com/iText/ - */ -package com.lowagie.text.pdf; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.FileInputStream; -import java.math.BigInteger; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.Signature; -import java.security.MessageDigest; -import java.security.SignatureException; -import java.security.cert.CRL; -import java.security.cert.CRLException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.security.KeyStore; -import java.io.File; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.Calendar; -import java.util.GregorianCalendar; -import com.lowagie.text.ExceptionConverter; - -import com.lowagie.bc.asn1.ASN1InputStream; -import com.lowagie.bc.asn1.DERObject; -import com.lowagie.bc.asn1.ASN1Sequence; -import com.lowagie.bc.asn1.ASN1Set; -import com.lowagie.bc.asn1.DERObjectIdentifier; -import com.lowagie.bc.asn1.DEROctetString; -import com.lowagie.bc.asn1.DERTaggedObject; -import com.lowagie.bc.asn1.DERInteger; -import com.lowagie.bc.asn1.ASN1TaggedObject; -import com.lowagie.bc.asn1.DERConstructedSet; -import com.lowagie.bc.asn1.DERSequence; -import com.lowagie.bc.asn1.DERNull; -import com.lowagie.bc.asn1.ASN1EncodableVector; -import com.lowagie.bc.asn1.DERSet; -import com.lowagie.bc.asn1.DERString; -import com.lowagie.bc.asn1.DERUTCTime; -import com.lowagie.bc.asn1.ASN1OutputStream; - -/** - * This class does all the processing related to signing and verifying a PKCS#7 - * signature. - *

- * It's based in code found at org.bouncycastle. - */ -public class PdfPKCS7 { - - private byte sigAttr[]; - private byte digestAttr[]; - private int version, signerversion; - private Set digestalgos; - private Collection certs, crls; - private X509Certificate signCert; - private byte[] digest; - private MessageDigest messageDigest; - private String digestAlgorithm, digestEncryptionAlgorithm; - private Signature sig; - private transient PrivateKey privKey; - private byte RSAdata[]; - private boolean verified; - private boolean verifyResult; - private byte externalDigest[]; - private byte externalRSAdata[]; - - private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1"; - private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2"; - private static final String ID_MD5 = "1.2.840.113549.2.5"; - private static final String ID_MD2 = "1.2.840.113549.2.2"; - private static final String ID_SHA1 = "1.3.14.3.2.26"; - private static final String ID_RSA = "1.2.840.113549.1.1.1"; - private static final String ID_DSA = "1.2.840.10040.4.1"; - private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3"; - private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4"; - private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5"; - private static final String ID_MD2RSA = "1.2.840.113549.1.1.2"; - private static final String ID_MD5RSA = "1.2.840.113549.1.1.4"; - private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5"; - /** - * Holds value of property reason. - */ - private String reason; - - /** - * Holds value of property location. - */ - private String location; - - /** - * Holds value of property signDate. - */ - private Calendar signDate; - - /** - * Holds value of property signName. - */ - private String signName; - - /** - * Verifies a signature using the sub-filter adbe.x509.rsa_sha1. - * @param contentsKey the /Contents key - * @param certsKey the /Cert key - * @param provider the provider or null for the default provider - * @throws SecurityException on error - * @throws CRLException on error - * @throws InvalidKeyException on error - * @throws CertificateException on error - * @throws NoSuchProviderException on error - * @throws NoSuchAlgorithmException on error - * @throws IOException on error - */ - public PdfPKCS7(byte[] contentsKey, byte[] certsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException { - CertificateFactory cf; - if (provider == null) - cf = CertificateFactory.getInstance("X.509"); - else - cf = CertificateFactory.getInstance("X.509", provider); - if (provider == null) - certs = cf.generateCertificates(new ByteArrayInputStream(certsKey)); - signCert = (X509Certificate)certs.iterator().next(); - crls = new ArrayList(); - ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey)); - digest = ((DEROctetString)in.readObject()).getOctets(); - if (provider == null) - sig = Signature.getInstance("SHA1withRSA"); - else - sig = Signature.getInstance("SHA1withRSA", provider); - sig.initVerify(signCert.getPublicKey()); - } - - /** - * Verifies a signature using the sub-filter adbe.pkcs7.detached or - * adbe.pkcs7.sha1. - * @param contentsKey the /Contents key - * @param provider the provider or null for the default provider - * @throws SecurityException on error - * @throws CRLException on error - * @throws InvalidKeyException on error - * @throws CertificateException on error - * @throws NoSuchProviderException on error - * @throws NoSuchAlgorithmException on error - */ - public PdfPKCS7(byte[] contentsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException { - ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey)); - - // - // Basic checks to make sure it's a PKCS#7 SignedData Object - // - DERObject pkcs; - - try { - pkcs = din.readObject(); - } - catch (IOException e) { - throw new SecurityException("can't decode PKCS7SignedData object"); - } - if (!(pkcs instanceof ASN1Sequence)) { - throw new SecurityException("Not a valid PKCS#7 object - not a sequence"); - } - ASN1Sequence signedData = (ASN1Sequence)pkcs; - DERObjectIdentifier objId = (DERObjectIdentifier)signedData.getObjectAt(0); - if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA)) - throw new SecurityException("Not a valid PKCS#7 object - not signed data"); - ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject(); - // the positions that we care are: - // 0 - version - // 1 - digestAlgorithms - // 2 - possible ID_PKCS7_DATA - // (the certificates and crls are taken out by other means) - // last - signerInfos - - // the version - version = ((DERInteger)content.getObjectAt(0)).getValue().intValue(); - - // the digestAlgorithms - digestalgos = new HashSet(); - Enumeration e = ((ASN1Set)content.getObjectAt(1)).getObjects(); - while (e.hasMoreElements()) - { - ASN1Sequence s = (ASN1Sequence)e.nextElement(); - DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0); - digestalgos.add(o.getId()); - } - - // the certificates and crls - CertificateFactory cf; - if (provider == null) - cf = CertificateFactory.getInstance("X.509"); - else - cf = CertificateFactory.getInstance("X.509", provider); - certs = cf.generateCertificates(new ByteArrayInputStream(contentsKey)); - crls = cf.generateCRLs(new ByteArrayInputStream(contentsKey)); - - // the possible ID_PKCS7_DATA - ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2); - if (rsaData.size() > 1) { - DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject(); - RSAdata = rsaDataContent.getOctets(); - } - - // the signerInfos - int next = 3; - while (content.getObjectAt(next) instanceof DERTaggedObject) - ++next; - ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next); - if (signerInfos.size() != 1) - throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time"); - ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0); - // the positions that we care are - // 0 - version - // 1 - the signing certificate serial number - // 2 - the digest algorithm - // 3 or 4 - digestEncryptionAlgorithm - // 4 or 5 - encryptedDigest - signerversion = ((DERInteger)signerInfo.getObjectAt(0)).getValue().intValue(); - // Get the signing certificate - ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1); - BigInteger serialNumber = ((DERInteger)issuerAndSerialNumber.getObjectAt(1)).getValue(); - for (Iterator i = certs.iterator(); i.hasNext();) { - X509Certificate cert = (X509Certificate)i.next(); - if (serialNumber.equals(cert.getSerialNumber())) { - signCert = cert; - break; - } - } - if (signCert == null) { - throw new SecurityException("Can't find signing certificate with serial " + serialNumber.toString(16)); - } - digestAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId(); - next = 3; - if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) { - ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next); - ASN1Sequence sseq = (ASN1Sequence)tagsig.getObject(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream dout = new ASN1OutputStream(bOut); - try { - ASN1EncodableVector attribute = new ASN1EncodableVector(); - for (int k = 0; k < sseq.size(); ++k) { - attribute.add(sseq.getObjectAt(k)); - } - dout.writeObject(new DERSet(attribute)); - dout.close(); - } - catch (IOException ioe){} - sigAttr = bOut.toByteArray(); - - for (int k = 0; k < sseq.size(); ++k) { - ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k); - if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) { - ASN1Set set = (ASN1Set)seq2.getObjectAt(1); - digestAttr = ((DEROctetString)set.getObjectAt(0)).getOctets(); - break; - } - } - if (digestAttr == null) - throw new SecurityException("Authenticated attribute is missing the digest."); - ++next; - } - digestEncryptionAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId(); - digest = ((DEROctetString)signerInfo.getObjectAt(next)).getOctets(); - if (RSAdata != null || digestAttr != null) { - if (provider == null || provider.startsWith("SunPKCS11")) - messageDigest = MessageDigest.getInstance(getHashAlgorithm()); - else - messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider); - } - if (provider == null) - sig = Signature.getInstance(getDigestAlgorithm()); - else - sig = Signature.getInstance(getDigestAlgorithm(), provider); - sig.initVerify(signCert.getPublicKey()); - } - - /** - * Generates a signature. - * @param privKey the private key - * @param certChain the certificate chain - * @param crlList the certificate revocation list - * @param hashAlgorithm the hash algorithm - * @param provider the provider or null for the default provider - * @param hasRSAdata true if the sub-filter is adbe.pkcs7.sha1 - * @throws SecurityException on error - * @throws InvalidKeyException on error - * @throws NoSuchProviderException on error - * @throws NoSuchAlgorithmException on error - */ - public PdfPKCS7(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, - String hashAlgorithm, String provider, boolean hasRSAdata) - throws SecurityException, InvalidKeyException, NoSuchProviderException, - NoSuchAlgorithmException - { - this.privKey = privKey; - - if (hashAlgorithm.equals("MD5")) { - digestAlgorithm = ID_MD5; - } - else if (hashAlgorithm.equals("MD2")) { - digestAlgorithm = ID_MD2; - } - else if (hashAlgorithm.equals("SHA")) { - digestAlgorithm = ID_SHA1; - } - else if (hashAlgorithm.equals("SHA1")) { - digestAlgorithm = ID_SHA1; - } - else { - throw new NoSuchAlgorithmException("Unknown Hash Algorithm "+hashAlgorithm); - } - - version = signerversion = 1; - certs = new ArrayList(); - crls = new ArrayList(); - digestalgos = new HashSet(); - digestalgos.add(digestAlgorithm); - - // - // Copy in the certificates and crls used to sign the private key. - // - signCert = (X509Certificate)certChain[0]; - for (int i = 0;i < certChain.length;i++) { - certs.add(certChain[i]); - } - - if (crlList != null) { - for (int i = 0;i < crlList.length;i++) { - crls.add(crlList[i]); - } - } - - if (privKey != null) { - // - // Now we have private key, find out what the digestEncryptionAlgorithm is. - // - digestEncryptionAlgorithm = privKey.getAlgorithm(); - if (digestEncryptionAlgorithm.equals("RSA")) { - digestEncryptionAlgorithm = ID_RSA; - } - else if (digestEncryptionAlgorithm.equals("DSA")) { - digestEncryptionAlgorithm = ID_DSA; - } - else { - throw new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm); - } - } - if (hasRSAdata) { - RSAdata = new byte[0]; - if (provider == null || provider.startsWith("SunPKCS11")) - messageDigest = MessageDigest.getInstance(getHashAlgorithm()); - else - messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider); - } - - if (privKey != null) { - if (provider == null) - sig = Signature.getInstance(getDigestAlgorithm()); - else - sig = Signature.getInstance(getDigestAlgorithm(), provider); - - sig.initSign(privKey); - } - } - - /** - * Update the digest with the specified bytes. This method is used both for signing and verifying - * @param buf the data buffer - * @param off the offset in the data buffer - * @param len the data length - * @throws SignatureException on error - */ - public void update(byte[] buf, int off, int len) throws SignatureException { - if (RSAdata != null || digestAttr != null) - messageDigest.update(buf, off, len); - else - sig.update(buf, off, len); - } - - /** - * Verify the digest. - * @throws SignatureException on error - * @return true if the signature checks out, false otherwise - */ - public boolean verify() throws SignatureException { - if (verified) - return verifyResult; - if (sigAttr != null) { - sig.update(sigAttr); - if (RSAdata != null) { - byte msd[] = messageDigest.digest(); - messageDigest.update(msd); - } - verifyResult = (Arrays.equals(messageDigest.digest(), digestAttr) && sig.verify(digest)); - } - else { - if (RSAdata != null) - sig.update(messageDigest.digest()); - verifyResult = sig.verify(digest); - } - verified = true; - return verifyResult; - } - - /** - * Get the X.509 certificates associated with this PKCS#7 object - * @return the X.509 certificates associated with this PKCS#7 object - */ - public Certificate[] getCertificates() { - return (X509Certificate[])certs.toArray(new X509Certificate[0]); - } - - /** - * Get the X.509 certificate revocation lists associated with this PKCS#7 object - * @return the X.509 certificate revocation lists associated with this PKCS#7 object - */ - public Collection getCRLs() { - return crls; - } - - /** - * Get the X.509 certificate actually used to sign the digest. - * @return the X.509 certificate actually used to sign the digest - */ - public X509Certificate getSigningCertificate() { - return signCert; - } - - /** - * Get the version of the PKCS#7 object. Always 1 - * @return the version of the PKCS#7 object. Always 1 - */ - public int getVersion() { - return version; - } - - /** - * Get the version of the PKCS#7 "SignerInfo" object. Always 1 - * @return the version of the PKCS#7 "SignerInfo" object. Always 1 - */ - public int getSigningInfoVersion() { - return signerversion; - } - - /** - * Get the algorithm used to calculate the message digest - * @return the algorithm used to calculate the message digest - */ - public String getDigestAlgorithm() { - String dea = digestEncryptionAlgorithm; - - if (digestEncryptionAlgorithm.equals(ID_RSA)) { - dea = "RSA"; - } - else if (digestEncryptionAlgorithm.equals(ID_DSA)) { - dea = "DSA"; - } - - return getHashAlgorithm() + "with" + dea; - } - - /** - * Returns the algorithm. - * @return the digest algorithm - */ - public String getHashAlgorithm() { - String da = digestAlgorithm; - - if (digestAlgorithm.equals(ID_MD5) || digestAlgorithm.equals(ID_MD5RSA)) { - da = "MD5"; - } - else if (digestAlgorithm.equals(ID_MD2) || digestAlgorithm.equals(ID_MD2RSA)) { - da = "MD2"; - } - else if (digestAlgorithm.equals(ID_SHA1) || digestAlgorithm.equals(ID_SHA1RSA)) { - da = "SHA1"; - } - return da; - } - - /** - * Loads the default root certificates at <java.home>/lib/security/cacerts - * with the default provider. - * @return a KeyStore - */ - public static KeyStore loadCacertsKeyStore() { - return loadCacertsKeyStore(null); - } - - /** - * Loads the default root certificates at <java.home>/lib/security/cacerts. - * @param provider the provider or null for the default provider - * @return a KeyStore - */ - public static KeyStore loadCacertsKeyStore(String provider) { - File file = new File(System.getProperty("java.home"), "lib"); - file = new File(file, "security"); - file = new File(file, "cacerts"); - FileInputStream fin = null; - try { - fin = new FileInputStream(file); - KeyStore k; - if (provider == null) - k = KeyStore.getInstance("JKS"); - else - k = KeyStore.getInstance("JKS", provider); - k.load(fin, null); - return k; - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - finally { - try{fin.close();}catch(Exception ex){} - } - } - - /** - * Verifies a single certificate. - * @param cert the certificate to verify - * @param crls the certificate revocation list or null - * @param calendar the date or null for the current date - * @return a String with the error description or null - * if no error - */ - public static String verifyCertificate(X509Certificate cert, Collection crls, Calendar calendar) { - if (calendar == null) - calendar = new GregorianCalendar(); - if (cert.hasUnsupportedCriticalExtension()) - return "Has unsupported critical extension"; - try { - cert.checkValidity(calendar.getTime()); - } - catch (Exception e) { - return e.getMessage(); - } - if (crls != null) { - for (Iterator it = crls.iterator(); it.hasNext();) { - if (((CRL)it.next()).isRevoked(cert)) - return "Certificate revoked"; - } - } - return null; - } - - /** - * Verifies a certificate chain against a KeyStore. - * @param certs the certificate chain - * @param keystore the KeyStore - * @param crls the certificate revocation list or null - * @param calendar the date or null for the current date - * @return null if the certificate chain could be validade or a - * Object[]{cert,error} where cert is the - * failed certificate and error is the error message - */ - public static Object[] verifyCertificates(Certificate certs[], KeyStore keystore, Collection crls, Calendar calendar) { - if (calendar == null) - calendar = new GregorianCalendar(); - for (int k = 0; k < certs.length; ++k) { - X509Certificate cert = (X509Certificate)certs[k]; - String err = verifyCertificate(cert, crls, calendar); - if (err != null) - return new Object[]{cert, err}; - try { - for (Enumeration aliases = keystore.aliases(); aliases.hasMoreElements();) { - try { - String alias = (String)aliases.nextElement(); - if (!keystore.isCertificateEntry(alias)) - continue; - X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias); - if (verifyCertificate(certStoreX509, crls, calendar) != null) - continue; - try { - cert.verify(certStoreX509.getPublicKey()); - return null; - } - catch (Exception e) { - continue; - } - } - catch (Exception ex) { - } - } - } - catch (Exception e) { - } - int j; - for (j = 0; j < certs.length; ++j) { - if (j == k) - continue; - X509Certificate certNext = (X509Certificate)certs[j]; - try { - cert.verify(certNext.getPublicKey()); - break; - } - catch (Exception e) { - } - } - if (j == certs.length) - return new Object[]{cert, "Cannot be verified against the KeyStore or the certificate chain"}; - } - return new Object[]{null, "Invalid state. Possible circular certificate chain"}; - } - - /** - * Get the "issuer" from the TBSCertificate bytes that are passed in - * @param enc a TBSCertificate in a byte array - * @return a DERObject - */ - private static DERObject getIssuer(byte[] enc) { - try { - ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc)); - ASN1Sequence seq = (ASN1Sequence)in.readObject(); - return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2); - } - catch (IOException e) { - throw new ExceptionConverter(e); - } - } - - /** - * Get the "subject" from the TBSCertificate bytes that are passed in - * @param enc A TBSCertificate in a byte array - * @return a DERObject - */ - private static DERObject getSubject(byte[] enc) { - try { - ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc)); - ASN1Sequence seq = (ASN1Sequence)in.readObject(); - return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4); - } - catch (IOException e) { - throw new ExceptionConverter(e); - } - } - - /** - * Get the issuer fields from an X509 Certificate - * @param cert an X509Certificate - * @return an X509Name - */ - public static X509Name getIssuerFields(X509Certificate cert) { - try { - return new X509Name((ASN1Sequence)getIssuer(cert.getTBSCertificate())); - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - } - - /** - * Get the subject fields from an X509 Certificate - * @param cert an X509Certificate - * @return an X509Name - */ - public static X509Name getSubjectFields(X509Certificate cert) { - try { - return new X509Name((ASN1Sequence)getSubject(cert.getTBSCertificate())); - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - } - - /** - * Gets the bytes for the PKCS#1 object. - * @return a byte array - */ - public byte[] getEncodedPKCS1() { - try { - if (externalDigest != null) - digest = externalDigest; - else - digest = sig.sign(); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - ASN1OutputStream dout = new ASN1OutputStream(bOut); - dout.writeObject(new DEROctetString(digest)); - dout.close(); - - return bOut.toByteArray(); - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - } - - /** - * Sets the digest/signature to an external calculated value. - * @param digest the digest. This is the actual signature - * @param RSAdata the extra data that goes into the data tag in PKCS#7 - * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null if the digest - * is also null. If the digest is not null - * then it may be "RSA" or "DSA" - */ - public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) { - externalDigest = digest; - externalRSAdata = RSAdata; - if (digestEncryptionAlgorithm != null) { - if (digestEncryptionAlgorithm.equals("RSA")) { - this.digestEncryptionAlgorithm = ID_RSA; - } - else if (digestEncryptionAlgorithm.equals("DSA")) { - this.digestEncryptionAlgorithm = ID_DSA; - } - else - throw new ExceptionConverter(new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm)); - } - } - - /** - * Gets the bytes for the PKCS7SignedData object. - * @return the bytes for the PKCS7SignedData object - */ - public byte[] getEncodedPKCS7() { - return getEncodedPKCS7(null, null); - } - - /** - * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes - * in the signerInfo can also be set. If either of the parameters is null, none will be used. - * @param secondDigest the digest in the authenticatedAttributes - * @param signingTime the signing time in the authenticatedAttributes - * @return the bytes for the PKCS7SignedData object - */ - public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime) { - try { - if (externalDigest != null) { - digest = externalDigest; - if (RSAdata != null) - RSAdata = externalRSAdata; - } - else if (externalRSAdata != null && RSAdata != null) { - RSAdata = externalRSAdata; - sig.update(RSAdata); - digest = sig.sign(); - } - else { - if (RSAdata != null) { - RSAdata = messageDigest.digest(); - sig.update(RSAdata); - } - digest = sig.sign(); - } - - // Create the set of Hash algorithms - DERConstructedSet digestAlgorithms = new DERConstructedSet(); - for(Iterator it = digestalgos.iterator(); it.hasNext();) { - ASN1EncodableVector algos = new ASN1EncodableVector(); - algos.add(new DERObjectIdentifier((String)it.next())); - algos.add(new DERNull()); - digestAlgorithms.addObject(new DERSequence(algos)); - } - - // Create the contentInfo. - ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_PKCS7_DATA)); - if (RSAdata != null) - v.add(new DERTaggedObject(0, new DEROctetString(RSAdata))); - DERSequence contentinfo = new DERSequence(v); - - // Get all the certificates - // - v = new ASN1EncodableVector(); - for (Iterator i = certs.iterator(); i.hasNext();) { - ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded())); - v.add(tempstream.readObject()); - } - - DERSet dercertificates = new DERSet(v); - - // Create signerinfo structure. - // - ASN1EncodableVector signerinfo = new ASN1EncodableVector(); - - // Add the signerInfo version - // - signerinfo.add(new DERInteger(signerversion)); - - v = new ASN1EncodableVector(); - v.add(getIssuer(signCert.getTBSCertificate())); - v.add(new DERInteger(signCert.getSerialNumber())); - signerinfo.add(new DERSequence(v)); - - // Add the digestAlgorithm - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(digestAlgorithm)); - v.add(new DERNull()); - signerinfo.add(new DERSequence(v)); - - // add the authenticated attribute if present - if (secondDigest != null && signingTime != null) { - ASN1EncodableVector attribute = new ASN1EncodableVector(); - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_CONTENT_TYPE)); - v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA))); - attribute.add(new DERSequence(v)); - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_SIGNING_TIME)); - v.add(new DERSet(new DERUTCTime(signingTime.getTime()))); - attribute.add(new DERSequence(v)); - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST)); - v.add(new DERSet(new DEROctetString(secondDigest))); - attribute.add(new DERSequence(v)); - signerinfo.add(new DERTaggedObject(false, 0, new DERSet(attribute))); - } - // Add the digestEncryptionAlgorithm - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(digestEncryptionAlgorithm)); - v.add(new DERNull()); - signerinfo.add(new DERSequence(v)); - - // Add the digest - signerinfo.add(new DEROctetString(digest)); - - - // Finally build the body out of all the components above - ASN1EncodableVector body = new ASN1EncodableVector(); - body.add(new DERInteger(version)); - body.add(digestAlgorithms); - body.add(contentinfo); - body.add(new DERTaggedObject(false, 0, dercertificates)); - - if (crls.size() > 0) { - v = new ASN1EncodableVector(); - for (Iterator i = crls.iterator();i.hasNext();) { - ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded()))); - v.add(t.readObject()); - } - DERSet dercrls = new DERSet(v); - body.add(new DERTaggedObject(false, 1, dercrls)); - } - - // Only allow one signerInfo - body.add(new DERSet(new DERSequence(signerinfo))); - - // Now we have the body, wrap it in it's PKCS7Signed shell - // and return it - // - ASN1EncodableVector whole = new ASN1EncodableVector(); - whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA)); - whole.add(new DERTaggedObject(0, new DERSequence(body))); - - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - ASN1OutputStream dout = new ASN1OutputStream(bOut); - dout.writeObject(new DERSequence(whole)); - dout.close(); - - return bOut.toByteArray(); - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - } - - - /** - * When using authenticatedAttributes the authentication process is different. - * The document digest is generated and put inside the attribute. The signing is done over the DER encoded - * authenticatedAttributes. This method provides that encoding and the parameters must be - * exactly the same as in {@link #getEncodedPKCS7(byte[],Calendar)}. - *

- * A simple example: - *

- *

-     * Calendar cal = Calendar.getInstance();
-     * PdfPKCS7 pk7 = new PdfPKCS7(key, chain, null, "SHA1", null, false);
-     * MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
-     * byte buf[] = new byte[8192];
-     * int n;
-     * InputStream inp = sap.getRangeStream();
-     * while ((n = inp.read(buf)) > 0) {
-     *    messageDigest.update(buf, 0, n);
-     * }
-     * byte hash[] = messageDigest.digest();
-     * byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal);
-     * pk7.update(sh, 0, sh.length);
-     * byte sg[] = pk7.getEncodedPKCS7(hash, cal);
-     * 
- * @param secondDigest the content digest - * @param signingTime the signing time - * @return the byte array representation of the authenticatedAttributes ready to be signed - */ - public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime) { - try { - ASN1EncodableVector attribute = new ASN1EncodableVector(); - ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_CONTENT_TYPE)); - v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA))); - attribute.add(new DERSequence(v)); - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_SIGNING_TIME)); - v.add(new DERSet(new DERUTCTime(signingTime.getTime()))); - attribute.add(new DERSequence(v)); - v = new ASN1EncodableVector(); - v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST)); - v.add(new DERSet(new DEROctetString(secondDigest))); - attribute.add(new DERSequence(v)); - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - - ASN1OutputStream dout = new ASN1OutputStream(bOut); - dout.writeObject(new DERSet(attribute)); - dout.close(); - - return bOut.toByteArray(); - } - catch (Exception e) { - throw new ExceptionConverter(e); - } - } - /** - * Getter for property reason. - * @return Value of property reason. - */ - public String getReason() { - return this.reason; - } - - /** - * Setter for property reason. - * @param reason New value of property reason. - */ - public void setReason(String reason) { - this.reason = reason; - } - - /** - * Getter for property location. - * @return Value of property location. - */ - public String getLocation() { - return this.location; - } - - /** - * Setter for property location. - * @param location New value of property location. - */ - public void setLocation(String location) { - this.location = location; - } - - /** - * Getter for property signDate. - * @return Value of property signDate. - */ - public Calendar getSignDate() { - return this.signDate; - } - - /** - * Setter for property signDate. - * @param signDate New value of property signDate. - */ - public void setSignDate(Calendar signDate) { - this.signDate = signDate; - } - - /** - * Getter for property sigName. - * @return Value of property sigName. - */ - public String getSignName() { - return this.signName; - } - - /** - * Setter for property sigName. - * @param signName New value of property sigName. - */ - public void setSignName(String signName) { - this.signName = signName; - } - - /** - * a class that holds an X509 name - */ - public static class X509Name { - /** - * country code - StringType(SIZE(2)) - */ - public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6"); - - /** - * organization - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10"); - - /** - * organizational unit name - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11"); - - /** - * Title - */ - public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12"); - - /** - * common name - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3"); - - /** - * device serial number name - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5"); - - /** - * locality name - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7"); - - /** - * state, or province name - StringType(SIZE(1..64)) - */ - public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8"); - - /** Naming attribute of type X520name */ - public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4"); - /** Naming attribute of type X520name */ - public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42"); - /** Naming attribute of type X520name */ - public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43"); - /** Naming attribute of type X520name */ - public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44"); - /** Naming attribute of type X520name */ - public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45"); - - /** - * Email address (RSA PKCS#9 extension) - IA5String. - *

Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here. - */ - public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1"); - - /** - * email address in Verisign certificates - */ - public static final DERObjectIdentifier E = EmailAddress; - - /** object identifier */ - public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25"); - - /** LDAP User id. */ - public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1"); - - /** A HashMap with default symbols */ - public static HashMap DefaultSymbols = new HashMap(); - - static { - DefaultSymbols.put(C, "C"); - DefaultSymbols.put(O, "O"); - DefaultSymbols.put(T, "T"); - DefaultSymbols.put(OU, "OU"); - DefaultSymbols.put(CN, "CN"); - DefaultSymbols.put(L, "L"); - DefaultSymbols.put(ST, "ST"); - DefaultSymbols.put(SN, "SN"); - DefaultSymbols.put(EmailAddress, "E"); - DefaultSymbols.put(DC, "DC"); - DefaultSymbols.put(UID, "UID"); - DefaultSymbols.put(SURNAME, "SURNAME"); - DefaultSymbols.put(GIVENNAME, "GIVENNAME"); - DefaultSymbols.put(INITIALS, "INITIALS"); - DefaultSymbols.put(GENERATION, "GENERATION"); - } - /** A HashMap with values */ - public HashMap values = new HashMap(); - - /** - * Constructs an X509 name - * @param seq an ASN1 Sequence - */ - public X509Name(ASN1Sequence seq) { - Enumeration e = seq.getObjects(); - - while (e.hasMoreElements()) { - ASN1Set set = (ASN1Set)e.nextElement(); - - for (int i = 0; i < set.size(); i++) { - ASN1Sequence s = (ASN1Sequence)set.getObjectAt(i); - String id = (String)DefaultSymbols.get(s.getObjectAt(0)); - if (id == null) - continue; - ArrayList vs = (ArrayList)values.get(id); - if (vs == null) { - vs = new ArrayList(); - values.put(id, vs); - } - vs.add(((DERString)s.getObjectAt(1)).getString()); - } - } - } - /** - * Constructs an X509 name - * @param dirName a directory name - */ - public X509Name(String dirName) { - X509NameTokenizer nTok = new X509NameTokenizer(dirName); - - while (nTok.hasMoreTokens()) { - String token = nTok.nextToken(); - int index = token.indexOf('='); - - if (index == -1) { - throw new IllegalArgumentException("badly formated directory string"); - } - - String id = token.substring(0, index).toUpperCase(); - String value = token.substring(index + 1); - ArrayList vs = (ArrayList)values.get(id); - if (vs == null) { - vs = new ArrayList(); - values.put(id, vs); - } - vs.add(value); - } - - } - - public String getField(String name) { - ArrayList vs = (ArrayList)values.get(name); - return vs == null ? null : (String)vs.get(0); - } - - /** - * gets a field array from the values Hashmap - * @param name - * @return an ArrayList - */ - public ArrayList getFieldArray(String name) { - ArrayList vs = (ArrayList)values.get(name); - return vs == null ? null : vs; - } - - /** - * getter for values - * @return a HashMap with the fields of the X509 name - */ - public HashMap getFields() { - return values; - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - return values.toString(); - } - } - - /** - * class for breaking up an X500 Name into it's component tokens, ala - * java.util.StringTokenizer. We need this class as some of the - * lightweight Java environment don't support classes like - * StringTokenizer. - */ - public static class X509NameTokenizer { - private String oid; - private int index; - private StringBuffer buf = new StringBuffer(); - - public X509NameTokenizer( - String oid) { - this.oid = oid; - this.index = -1; - } - - public boolean hasMoreTokens() { - return (index != oid.length()); - } - - public String nextToken() { - if (index == oid.length()) { - return null; - } - - int end = index + 1; - boolean quoted = false; - boolean escaped = false; - - buf.setLength(0); - - while (end != oid.length()) { - char c = oid.charAt(end); - - if (c == '"') { - if (!escaped) { - quoted = !quoted; - } - else { - buf.append(c); - } - escaped = false; - } - else { - if (escaped || quoted) { - buf.append(c); - escaped = false; - } - else if (c == '\\') { - escaped = true; - } - else if (c == ',') { - break; - } - else { - buf.append(c); - } - } - end++; - } - - index = end; - return buf.toString().trim(); - } - } -} \ No newline at end of file -- cgit v1.2.3