科普:PDF加密有两种方式,分别为owner password和user password。它们有什么区别呢?简单来说,设置了user password,在打开PDF的时候就需要输入密码;设置了owner password,可以打开PDF,但是不能修改、拷贝里面的内容。
本文讲述的是破解owner password。
· 重写PdfReader
import com.itextpdf.text.pdf.PdfReader;
import java.io.IOException;
import java.io.InputStream;
public class MyPdfReader extends PdfReader {
public MyPdfReader(final String filename) throws IOException {
super(filename);
}
public MyPdfReader(final byte[] bytes) throws IOException {
super(bytes);
}
public MyPdfReader(final InputStream is) throws IOException {
super(is);
}
public void decryptOnPurpose() {
encrypted = false;
}
}
· 实现解保护
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.exceptions.BadPasswordException;
import com.itextpdf.text.exceptions.InvalidPdfException;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class UnProtectedPDFUtil {
private static MyPdfReader pdfReader = null;
public static byte[] unProtected(byte[] fileBytes) throws Exception {
ByteArrayOutputStream bos = null;
ByteArrayInputStream bis = null;
try {
bos = new ByteArrayOutputStream();
bis = new ByteArrayInputStream(fileBytes);
initPdfReader(bis);
if (checkProtected()) {
unProtectedPdf(bos);
byte[] newBytes = bos.toByteArray();
bos.flush();
return newBytes;
} else {
return fileBytes;
}
} catch (Exception e) {
throw e;
} finally {
if (null != bos) {
bos.close();
}
if (null != bis) {
bis.close();
}
}
}
/**
* Will check user password or owner password. If user password, will throws
* BadPasswordException.
*
* @param is
* @throws BadPasswordException
*/
private static void initPdfReader(final InputStream is) throws BadPasswordException {
try {
pdfReader = new MyPdfReader(is);
} catch (BadPasswordException e) {
// if catch BadPasswordException. it should be user password.
throw new BadPasswordException("Bad password. It should be user password.");
} catch (IOException e) {
return;
}
}
private static boolean checkProtected() throws InvalidPdfException {
if (null == pdfReader) {
throw new InvalidPdfException("Invalid pdf.");
}
// check is owner password (protected).
if (pdfReader.isEncrypted()) {
return true;
} else {
return false;
}
}
private static void unProtectedPdf(OutputStream os) {
PdfStamper stamper = null;
try {
MyPdfReader.unethicalreading = true;
pdfReader.decryptOnPurpose();
stamper = new PdfStamper(pdfReader, os);
} catch (DocumentException e) {
return;
} catch (IOException e) {
return;
} finally {
try {
if (null != stamper) {
stamper.close();
}
} catch (Exception e) {
return;
}
}
}
}
· 使用样例
byte[] unProtectedBytes = UnProtectedPdfUtil.unProtected(byte[] fileBytes);