You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2014/10/28 18:35:33 UTC
svn commit: r1634927 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java
Author: tilman
Date: Tue Oct 28 17:35:33 2014
New Revision: 1634927
URL: http://svn.apache.org/r1634927
Log:
PDFBOX-2460: fix prepareForDecryption() for BC 1.51 and add verbose error handler, thanks to Ralf Hauser
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java?rev=1634927&r1=1634926&r2=1634927&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/encryption/PublicKeySecurityHandler.java Tue Oct 28 17:35:33 2014
@@ -19,6 +19,7 @@ package org.apache.pdfbox.pdmodel.encryp
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.math.BigInteger;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
@@ -39,7 +40,12 @@ import javax.crypto.IllegalBlockSizeExce
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.PDDocument;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
@@ -57,14 +63,14 @@ import org.bouncycastle.asn1.cms.Recipie
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.TBSCertificateStructure;
+import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.KeyTransRecipientId;
+import org.bouncycastle.cms.RecipientId;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.apache.pdfbox.cos.COSArray;
-import org.apache.pdfbox.cos.COSString;
-import org.apache.pdfbox.pdmodel.PDDocument;
/**
* This class implements the public key security handler described in the PDF specification.
@@ -74,6 +80,11 @@ import org.apache.pdfbox.pdmodel.PDDocum
*/
public final class PublicKeySecurityHandler extends SecurityHandler
{
+ /**
+ * Log instance.
+ */
+ private static final Log LOG = LogFactory.getLog(PublicKeySecurityHandler.class);
+
/** The filter name. */
public static final String FILTER = "Adobe.PubSec";
@@ -107,14 +118,14 @@ public final class PublicKeySecurityHand
*
* @throws IOException If there is an error accessing data.
*/
+ @Override
public void decryptDocument(PDDocument doc, DecryptionMaterial decryptionMaterial) throws IOException
{
this.document = doc;
PDEncryption dictionary = doc.getEncryption();
- prepareForDecryption( dictionary, doc.getDocument().getDocumentID(),
- decryptionMaterial );
+ prepareForDecryption( dictionary, doc.getDocument().getDocumentID(), decryptionMaterial );
proceedDecryption();
}
@@ -131,9 +142,10 @@ public final class PublicKeySecurityHand
*
* @throws IOException If there is an error accessing data.
*/
+ @Override
public void prepareForDecryption(PDEncryption encryption, COSArray documentIDArray,
- DecryptionMaterial decryptionMaterial)
- throws IOException
+ DecryptionMaterial decryptionMaterial)
+ throws IOException
{
if (!(decryptionMaterial instanceof PublicKeyDecryptionMaterial))
{
@@ -161,34 +173,65 @@ public final class PublicKeySecurityHand
byte[][] recipientFieldsBytes = new byte[encryption.getRecipientsLength()][];
int recipientFieldsLength = 0;
-
- for (int i = 0; i < encryption.getRecipientsLength(); i++)
+ int i = 0;
+ String extraInfo = "";
+ for (; i < encryption.getRecipientsLength(); i++)
{
COSString recipientFieldString = encryption.getRecipientStringAt(i);
byte[] recipientBytes = recipientFieldString.getBytes();
CMSEnvelopedData data = new CMSEnvelopedData(recipientBytes);
- Iterator<?> recipCertificatesIt = data.getRecipientInfos().getRecipients()
- .iterator();
+ Iterator<?> recipCertificatesIt = data.getRecipientInfos().getRecipients().iterator();
+ int j = 0;
while (recipCertificatesIt.hasNext())
{
RecipientInformation ri = (RecipientInformation) recipCertificatesIt.next();
// Impl: if a matching certificate was previously found it is an error,
// here we just don't care about it
- if (ri.getRID().match(material.getCertificate()) && !foundRecipient)
+ X509Certificate certificate = material.getCertificate();
+ X509CertificateHolder materialCert = null;
+ if (null != certificate)
+ {
+ materialCert = new X509CertificateHolder(certificate.getEncoded());
+ }
+ RecipientId rid = ri.getRID();
+ if (rid.match(materialCert) && !foundRecipient)
{
foundRecipient = true;
PrivateKey privateKey = (PrivateKey) material.getPrivateKey();
- envelopedData = ri.getContent(new JceKeyTransEnvelopedRecipient(privateKey)
- .setProvider("BC"));
+ envelopedData = ri.getContent(new JceKeyTransEnvelopedRecipient(privateKey).setProvider("BC"));
break;
}
+ j++;
+ if (LOG.isDebugEnabled() && certificate != null)
+ {
+ extraInfo += "\n" + j + ": ";
+ if (rid instanceof KeyTransRecipientId)
+ {
+ KeyTransRecipientId ktRid = (KeyTransRecipientId) rid;
+ BigInteger ridSerialNumber = ktRid.getSerialNumber();
+ if (ridSerialNumber != null)
+ {
+ String certSerial = "unknown";
+ BigInteger certSerialNumber = certificate.getSerialNumber();
+ if (certSerialNumber != null)
+ {
+ certSerial = certSerialNumber.toString(16);
+ }
+ extraInfo += "serial-#: rid " + ridSerialNumber.toString(16)
+ + " vs. cert " + certSerial + " issuer: rid \'"
+ + ktRid.getIssuer() + "\' vs. cert \'"
+ + (materialCert == null ? "null" : materialCert.getIssuer()) + "\' ";
+ }
+ }
+ }
}
recipientFieldsBytes[i] = recipientBytes;
recipientFieldsLength += recipientBytes.length;
}
if (!foundRecipient || envelopedData == null)
{
- throw new IOException("The certificate matches no recipient entry");
+ throw new IOException("The certificate matches none of " + i
+ + " recipient entries" + extraInfo);
}
if (envelopedData.length != 24)
{
@@ -234,6 +277,10 @@ public final class PublicKeySecurityHand
{
throw new IOException(e);
}
+ catch (CertificateEncodingException e)
+ {
+ throw new IOException(e);
+ }
}
/**
@@ -243,6 +290,7 @@ public final class PublicKeySecurityHand
*
* @throws IOException If there is an error while encrypting.
*/
+ @Override
public void prepareDocumentForEncryption(PDDocument doc) throws IOException
{
if (keyLength == 256)