gpt4 book ai didi

pdf - iText - 仅加密嵌入文件

转载 作者:行者123 更新时间:2023-12-03 23:57:46 27 4
gpt4 key购买 nike

我想创建一个未加密的 pdf 文件,其中包含一个带有 iText 的加密嵌入文件,如 PDF 32000-1:2008 的第 7.6.1 节所述。 :

Beginning with PDF 1.5, embedded files can be encrypted in an otherwise unencrypted document



但是,以下示例 (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"));
}

这个结果似乎与规范中的陈述相反:

if the contents of the stream are embedded within the PDF file (see 7.11.4, "Embedded File Streams"), they shall be encrypted like any other stream in the file



上面例子产生的pdf文件包含CF字典中加密嵌入文件流的正确条目:
<</CF<</StdCF<</AuthEvent/EFOpen/CFM/AESV2/Length 16>>>>/EFF/StdCF

规范的表 20 指出:

Conforming writers shall respect this value when encrypting embedded files, except for embedded file streams that have their own crypt filter specifier.



在我们的例子中,流没有自己的 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

这导致以下问题:
  • 这是 iText 中的错误还是我误解了 PDF 规范?
  • 如何使用加密的嵌入文件创建未加密的 pdf 文件
    用 iText?
  • 如果这(还)不可能,是否有任何其他免费库或命令
    线工具来做到这一点?

  • PS:Acrobat Reader DC 和 PDF-XChange Viewer 2.5 要求输入密码才能打开附件,而像 evince 这样的(不符合标准的)读者可以毫无问题地打开附件。但这不是我的问题。我的问题不是关于读者行为和可能的道德,而是关于 pdf 文件本身及其对规范的遵守。

    最佳答案

    2021 年更新:
    Release 7.1.16最终实现了对嵌入文件的加密,否则未加密的 pdf 文档。
    (API 略有变化:在下面的 iText 7 测试中,删除 createEmbeddedFileSpec 的最后一个参数,使其显示为 PdfFileSpec.createEmbeddedFileSpec(pdf,"attached file".getBytes(),null,"attachment.txt",null,null,null); )

    原答案
    由于没有得到任何答案,我对 iText 5.5.9 和 iText 7.0.1 进行了更多测试,得出的结论是 不使用 EMBEDDED_FILES_ONLY 加密嵌入的文件流是 iText 7 新版本中的一个错误 .它只适用于 iText 5 和 ENCRYPTION_AES_256 ,尽管 Acrobat 阅读器发出警告,指出此页面上存在错误,并且可能无法正确显示该页面。详情见下表:
    Summary of test results
    以下是使用 iText 5.5.9 生成上表中使用的 pdf 文件的最小、完整和可验证示例的代码...

    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 7.0.1:
    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;
    }

    }
    我必须承认,我对 iText 人员至少对我的三个问题中的第一个没有反馈感到有点失望,但希望 iText 7 的 future 版本能够正确处理 EMBEDDED_FILES_ONLY旗帜。正如测试所显示的那样,对于 pdf 制作者和读者来说,正确处理此功能似乎绝非易事。

    关于pdf - iText - 仅加密嵌入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39789929/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com