Search in sources :

Example 1 with SignatureIntegrityException

use of org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException in project mucommander by mucommander.

the class SignaturesPanel method updateSignature.

/**
 * Updates the data fields on a signature tree node after verification has taken place.  It is assumed
 * this method is always called from the AWT thread.
 *
 * @param signatureWidgetAnnotation annotation to update
 * @param signatureTreeNode         node that will be updated.
 */
public void updateSignature(SignatureWidgetAnnotation signatureWidgetAnnotation, SignatureTreeNode signatureTreeNode) {
    if (signatureWidgetAnnotation != null) {
        try {
            TreePath treePath = new TreePath(signatureTreeNode.getPath());
            boolean isExpanded = signatureTree.isExpanded(treePath);
            signatureTreeNode.validateSignatureNode();
            signatureTreeNode.refreshSignerNode();
            treeModel.reload();
            if (isExpanded) {
                signatureTree.expandPath(new TreePath(signatureTreeNode.getPath()));
            }
        } catch (SignatureIntegrityException e) {
            logger.log(Level.WARNING, "Could not build signature node.", e);
        }
    }
}
Also used : TreePath(javax.swing.tree.TreePath) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException)

Example 2 with SignatureIntegrityException

use of org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException in project mucommander by mucommander.

the class AbstractPkcsValidator method validateDocument.

/**
 * Validates the document against the data in the signatureDictionary.
 *
 * @throws SignatureIntegrityException
 */
