我想对加密的 PDF 文件进行数字签名。原始 PDF 受密码保护,如果不提供所有者密码,您将无法修改它或复制其中的文本。但是,我发现我可以修改它并在盖上数字签名后仅使用用户密码即可从中复制文本!那么,如何更正代码以在签署 PDF 时保留权限?我使用的代码如下所示,其中
encryptPdf()
是加密 PDF 文件的方法,sign()
是对 PDF 文件进行签名的方法。我已经在 stampingProperties.preserveEncryption();
方法中写入了 sign()
,但仍然无法保留权限。
package net.opho.olympiad.util;
import com.itextpdf.bouncycastleconnector.BouncyCastleFactoryCreator;
import com.itextpdf.kernel.crypto.DigestAlgorithms;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.mac.MacProperties;
import com.itextpdf.kernel.mac.MacProperties.MacDigestAlgorithm;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.signatures.*;
import lombok.extern.slf4j.Slf4j;
import net.opho.olympiad.entity.PdfResource;
import net.opho.olympiad.entity.Signature;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.time.LocalDateTime;
@Slf4j
public class PdfUtil {
public static byte[] encryptPdf(String pdfPath, String userPassword, String ownerPassword) throws IOException {
Security.addProvider(BouncyCastleFactoryCreator.getFactory().getProvider());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
WriterProperties writerProperties = new WriterProperties();
writerProperties.setPdfVersion(PdfVersion.PDF_2_0).setStandardEncryption(
userPassword.getBytes(),
ownerPassword.getBytes(),
EncryptionConstants.ALLOW_PRINTING,
EncryptionConstants.ENCRYPTION_AES_256,
new MacProperties(MacDigestAlgorithm.SHA_256));
PdfDocument pdfDocument = new PdfDocument(new PdfReader(pdfPath), new PdfWriter(byteArrayOutputStream, writerProperties));
pdfDocument.close();
byte[] output = byteArrayOutputStream.toByteArray();
log.info(pdfPath + " encrypted, byte length: " + output.length);
return output;
}
public static byte[] sign(byte[] pdfFileContent, String ownerPassword, Signature signature, String username) throws IOException, GeneralSecurityException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfReader reader = ownerPassword == null ? new PdfReader(new ByteArrayInputStream(pdfFileContent)) : new PdfReader(new ByteArrayInputStream(pdfFileContent), (new ReaderProperties()).setPassword(ownerPassword.getBytes()));
StampingProperties stampingProperties = new StampingProperties();
stampingProperties.preserveEncryption();
PdfSigner signer = new PdfSigner(reader, byteArrayOutputStream, stampingProperties);
SignerProperties signerProperties = new SignerProperties();
signerProperties.setReason("Document for OPhO user " + username).setLocation("OPhO Official Website");
signer.setSignerProperties(signerProperties);
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(signature.getKeyStorage()), signature.getKeyStoragePassword().toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, signature.getKeyStoragePassword().toCharArray());
IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, provider.getName());
IExternalDigest digest = new BouncyCastleDigest();
signer.signDetached(digest, pks, ks.getCertificateChain(alias), null, null, null, 0, PdfSigner.CryptoStandard.CMS);
byte[] output = byteArrayOutputStream.toByteArray();
log.info("Signed, byte length: " + output.length);
return output;
}
}
虽然可以在 PDF 上设置权限,但查看者或其他编辑者不需要使用它们,因此通常会保留但不使用它们。
我将此页保存并拒绝打印和复制。然后,我使用使用 adobe 方法的签名服务,因此大多数用户会认为加密文件是“安全的”,但读者可以打印和复制文本,同时在其信息中显示这些限制。
复制文字
我想对加密的 PDF 文件进行数字签名。原始 PDF 受密码保护, 如果不提供所有者的密码,您将无法修改它或从中复制文本。然而,我 发现我可以修改它并在标记后仅使用用户密码从中复制文本 数字签名!那么,如何更正代码以在签名时保留权限 PDF?我使用的代码如下所示,其中 是一种加密PDF文件的方法