Reputation: 11
I am trying to use itextsharp writer.setEncryption method with nothing to encrypt file without password but it is setting password for some random pdf even if I have passed nothing to encrypt it.
pdf.SetEncryption(Nothing, Nothing, PdfWriter.AllowScreenReaders, PdfWriter.STRENGTH40BITS)
Upvotes: 0
Views: 846
Reputation: 95918
It is working properly.
Please have a look at the documentation of the method you used:
/** Sets the encryption options for this document. The userPassword and the
* ownerPassword can be null or have zero length. In this case the ownerPassword
* is replaced by a random string. The open permissions for the document can be
* AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
* AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
* The permissions can be combined by ORing them.
* @param userPassword the user password. Can be null or empty
* @param ownerPassword the owner password. Can be null or empty
* @param permissions the user permissions
* @param strength128Bits <code>true</code> for 128 bit key length, <code>false</code> for 40 bit key length
* @throws DocumentException if the document is already open
*/
virtual public void SetEncryption(byte[] userPassword, byte[] ownerPassword, int permissions, bool strength128Bits)
So if you don't give a value for the owner password, the documented behavior is that a random string is used, exactly as you observed.
Apparently you try to set the permissions of the PDF to only PdfWriter.AllowScreenReaders
, but setting this permission selection is only possible for encrypted files, and for encryption a non-empty owner password is required, so iText chooses one for you.
An empty user password on the other hand is possible because in the course of its use during encryption and decryption a "default password string" is appended to the user password value anyways.
In answer to questions in comments...
if (ownerPassword == null || ownerPassword.Length == 0)
ownerPassword = DigestAlgorithms.Digest("MD5", CreateDocumentId());
(PdfEncryption
method SetupAllKeys
)
where CreateDocumentId
is defined like this:
public static byte[] CreateDocumentId() {
long time = DateTime.Now.Ticks + Environment.TickCount;
long mem = GC.GetTotalMemory(false);
String s = time + "+" + mem + "+" + (seq++);
byte[] b = Encoding.ASCII.GetBytes(s);
return DigestAlgorithms.Digest("MD5", b);
}
The password is not explicitly stored anywhere for later retrieval. In this situation, i.e. a call for encryption using an empty owner password, it is assumed that the caller is not interested in knowing the password.
If this sounds weird to you, please be aware that for the actual encryption of document data the user password is used, not the owner password. (More exactly a value derived from the user password.) The owner password during document encryption only is used to encrypt the user password (more exactly, a value derived from it) and store that value in the PDF.
When the PDF is opened again and the user provides a password, it is tested whether it can immediately be used for document data decryption (i.e. it is the user password) or whether it can be used to decrypt the above mentioned value to the user password which then can decrypt the document (i.e. it is the owner password).
In either case the user has access to the PDF but if it was only the user password, not the owner password, the PDF processor is expected to restrict the allowed operations according to a given permissions value.
Thus, a caller not giving an owner password here is interpreted to be not interested in anyone having full access to the PDF in a specification conforming PDF processor, for restricted access the user password suffices. This has nothing to do with making the document undecryptable due to a lost password...
Well, MD5 returns a 128 bit hash but as the structure of the hashed data is well known, the password is by far not as strong as a truly random 128 bis value. On the other hand an eight character string usually also is by far not as strong as that...
Upvotes: 1