/**
* @throws IOException
*/
private void ReadDecryptedDocObj() {
if (encrypted)
return;
PdfObject encDic = trailer.Get(PdfName.ENCRYPT);
if (encDic == null || encDic.ToString().Equals("null"))
return;
encryptionError = true;
byte[] encryptionKey = null;
encrypted = true;
PdfDictionary enc = (PdfDictionary)GetPdfObject(encDic);
String s;
PdfObject o;
PdfArray documentIDs = trailer.GetAsArray(PdfName.ID);
byte[] documentID = null;
if (documentIDs != null) {
o = documentIDs[0];
strings.Remove((PdfString)o);
s = o.ToString();
documentID = DocWriter.GetISOBytes(s);
if (documentIDs.Size > 1)
strings.Remove((PdfString)documentIDs[1]);
}
// just in case we have a broken producer
if (documentID == null)
documentID = new byte[0];
byte[] uValue = null;
byte[] oValue = null;
int cryptoMode = PdfWriter.STANDARD_ENCRYPTION_40;
int lengthValue = 0;
PdfObject filter = GetPdfObjectRelease(enc.Get(PdfName.FILTER));
if (filter.Equals(PdfName.STANDARD)) {
s = enc.Get(PdfName.U).ToString();
strings.Remove((PdfString)enc.Get(PdfName.U));
uValue = DocWriter.GetISOBytes(s);
s = enc.Get(PdfName.O).ToString();
strings.Remove((PdfString)enc.Get(PdfName.O));
oValue = DocWriter.GetISOBytes(s);
if (enc.Contains(PdfName.OE))
strings.Remove((PdfString)enc.Get(PdfName.OE));
if (enc.Contains(PdfName.UE))
strings.Remove((PdfString)enc.Get(PdfName.UE));
if (enc.Contains(PdfName.PERMS))
strings.Remove((PdfString)enc.Get(PdfName.PERMS));
o = enc.Get(PdfName.P);
if (!o.IsNumber())
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.p.value"));
pValue = ((PdfNumber)o).IntValue;
o = enc.Get(PdfName.R);
if (!o.IsNumber())
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.r.value"));
rValue = ((PdfNumber)o).IntValue;
switch (rValue) {
case 2:
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_40;
break;
case 3:
o = enc.Get(PdfName.LENGTH);
if (!o.IsNumber())
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.length.value"));
lengthValue = ( (PdfNumber) o).IntValue;
if (lengthValue > 128 || lengthValue < 40 || lengthValue % 8 != 0)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.length.value"));
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
break;
case 4:
PdfDictionary dic = (PdfDictionary)enc.Get(PdfName.CF);
if (dic == null)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("cf.not.found.encryption"));
dic = (PdfDictionary)dic.Get(PdfName.STDCF);
if (dic == null)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("stdcf.not.found.encryption"));
if (PdfName.V2.Equals(dic.Get(PdfName.CFM)))
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
else if (PdfName.AESV2.Equals(dic.Get(PdfName.CFM)))
cryptoMode = PdfWriter.ENCRYPTION_AES_128;
else
throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("no.compatible.encryption.found"));
PdfObject em = enc.Get(PdfName.ENCRYPTMETADATA);
if (em != null && em.ToString().Equals("false"))
cryptoMode |= PdfWriter.DO_NOT_ENCRYPT_METADATA;
break;
case 5:
cryptoMode = PdfWriter.ENCRYPTION_AES_256;
PdfObject em5 = enc.Get(PdfName.ENCRYPTMETADATA);
if (em5 != null && em5.ToString().Equals("false"))
cryptoMode |= PdfWriter.DO_NOT_ENCRYPT_METADATA;
break;
default:
throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("unknown.encryption.type.r.eq.1", rValue));
}
} else if (filter.Equals(PdfName.PUBSEC)) {
bool foundRecipient = false;
byte[] envelopedData = null;
PdfArray recipients = null;
o = enc.Get(PdfName.V);
if (!o.IsNumber())
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.v.value"));
int vValue = ((PdfNumber)o).IntValue;
switch(vValue) {
case 1:
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_40;
lengthValue = 40;
recipients = (PdfArray)enc.Get(PdfName.RECIPIENTS);
break;
case 2:
o = enc.Get(PdfName.LENGTH);
if (!o.IsNumber())
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.length.value"));
lengthValue = ( (PdfNumber) o).IntValue;
if (lengthValue > 128 || lengthValue < 40 || lengthValue % 8 != 0)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("illegal.length.value"));
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
recipients = (PdfArray)enc.Get(PdfName.RECIPIENTS);
break;
case 4:
case 5:
PdfDictionary dic = (PdfDictionary)enc.Get(PdfName.CF);
if (dic == null)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("cf.not.found.encryption"));
dic = (PdfDictionary)dic.Get(PdfName.DEFAULTCRYPTFILTER);
if (dic == null)
throw new InvalidPdfException(MessageLocalization.GetComposedMessage("defaultcryptfilter.not.found.encryption"));
if (PdfName.V2.Equals(dic.Get(PdfName.CFM))) {
cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
lengthValue = 128;
}
else if (PdfName.AESV2.Equals(dic.Get(PdfName.CFM))) {
cryptoMode = PdfWriter.ENCRYPTION_AES_128;
lengthValue = 128;
}
else if (PdfName.AESV3.Equals(dic.Get(PdfName.CFM))) {
cryptoMode = PdfWriter.ENCRYPTION_AES_256;
lengthValue = 256;
}
else
throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("no.compatible.encryption.found"));
PdfObject em = dic.Get(PdfName.ENCRYPTMETADATA);
if (em != null && em.ToString().Equals("false"))
cryptoMode |= PdfWriter.DO_NOT_ENCRYPT_METADATA;
recipients = (PdfArray)dic.Get(PdfName.RECIPIENTS);
break;
default:
throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("unknown.encryption.type.v.eq.1", vValue));
}
for (int i = 0; i<recipients.Size; i++)
{
PdfObject recipient = recipients[i];
if (recipient is PdfString)
strings.Remove((PdfString)recipient);
CmsEnvelopedData data = null;
data = new CmsEnvelopedData(recipient.GetBytes());
foreach (RecipientInformation recipientInfo in data.GetRecipientInfos().GetRecipients()) {
if (recipientInfo.RecipientID.Match(certificate) && !foundRecipient) {
envelopedData = recipientInfo.GetContent(certificateKey);
foundRecipient = true;
}
}
}
if (!foundRecipient || envelopedData == null)
{
throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("bad.certificate.and.key"));
}
IDigest sh;
if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.ENCRYPTION_AES_256)
sh = DigestUtilities.GetDigest("SHA-256");
else
sh = DigestUtilities.GetDigest("SHA-1");
sh.BlockUpdate(envelopedData, 0, 20);
for (int i=0; i<recipients.Size; i++) {
byte[] encodedRecipient = recipients[i].GetBytes();
sh.BlockUpdate(encodedRecipient, 0, encodedRecipient.Length);
}
if ((cryptoMode & PdfWriter.DO_NOT_ENCRYPT_METADATA) != 0)
sh.BlockUpdate(PdfEncryption.metadataPad, 0, PdfEncryption.metadataPad.Length);
encryptionKey = new byte[sh.GetDigestSize()];
sh.DoFinal(encryptionKey, 0);
}
decrypt = new PdfEncryption();
decrypt.SetCryptoMode(cryptoMode, lengthValue);
if (filter.Equals(PdfName.STANDARD)) {
if (rValue == 5) {
ownerPasswordUsed = decrypt.ReadKey(enc, password);
pValue = decrypt.GetPermissions();
}
else {
//check by owner password
decrypt.SetupByOwnerPassword(documentID, password, uValue, oValue, pValue);
if (!EqualsArray(uValue, decrypt.userKey, (rValue == 3 || rValue == 4) ? 16 : 32)) {
//check by user password
decrypt.SetupByUserPassword(documentID, password, oValue, pValue);
if (!EqualsArray(uValue, decrypt.userKey, (rValue == 3 || rValue == 4) ? 16 : 32)) {
throw new BadPasswordException(MessageLocalization.GetComposedMessage("bad.user.password"));
}
}
else
ownerPasswordUsed = true;
}
} else if (filter.Equals(PdfName.PUBSEC)) {
if ((cryptoMode & PdfWriter.ENCRYPTION_MASK) == PdfWriter.ENCRYPTION_AES_256)
decrypt.SetKey(encryptionKey);
else
decrypt.SetupByEncryptionKey(encryptionKey, lengthValue);
ownerPasswordUsed = true;
}
for (int k = 0; k < strings.Count; ++k) {
PdfString str = strings[k];
str.Decrypt(this);
}
if (encDic.IsIndirect()) {
cryptoRef = (PRIndirectReference)encDic;
xrefObj[cryptoRef.Number] = null;
}
encryptionError = false;
}