我想创建一个未加密的pdf文件,其中包含带有iText的加密嵌入文件,如PDF 32000-1:2008第7.6.1节所述:
从PDF 1.5开始,嵌入式文件可以加密 否则未加密的文件
但是,以下示例(iText 7.0.1)生成一个PDF文件,其中包含未加密的嵌入式文件流(关闭压缩以更好地分析生成的PDF文件):
/* cf. 7.6.3.1: Documents in which only file attachments are
encrypted shall use the same password as the user and owner password.*/
PdfWriter writer = new PdfWriter(fileName, new WriterProperties()
.setStandardEncryption("secret".getBytes(),
"secret".getBytes(), EncryptionConstants.ALLOW_PRINTING |
EncryptionConstants.ALLOW_MODIFY_ANNOTATIONS,
EncryptionConstants.ENCRYPTION_AES_128 |
EncryptionConstants.DO_NOT_ENCRYPT_METADATA |
EncryptionConstants.EMBEDDED_FILES_ONLY)
.setCompressionLevel(CompressionConstants.NO_COMPRESSION));
PdfDocument pdf = new PdfDocument(writer);
PdfFileSpec fs = PdfFileSpec.createEmbeddedFileSpec(pdf,"attached file".getBytes(),
null,"attachment.txt",null,null,null,true);
pdf.addFileAttachment("attachment.txt", fs);
try (Document doc = new Document(pdf)) {
doc.add(new Paragraph("main file"));
}
此结果似乎与规范说明相反:
如果流的内容嵌入在PDF文件中(请参阅 7.11.4,"嵌入式文件流"),它们应像文件中的任何其他流一样加密
上面示例生成的pdf文件包含CF字典中加密嵌入文件流的正确条目:
<</CF<</StdCF<</AuthEvent/EFOpen/CFM/AESV2/Length 16>>>>/EFF/StdCF
规范表20中的表格:
在加密嵌入时,符合编写者应尊重此值 文件,除了具有自己的crypt的嵌入式文件流 过滤器说明符。
我们案例中的流没有自己的CF说明符,因此应使用AESV2进行加密。但是,在我们的示例中,流未加密:
4 0 obj
<</Length 13/Params<</ModDate(D:20160930101501+02'00')/Size 13>>/Subtype /application#2foctet-stream/Type/EmbeddedFile>>stream
attached file
endstream
endobj
这导致以下问题:
PS:Acrobat Reader DC和PDF-XChange Viewer 2.5要求输入密码才能打开附件,而(不符合要求)的读者如evince打开附件时没有任何问题。但这不是我的问题。我的问题不是关于读者行为和可能的道德问题,而是关于pdf文件本身及其对规范的遵守情况。
答案 0 :(得分:1)
由于我没有得到任何答案,我使用iText 5.5.9和iText 7.0.1进行了更多测试,并得出结论不用override func viewDidLoad() {
super.viewDidLoad()
myImageView.image = newphoto
}
加密嵌入式文件流新版iText 7中的错误。它仅适用于iText 5和EMBEDDED_FILES_ONLY
,但Acrobat reader会发出警告,指出此页面上存在错误,并且可能无法正确显示页面。有关详细信息,请参阅下表:
以下是使用iText 5.5.9生成上表中使用的pdf文件的最小,完整和可验证示例的代码...
ENCRYPTION_AES_256
...和iText 7.0.1:
package pdfencryptef_itext5;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfFileSpecification;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class PDFEncryptEF_iText5 {
public static void main(String[] args) throws Exception {
new PDFEncryptEF_iText5().createPDF("iText5_STD128.pdf", PdfWriter.STANDARD_ENCRYPTION_128);
new PDFEncryptEF_iText5().createPDF("iText5_AES128.pdf", PdfWriter.ENCRYPTION_AES_128);
new PDFEncryptEF_iText5().createPDF("iText5_AES256.pdf", PdfWriter.ENCRYPTION_AES_256);
Security.addProvider(new BouncyCastleProvider());
new PDFEncryptEF_iText5().createPDF("iText5_AES128C.pdf", -PdfWriter.ENCRYPTION_AES_128);
new PDFEncryptEF_iText5().createPDF("iText5_AES256C.pdf", -PdfWriter.ENCRYPTION_AES_256);
}
public void createPDF(String fileName, int encryption ) throws FileNotFoundException, DocumentException, IOException, CertificateException {
Document document = new Document();
Document.compress = false;
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(fileName));
if( encryption >= 0 ){
writer.setEncryption("secret".getBytes(),"secret".getBytes(), 0,
encryption | PdfWriter.EMBEDDED_FILES_ONLY);
} else {
Certificate cert = getPublicCertificate("MyCert.cer" );
writer.setEncryption( new Certificate[] {cert}, new int[] {0}, -encryption | PdfWriter.EMBEDDED_FILES_ONLY);
}
writer.setPdfVersion(PdfWriter.VERSION_1_6);
document.open();
PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(writer, null, "attachment.txt", "attached file".getBytes(), 0);
writer.addFileAttachment( fs );
document.add(new Paragraph("main file"));
document.close();
}
public Certificate getPublicCertificate(String path) throws IOException, CertificateException {
FileInputStream is = new FileInputStream(path);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
return cert;
}
}
我必须承认,我对iText人员至少在我的三个问题中的第一个问题没有反馈感到有点失望,但希望未来版本的iText 7能够正确处理package pdfencryptef_itext7;
import com.itextpdf.kernel.pdf.CompressionConstants;
import com.itextpdf.kernel.pdf.EncryptionConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfVersion;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.kernel.pdf.filespec.PdfFileSpec;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class PDFEncryptEF_iText7 {
public static void main(String[] args) throws Exception {
new PDFEncryptEF_iText7().createPDF("iText7_STD128.pdf", EncryptionConstants.STANDARD_ENCRYPTION_128);
new PDFEncryptEF_iText7().createPDF("iText7_AES128.pdf", EncryptionConstants.ENCRYPTION_AES_128);
new PDFEncryptEF_iText7().createPDF("iText7_AES256.pdf", EncryptionConstants.ENCRYPTION_AES_256);
Security.addProvider(new BouncyCastleProvider());
new PDFEncryptEF_iText7().createPDF("iText7_AES128C.pdf", -EncryptionConstants.ENCRYPTION_AES_128);
new PDFEncryptEF_iText7().createPDF("iText7_AES256C.pdf", -EncryptionConstants.ENCRYPTION_AES_256);
}
public void createPDF(String fileName, int encryption ) throws FileNotFoundException, IOException, CertificateException{
PdfWriter writer;
if( encryption >= 0 ){
writer = new PdfWriter(fileName, new WriterProperties().setStandardEncryption("secret".getBytes(),"secret".getBytes(),
0,
encryption | EncryptionConstants.EMBEDDED_FILES_ONLY)
.setPdfVersion(PdfVersion.PDF_1_6));
} else {
Certificate cert = getPublicCertificate("MyCert.cer" );
writer = new PdfWriter(fileName, new WriterProperties().setPublicKeyEncryption( new Certificate[] {cert},
new int[] {0},
-encryption | EncryptionConstants.EMBEDDED_FILES_ONLY )
.setPdfVersion(PdfVersion.PDF_1_6));
}
writer.setCompressionLevel(CompressionConstants.NO_COMPRESSION);
PdfDocument pdf = new PdfDocument(writer);
PdfFileSpec fs = PdfFileSpec.createEmbeddedFileSpec(pdf,"attached file".getBytes(),null,"attachment.txt",null,null,null,true);
pdf.addFileAttachment("attachment.txt", fs);
try (Document doc = new Document(pdf)) {
doc.add(new Paragraph("main file"));
}
}
public Certificate getPublicCertificate(String path) throws IOException, CertificateException {
FileInputStream is = new FileInputStream(path);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
return cert;
}
}
旗。正如测试所显示的那样,对于pdf制作人和读者来说,正确处理这一功能似乎远非微不足道。