protected void validateDocument() throws SignatureIntegrityException {
    SignatureDictionary signatureDictionary = signatureFieldDictionary.getSignatureDictionary();
    Signature signature;
    MessageDigest messageDigestAlgorithm;
    MessageDigest eConMessageDigestAlgorithm;
    try {
        String provider = signatureDictionary.getFilter().getName();
        messageDigestAlgorithm = AlgorithmIdentifier.getDigestInstance(digestAlgorithmIdentifier, provider);
        eConMessageDigestAlgorithm = AlgorithmIdentifier.getDigestInstance(digestAlgorithmIdentifier, provider);
        signature = createSignature(signerCertificate.getPublicKey(), provider, signatureAlgorithmIdentifier, digestAlgorithmIdentifier);
        PublicKey publicKey = signerCertificate.getPublicKey();
        if (logger.isLoggable(Level.FINER)) {
            logger.finest("Certificate: \n" + signerCertificate.toString());
            logger.finest("Public Key:  \n" + publicKey);
        }
    } catch (NoSuchProviderException e1) {
        logger.log(Level.WARNING, "No such provider found ", e1);
        return;
    } catch (NoSuchAlgorithmException e1) {
        logger.log(Level.WARNING, "No such algorithm found ", e1);
        return;
    } catch (InvalidKeyException e1) {
        logger.log(Level.WARNING, "Invalid key ", e1);
        return;
    }
    // let digest the data.
    ArrayList<Integer> byteRange = signatureFieldDictionary.getSignatureDictionary().getByteRange();
    SeekableInput documentInput = signatureFieldDictionary.getLibrary().getDocumentInput();
    documentInput.beginThreadAccess();
    try {
        long totalLength = documentInput.getLength();
        long digestedLength = byteRange.get(2) + byteRange.get(3);
        // or signatures added after this signature.
        if (digestedLength < totalLength) {
            isDocumentDataModified = true;
        }
        documentInput.seekAbsolute(byteRange.get(0));
        byte[] firstSection = new byte[byteRange.get(1)];
        documentInput.read(firstSection);
        messageDigestAlgorithm.update(firstSection);
        documentInput.seekAbsolute(byteRange.get(2));
        byte[] secondSection = new byte[byteRange.get(3)];
        documentInput.read(secondSection);
        messageDigestAlgorithm.update(secondSection);
    } catch (IOException e) {
        throw new SignatureIntegrityException(e);
    } finally {
        documentInput.endThreadAccess();
    }
    // setup the compare
    try {
        // RFC3852 - The result of the message digest calculation process depends on whether the signedAttrs field
        // is present. When the field is absent, the result is just the message digest of the content as described
        // above. When the field is present, however, the result is the message digest of the complete DER encoding
        // of the SignedAttrs value contained in the signedAttrs field.
        byte[] documentDigestBytes = messageDigestAlgorithm.digest();
        if (signedAttributesSequence != null) {
            boolean encapsulatedDigestCheck = true;
            boolean verifyEncContentInfoData = true;
            if (encapsulatedContentInfoData != null) {
                verifyEncContentInfoData = Arrays.equals(documentDigestBytes, encapsulatedContentInfoData);
                eConMessageDigestAlgorithm.update(encapsulatedContentInfoData);
                encapsulatedDigestCheck = Arrays.equals(eConMessageDigestAlgorithm.digest(), messageDigest);
            }
            boolean nonEncapsulatedDigestCheck = Arrays.equals(documentDigestBytes, messageDigest);
            // When the field is present, however, the result is the message digest of the complete DER encoding of
            // the SignedAttrs value contained in the signedAttrs field
            boolean isSignatureValid = verifySignedAttributes(signatureDictionary.getFilter().getName(), signerCertificate, signatureValue, signatureAlgorithmIdentifier, digestAlgorithmIdentifier, signedAttributesSequence.getEncoded(ASN1Encoding.DER));
            if (logger.isLoggable(Level.FINEST)) {
                logger.finest("Encapsulated Digest verified: " + encapsulatedDigestCheck);
                logger.finest("Non-encapsulated Digest verified: " + nonEncapsulatedDigestCheck);
                logger.finest("Signature verified: " + isSignatureValid);
                logger.finest("Encapsulated data verified: " + verifyEncContentInfoData);
            }
            // verify the attributes.
            if ((encapsulatedDigestCheck || nonEncapsulatedDigestCheck) && verifyEncContentInfoData) {
                isSignedDataModified = false;
            }
        } else {
            if (encapsulatedContentInfoData != null) {
                signature.update(messageDigestAlgorithm.digest());
            }
            boolean nonEncapsulatedDigestCheck = Arrays.equals(documentDigestBytes, messageDigest);
            if (nonEncapsulatedDigestCheck) {
                isSignedDataModified = false;
            }
        }
        lastVerified = new Date();
    } catch (SignatureException e) {
        throw new SignatureIntegrityException(e);
    } catch (IOException e) {
        throw new SignatureIntegrityException(e);
    }
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        java.io.FileInputStream fis = null;
        try {
            fis = new java.io.FileInputStream(caCertLocation);
            trustStore.load(fis, null);
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
        // cert validation
        X509Certificate[] cers = certificateChain.toArray(new X509Certificate[0]);
        ArrayList<X509Certificate> trusted = new ArrayList<X509Certificate>(trustStore.size());
        Enumeration<String> aliases = trustStore.aliases();
        while (aliases.hasMoreElements()) {
            trusted.add((X509Certificate) trustStore.getCertificate(aliases.nextElement()));
        }
        CertificateVerifier.verifyCertificate(cers[0], trusted);
        isCertificateChainTrusted = true;
        isCertificateDateValid = true;
        lastVerified = new Date();
    } catch (CertificateExpiredException e) {
        logger.log(Level.FINEST, "Certificate chain could not be validated, certificate is expired", e);
        isCertificateDateValid = false;
    } catch (SelfSignedVerificationException e) {
        logger.log(Level.FINEST, "Certificate chain could not be validated, signature is self singed.", e);
        isSelfSigned = true;
    } catch (CertificateVerificationException e) {
        logger.log(Level.FINEST, "Certificate chain could not be validated. ", e);
        isCertificateChainTrusted = false;
    } catch (RevocationVerificationException e) {
        logger.log(Level.FINEST, "Certificate chain could not be validated, certificate has been revoked.", e);
        isRevocation = true;
    } catch (IOException e) {
        logger.log(Level.FINEST, "Error locating trusted keystore .", e);
        isCertificateChainTrusted = false;
    } catch (CertificateException e) {
        logger.log(Level.FINEST, "Certificate exception.", e);
        isCertificateChainTrusted = false;
    } catch (Throwable e) {
        logger.log(Level.FINEST, "Error validation certificate chain.", e);
        isCertificateChainTrusted = false;
    }
}
Also used : CertificateExpiredException(java.security.cert.CertificateExpiredException) CertificateException(java.security.cert.CertificateException) SelfSignedVerificationException(org.icepdf.core.pobjects.acroform.signature.exceptions.SelfSignedVerificationException) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException) SignatureDictionary(org.icepdf.core.pobjects.acroform.SignatureDictionary) SeekableInput(org.icepdf.core.io.SeekableInput) IOException(java.io.IOException) X509Certificate(java.security.cert.X509Certificate) BigInteger(java.math.BigInteger) CertificateVerificationException(org.icepdf.core.pobjects.acroform.signature.exceptions.CertificateVerificationException) RevocationVerificationException(org.icepdf.core.pobjects.acroform.signature.exceptions.RevocationVerificationException)

