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);
}
}
}
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;
}
}
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");
}
}
}
}
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;
}
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;
}
Aggregations