/** * @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; }