Example 3 with SignatureIntegrityException

use of org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException in project mucommander by mucommander.

the class AbstractPkcsValidator method parseSignerData.

/**
 * SignedData ::= SEQUENCE {
 * 0, version CMSVersion,
 * 1, digestAlgorithms DigestAlgorithmIdentifiers,
 * 2, encapContentInfo EncapsulatedContentInfo,
 * 3, certificateChain [0] IMPLICIT CertificateSet OPTIONAL,
 * 4, crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
 * 5, signerInfos SignerInfos }
 * <p/>
 * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
 * SignerInfos ::= SET OF SignerInfo
 */
protected void parseSignerData(ASN1Sequence signedData, byte[] cmsData) throws SignatureIntegrityException {
    // digest algorithms ID, not currently using them but useful for debug.
    if (logger.isLoggable(Level.FINER)) {
        // should always be 1.
        int cmsVersion = ((ASN1Integer) signedData.getObjectAt(0)).getValue().intValue();
        logger.finest("CMS version: " + cmsVersion);
        Enumeration<ASN1Sequence> enumeration = ((ASN1Set) signedData.getObjectAt(1)).getObjects();
        while (enumeration.hasMoreElements()) {
            String objectId = ((ASN1ObjectIdentifier) enumeration.nextElement().getObjectAt(0)).getId();
            try {
                String digestAlgorithmName = AlgorithmIdentifier.getDigestAlgorithmName(objectId);
                MessageDigest tmp = AlgorithmIdentifier.getDigestInstance(objectId, null);
                logger.finest("DigestAlgorithmIdentifiers: " + digestAlgorithmName + " " + objectId);
                logger.finest(tmp.toString());
            } catch (Throwable ex) {
                logger.log(Level.WARNING, "Error finding iod: " + objectId, ex);
            }
        }
    }
    /**
     * EncapsulatedContentInfo ::= SEQUENCE {
     *    eContentType ContentType,
     *    eContent [0] EXPLICIT OCTET STRING OPTIONAL }
     *
     * ContentType ::= OBJECT IDENTIFIER
     */
    encapsulatedContentInfoData = null;
    ASN1Sequence encapsulatedContentInfo = (ASN1Sequence) signedData.getObjectAt(2);
    // grab just the first definitions, as we are looking for encapuslated data for PKCS7.sha1.
    if (encapsulatedContentInfo.size() >= 2) {
        // should still be iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 ...
        ASN1ObjectIdentifier eObjectIdentifier = (ASN1ObjectIdentifier) encapsulatedContentInfo.getObjectAt(0);
        String eObjectIdentifierId = eObjectIdentifier.getId();
        if (logger.isLoggable(Level.FINER)) {
            logger.finest("EncapsulatedContentInfo: " + eObjectIdentifierId + " " + Pkcs7Validator.getObjectIdName(eObjectIdentifierId));
        }
        // should be octets encode as pkcs#7
        ASN1OctetString eContent = (ASN1OctetString) ((ASN1TaggedObject) encapsulatedContentInfo.getObjectAt(1)).getObject();
        // shows up in pkcs7.sha1 only
        encapsulatedContentInfoData = eContent.getOctets();
        if (logger.isLoggable(Level.FINER)) {
            logger.finest("EncapsulatedContentInfo Data " + eContent.toString());
        }
    } else if (encapsulatedContentInfo.size() == 1) {
        if (logger.isLoggable(Level.FINER)) {
            ASN1ObjectIdentifier eObjectIdentifier = (ASN1ObjectIdentifier) encapsulatedContentInfo.getObjectAt(0);
            String eObjectIdentifierId = eObjectIdentifier.getId();
            logger.finest("EncapsulatedContentInfo size is 1: " + eObjectIdentifierId + " " + Pkcs7Validator.getObjectIdName(eObjectIdentifierId));
        }
    }
    // grab the signer info.
    ASN1Sequence signerInfo = parseCertificateData(cmsData, signedData);
    // DigestAlgorithmIdentifier ::= AlgorithmIdentifier
    digestAlgorithmIdentifier = ((ASN1ObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(2)).getObjectAt(0)).getId();
    // signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
    // signedAttrs is optional so we look for the occurrence
    // 
    // SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
    // 
    // Attribute ::= SEQUENCE {
    // attrType OBJECT IDENTIFIER,
    // attrValues SET OF AttributeValue }
    // 
    // AttributeValue ::= ANY
    // SignatureValue ::= OCTET STRING
    int nextEntry = 3;
    messageDigest = null;
    ASN1TaggedObject signedAttributes;
    signedAttributesSequence = null;
    if (signerInfo.getObjectAt(nextEntry) instanceof ASN1TaggedObject) {
        signedAttributes = (ASN1TaggedObject) signerInfo.getObjectAt(nextEntry);
        signedAttributesSequence = ASN1Set.getInstance(signedAttributes, false);
        for (int i = 0, max = signedAttributesSequence.size(); i < max; ++i) {
            // attribute type/value pair.
            ASN1Sequence attributePair = (ASN1Sequence) signedAttributesSequence.getObjectAt(i);
            // mainly just looking for the message digest.
            if (((ASN1ObjectIdentifier) attributePair.getObjectAt(0)).getId().equals(PKCSObjectIdentifiers.pkcs_9_at_messageDigest.getId())) {
                ASN1Set set = (ASN1Set) attributePair.getObjectAt(1);
                messageDigest = ((ASN1OctetString) set.getObjectAt(0)).getOctets();
            }
        // try and pull out the signing time.
        // currently not using this time.
        // if (((ASN1ObjectIdentifier) attributePair.getObjectAt(0)).getId().equals(
        // PKCSObjectIdentifiers.pkcs_9_at_signingTime.getId())) {
        // ASN1Set set = (ASN1Set) attributePair.getObjectAt(1);
        // ASN1UTCTime signerTime = ((ASN1UTCTime) set.getObjectAt(0));
        // try {
        // // see if the signer time matches the certificate validity times.
        // System.out.println(" SignatureSigner Time " + signerTime.getDate());
        // } catch (ParseException e) {
        // e.printStackTrace();
        // }
        // }
        // more attributes to come.
        }
        if (messageDigest == null) {
            throw new SignatureIntegrityException("Message Digest can nut be null");
        }
        ++nextEntry;
    }
    // signatureAlgorithm SignatureAlgorithmIdentifier,
    signatureAlgorithmIdentifier = ((ASN1ObjectIdentifier) ((ASN1Sequence) signerInfo.getObjectAt(nextEntry)).getObjectAt(0)).getId();
    nextEntry++;
    // signature SignatureValue
    signatureValue = ((ASN1OctetString) signerInfo.getObjectAt(nextEntry)).getOctets();
    nextEntry++;
    // once again optional so we check to see if the entry is available.
    if (nextEntry < signerInfo.size() && signerInfo.getObjectAt(nextEntry) instanceof ASN1TaggedObject) {
        ASN1TaggedObject unsignedAttributes = (ASN1TaggedObject) signerInfo.getObjectAt(nextEntry);
        ASN1Set unsignedAttributeSequence = ASN1Set.getInstance(unsignedAttributes, false);
        AttributeTable attributeTable = new AttributeTable(unsignedAttributeSequence);
        Attribute timeStamp = attributeTable.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
        if (timeStamp != null && timeStamp.getAttrValues().size() > 0) {
            ASN1Set attributeValues = timeStamp.getAttrValues();
            ASN1Sequence tokenSequence = ASN1Sequence.getInstance(attributeValues.getObjectAt(0));
            ContentInfo contentInfo = ContentInfo.getInstance(tokenSequence);
            // if we can parse it we call it good, so cert has a embedded time but we don't do any validation on it
            try {
                new TimeStampToken(contentInfo);
                isEmbeddedTimeStamp = true;
            } catch (Throwable e1) {
                throw new SignatureIntegrityException("Valid TimeStamp could now be created");
            }
        }
    }
}
Also used : Attribute(org.bouncycastle.asn1.cms.Attribute) AttributeTable(org.bouncycastle.asn1.cms.AttributeTable) ContentInfo(org.bouncycastle.asn1.cms.ContentInfo) TimeStampToken(org.bouncycastle.tsp.TimeStampToken) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException)

Example 4 with SignatureIntegrityException

use of org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException in project mucommander by mucommander.

the class AbstractPkcsValidator method checkByteRange.

public boolean checkByteRange() throws SignatureIntegrityException {
    if (signatureFieldDictionary == null) {
        return false;
    }
    ArrayList<Integer> byteRange = signatureFieldDictionary.getSignatureDictionary().getByteRange();
    SeekableInput documentInput = signatureFieldDictionary.getLibrary().getDocumentInput();
    documentInput.beginThreadAccess();
    try {
        long totalLength = documentInput.getLength();
        long digestedLength = byteRange.get(2) + byteRange.get(3);
        // or signatures added after this signature.
        if (digestedLength == totalLength) {
            return true;
        }
    } catch (IOException e) {
        throw new SignatureIntegrityException(e);
    } finally {
        documentInput.endThreadAccess();
    }
    return false;
}
Also used : BigInteger(java.math.BigInteger) SeekableInput(org.icepdf.core.io.SeekableInput) IOException(java.io.IOException) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException)

Example 5 with SignatureIntegrityException

use of org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException in project mucommander by mucommander.

the class Pkcs1Validator method init.

public void init() throws SignatureIntegrityException {
    SignatureDictionary signatureDictionary = signatureFieldDictionary.getSignatureDictionary();
    announceSignatureType(signatureDictionary);
    // start the decode of the raw type.
    StringObject stringObject = signatureDictionary.getContents();
    // make sure we don't loose any bytes converting the string in the raw.
    byte[] cmsData = Utils.convertByteCharSequenceToByteArray(stringObject.getLiteralString());
    // get the certificate
    stringObject = signatureDictionary.getCertString();
    // make sure we don't loose any bytes converting the string in the raw.
    byte[] certsKey = Utils.convertByteCharSequenceToByteArray(stringObject.getLiteralString());
    try {
        X509CertParser x509CertParser = new X509CertParser();
        x509CertParser.engineInit(new ByteArrayInputStream(certsKey));
        certificateChain = x509CertParser.engineReadAll();
        signerCertificate = (X509Certificate) certificateChain.iterator().next();
        // content data is encrypted using the cert above.
        ASN1InputStream asn1InputStream = new ASN1InputStream(new ByteArrayInputStream(cmsData));
        ASN1Primitive tmp = asn1InputStream.readObject();
        messageDigest = ((ASN1OctetString) tmp).getOctets();
        String provider = signatureDictionary.getFilter().getName();
        digestAlgorithmIdentifier = OIWObjectIdentifiers.idSHA1.getId();
        signatureAlgorithmIdentifier = PKCSObjectIdentifiers.rsaEncryption.getId();
        // basic creation and public key check which should throw any format errors.
        createSignature(signerCertificate.getPublicKey(), provider, signatureAlgorithmIdentifier, digestAlgorithmIdentifier);
        // Use RSA/ECB/NoPadding do decrypt the message digest
        Cipher asymmetricCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        // initialize your cipher
        asymmetricCipher.init(Cipher.DECRYPT_MODE, signerCertificate.getPublicKey());
        // assuming, cipherText is a byte array containing your encrypted message
        messageDigest = asymmetricCipher.doFinal(messageDigest);
        // trim the padding bytes
        if (messageDigest.length > 20) {
            // You can create the ASN.1 BER encoding of an MD5, SHA-1, or SHA-256 value by prepending these strings to
            // the 16-byte or 20-byte hash values, respectively:
            // We always assume sha1 which is:
            // ref: sha1   : X'30213009 06052B0E 03021A05 000414'
            // ref: SHA-256: X'3031300D 06096086 48016503 04020105 000420'
            // ref: MD5:     X'3020300C 06082A86 4886F70D 02050500 0410'
            byte[] trunkedMD = new byte[20];
            System.arraycopy(messageDigest, 15, trunkedMD, 0, 20);
            messageDigest = trunkedMD;
        }
    } catch (Exception e) {
        throw new SignatureIntegrityException(e);
    }
    initialized = true;
}
Also used : X509CertParser(org.bouncycastle.jce.provider.X509CertParser) ASN1InputStream(org.bouncycastle.asn1.ASN1InputStream) SignatureDictionary(org.icepdf.core.pobjects.acroform.SignatureDictionary) ByteArrayInputStream(java.io.ByteArrayInputStream) StringObject(org.icepdf.core.pobjects.StringObject) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) Cipher(javax.crypto.Cipher) ASN1Primitive(org.bouncycastle.asn1.ASN1Primitive) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException) SignatureIntegrityException(org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException)

Aggregations

SignatureIntegrityException (org.icepdf.core.pobjects.acroform.signature.exceptions.SignatureIntegrityException)9 IOException (java.io.IOException)3 BigInteger (java.math.BigInteger)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 X509Certificate (java.security.cert.X509Certificate)2 X509CertParser (org.bouncycastle.jce.provider.X509CertParser)2 SeekableInput (org.icepdf.core.io.SeekableInput)2 SignatureDictionary (org.icepdf.core.pobjects.acroform.SignatureDictionary)2 CertificateException (java.security.cert.CertificateException)1 CertificateExpiredException (java.security.cert.CertificateExpiredException)1 Cipher (javax.crypto.Cipher)1 X500Principal (javax.security.auth.x500.X500Principal)1 TreePath (javax.swing.tree.TreePath)1 ASN1InputStream (org.bouncycastle.asn1.ASN1InputStream)1 ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)1 ASN1Primitive (org.bouncycastle.asn1.ASN1Primitive)1 Attribute (org.bouncycastle.asn1.cms.Attribute)1 AttributeTable (org.bouncycastle.asn1.cms.AttributeTable)1 ContentInfo (org.bouncycastle.asn1.cms.ContentInfo)1 TimeStampToken (org.bouncycastle.tsp.TimeStampToken)1