/*
* Copyright 2006-2017 ICEsoft Technologies Canada Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.icepdf.core.pobjects.security;
import org.icepdf.core.pobjects.*;
import org.icepdf.core.util.Library;
import java.util.HashMap;
import java.util.List;
/**
* <p>The EncryptionDictionary class is used to hold values needed by the Standard
* Security Handler, Public Key Handlers and Crypt filters. This PDF object
* is found via a document's Trailer object, but only when the Trailer has an
* encrypted named reference.</p>
* <br>
* <p>The dictionary is composed of combinations of the following entries defined
* by the different encryption types. ICEpdf currently only supports the
* Standard Security Handler.</p>
* <br>
* <br>
* <table border="1" cellpadding="1" cellspacing="1" summary="" >
* <tr>
* <td colspan="3" ><b>Common to all Encryption Dictionaries</b></td>
* </tr>
* <tr>
* <td><b>Key</b></td>
* <td><b>Type</b></td>
* <td><b>Value</b></td>
* </tr>
* <tr>
* <td valign="top" >Filter</td>
* <td valign="top" >name</td>
* <td>(Required) The name of the preferred security handler for this
* document; typically it is the name of the security handler that was
* used to encrypt the document. If SubFilter is not present, only this
* security handler should be used when opening the document. If it is
* present, viewer applications are free to use any security handler
* that implements the format specified by SubFilter.</td>
* </tr>
* <tr>
* <td valign="top" >SubFilter</td>
* <td valign="top" >name</td>
* <td>(Optional; PDF 1.3) A name that completely specifies the format and
* interpretation of the contents of the encryption dictionary. It is
* needed in order to allow security handlers other than the one
* specified by Filter to decrypt the document. If it is absent, other
* security handlers will not be able to decrypt the document.</td>
* </tr>
* <tr>
* <td valign="top" >V</td>
* <td valign="top" >number</td>
* <td>(Optional but strongly recommended) A code specifying the algorithm
* to be used in encrypting and decrypting the document:
* <ul>
* <li>0 - An algorithm that is undocumented and no longer
* supported, and whose use is strongly discouraged.</li>
* <li>1 - Algorithm 3.1, with an encryption key length
* of 40 bits; see below.</li>
* <li>2 - (PDF 1.4) Algorithm 3.1, but allowing
* encryption key lengths greater than 40 bits.</li>
* <li>3 - (PDF 1.4) An unpublished algorithm allowing encryption
* key lengths ranging from 40 to 128 bits. (This algorithm
* is unpublished as an export requirement of the U.S.
* Department of Commerce.)</li>
* <li>(PDF 1.5) The security handler defines the use of encryption
* and decryption in the document, using the rules specified by
* the CF, StmF, and StrF entries.</li>
* </ul>
* </td>
* </tr>
* <tr>
* <td valign="top" >Length</td>
* <td valign="top" >integer</td>
* <td>(Optional; PDF 1.4; only if V is 2 or 3) The length of the
* encryption key, in bits. The value must be a multiple of 8, in the
* range 40 to 128. Default value: 40.</td>
* </tr>
* <tr>
* <td valign="top" >CF</td>
* <td valign="top" >dictionary</td>
* <td>(Optional; meaningful only when the value of V is 4; PDF 1.5) A
* dictionary whose keys are crypt filter names and whose values are
* the corresponding crypt filter dictionaries.</td>
* </tr>
* <tr>
* <td valign="top" >StmF</td>
* <td valign="top" >name</td>
* <td>(Optional; meaningful only when the value of V is 4; PDF 1.5) The
* name of the crypt filter that is used by default when encrypting
* streams; it must correspond to a key in the CF dictionary or a
* standard crypt filter name. All streams in the document, except for
* cross-reference streams or those that have a crypt entry in their
* Filter array are decrypted by the security handler, using this
* crypt filter.</td>
* </tr>
* <tr>
* <td valign="top" >StrF</td>
* <td valign="top" >name</td>
* <td>(Optional; meaningful only when the value of V is 4; PDF 1.5) The
* name of the crypt filter that is used when decrypting all strings
* in the document; it must correspond to a key in the CF dictionary
* or a standard crypt filter name.</td>
* </tr>
* </table>
* <br>
* <p>The dictionary composes of the following values that can be returned via
* their named mehtod or by a generic getValue method if the key's name is known.
* The values of the O and U entries in this dictionary are used to determine
* whether a password entered when the document is opened is the correct owner
* password, user password, or neither.</p>
* <br>
* <table border="1" cellpadding="1" cellspacing="1" summary="" >
* <tr>
* <td colspan="3" ><b>Standard Encryption Dictionary Entries</b> </td>
* </tr>
* <tr>
* <td><b>Key</b></td>
* <td><b>Type</b></td>
* <td><b>Value</b></td>
* </tr>
* <tr>
* <td valign="top" >R</td>
* <td valign="top" >number</td>
* <td>
* <p>(Required) A number specifying which revision of the standard
* security handler should be used to interpret this dictionary. The
* revision number should be:</p>
* <ul>
* <li>2 if the document is encrypted with a V value less than 2
* and does not have any of the access permissions set (via the
* P entry, below) that are designated "Revision3"</li>
* <li>3 if the document is encrypted with a V value of 2 or 3, or
* has any "Revision 3" access permissions set.</li>
* <li>4 if the document is encrypted with a V value of 4.</li>
* </ul>
* </td>
* </tr>
* <tr>
* <td valign="top" >O</td>
* <td valign="top" >String</td>
* <td>(Required) A 32-byte string, based on both the owner and user
* passwords, that is used in computing the encryption key and in
* determining whether a valid owner password was entered.</td>
* </tr>
* <tr>
* <td valign="top" >U</td>
* <td valign="top" >String</td>
* <td>U string (Required) A 32-byte string, based on the user password,
* that is used in determining whether to prompt the user for a
* password and, if so, whether a valid user or owner password was
* entered.</td>
* <tr>
* <td valign="top" >P</td>
* <td valign="top" >Integer</td>
* <td>(Required) A set of flags specifying which operations are permitted
* when the document is opened with user access.
* </td>
* </tr>
* </table>
* <br>
* <p>Encryption dictionaries for public-key security handlers contain the
* common entries shown above. In addition, they may contain the entries
* shown below.</p>
* <br>
* <table border="1" cellpadding="1" cellspacing="1" summary="">
* <tr>
* <td colspan="3" ><b>Additional public-key Dictionary Entries</b> </td>
* </tr>
* <tr>
* <td><b>Key</b></td>
* <td><b>Type</b></td>
* <td><b>Value</b></td>
* </tr>
* <tr>
* <td valign="top" >Recipients</td>
* <td valign="top" >array</td>
* <td>(Required when SubFilter is adbe.pkcs7.s3 or adbe.pkcs7.s4; PDF 1.3)
* An array of strings, where each string is a PKCS#7 object listing
* recipients that have been granted equal access rights to the document.
* The data contained in the PKCS#7 object includes both a cryptographic
* key that is used to decrypt the encrypted data and the access
* permissions that apply to the recipient list. There should be only
* one object per unique set of access permissions; if a recipient
* appears in more than one list, the permissions used will be those
* found in the first matching list.<br>
* <b>Note:</b><br>
* When SubFilter is adbe.pkcs7.s5, recipient lists are specified in
* the crypt filter dictionary.</td>
* </tr>
* </table>
* <br>
* <p>Encryption dictionaries for crypt filter security handlers contain the
* common entries shown above. In addition, they may contain the entries
* shown below</p>
* <br>
* <table border="1" cellpadding="1" cellspacing="1" summary="" >
* <tr>
* <td colspan="3" ><b> Standard Encryption Dictionary Entries</b> </td>
* </tr>
* <tr>
* <td><b>Key</b></td>
* <td><b>Type</b></td>
* <td><b>Value</b></td>
* </tr>
* <tr>
* <td valign="top" >Type</td>
* <td valign="top" >name</td>
* <td>(Optional) If present, must be CryptFilter for a crypt filter
* dictionary.</td>
* </tr>
* <tr>
* <td valign="top" >CFM</td>
* <td valign="top" >name</td>
* <td>(Optional) The method used, if any, by the viewer application to
* decrypt data. In PDF 1.5, the following values are supported:
* <ul>
* <li>None: (default)the viewer application does not decrypt data,
* but directs the input stream to the security handler for
* decryption.</li>
* <li>V2: the viewer application asks the security handler for the
* decryption key and implicitly decrypts data using Algorithm
* 3.1. A viewer application may ask once for this decryption
* key, then cache the key for subsequent use for streams that
* use the same crypt filter; therefore, there must be a one-to-one
* relationship between a crypt filter name and the corresponding
* decryption key.</li>
* </ul>
* </td>
* </tr>
* <tr>
* <td valign="top" >Length</td>
* <td valign="top" >integer</td>
* <td>(Optional) When the value of CFM is V2, this entry is used to
* indicate the bit length of the decryption key. It must be a multiple
* of 8 in the range of 40 to 128. Default value: 128. When the value
* of CFM is None, security handlers can define their own use of this
* entry, but are encouraged to follow the usage conventions defined
* for V2.</td>
* </tr>
* <tr>
* <td valign="top" >AuthEvent</td>
* <td valign="top" >name</td>
* <td>
* (Optional) The event to be used to trigger the authorization that is
* required to access decryption keys used by this filter. If
* authorization fails, the event should fail. Acceptable values are:
* <ul>
* <li>DocOpen: (default) authorization is required when a document
* is opened.</li>
* <li>EFOpen: authorization is required when about to access embedded
* files.</li>
* </ul>
* If this filter is used as the value of StrF or StmF in the encryption
* dictionary, the viewer application should ignore this key and behave
* as if the value is DocOpen.
* </td>
* </tr>
* </table>
*
* @since 1.1
*/
public class EncryptionDictionary extends Dictionary {
public static final Name FILTER_KEY = new Name("Filter");
public static final Name SUB_FILTER_KEY = new Name("SubFilter");
public static final Name V_KEY = new Name("V");
public static final Name LENGTH_KEY = new Name("Length");
public static final Name R_KEY = new Name("R");
public static final Name O_KEY = new Name("O");
public static final Name U_KEY = new Name("U");
public static final Name P_KEY = new Name("P");
public static final Name CF_KEY = new Name("CF");
public static final Name STMF_KEY = new Name("StmF");
public static final Name STRF_KEY = new Name("StrF");
public static final Name EEF_KEY = new Name("EEF");
public static final Name OE_KEY = new Name("OE");
public static final Name UE_KEY = new Name("UE");
public static final Name PERMS_KEY = new Name("Perms");
public static final Name ENCRYPT_METADATA_KEY = new Name("EncryptMetadata");
// File ID, generated when document is created, first index used by
// encryption algorithms
private List fileID = null;
private CryptFilter cryptFilter;
// Revision 5 authentication holders as they are passwords
// are validate when the key is calculated.
private boolean isAuthenticatedUserPassword;
private boolean isAuthenticatedOwnerPassword;
/**
* Creates a new Encryption Dictionary object.
*
* @param lib library dictionary of all objects in document.
* @param encryptionDictionary dictionary of all values taken from encrypt key
* in the documents Trailer reference.
* @param fileID Vector containing the two file ID values originally
* parsed from the Trailer reference.
*/
public EncryptionDictionary(Library lib, HashMap<Object, Object> encryptionDictionary, List fileID) {
super(lib, encryptionDictionary);
this.entries = encryptionDictionary;
this.fileID = fileID;
}
/**
* Gets the document's File ID.
*
* @return vector containing two values that represent the file ID
*/
public List getFileID() {
return fileID;
}
/**
* Entries common to all encryption dictionaries
*/
/**
* Gets the preferred security handler name.
*
* @return handler name.
*/
public Name getPreferredSecurityHandlerName() {
return library.getName(entries, FILTER_KEY);
}
/**
* Gets the preferred security handler sub-name.
*
* @return handler sub-name.
*/
public Name getPreferredSecurityHandlerSubName() {
return library.getName(entries, SUB_FILTER_KEY);
}
/**
* Gets a code specifying the algorithm to be used in encrypting and
* decrypting the document:
* <ul>
* <li>0 An algorithm that is undocumented. This value shall not be used.</li>
* <li>1 "Algorithm 1: Encryption of data using the RC4 or AES algorithms"
* in 7.6.2, "General Encryption Algorithm," with an encryption key length
* of 40 bits; see below.</li>
* <li>2 (PDF 1.4) "Algorithm 1: Encryption of data using the RC4 or AES
* algorithms"in 7.6.2, "General Encryption Algorithm," but permitting
* encryption key lengths greater than 40 bits.</li>
* <li>3(PDF 1.4) An unpublished algorithm that permits encryption key
* lengths ranging from 40 to 128 bits. This value shall not appear in a
* conforming PDF file.</li>
* <li>4(PDF 1.5) The security handler defines the use of encryption and
* decryption in the document, using the rules specified by the CF, StmF,
* and StrF entries. The default value if this entry is omitted shall be
* 0, but when present should be a value of 1 or greater.</li>
* </ul>
*
* @return encryption version.
*/
public int getVersion() {
return library.getInt(entries, V_KEY);
}
/**
* Gets the length of the encryption key, in bits.
*
* @return length of encryption key.
*/
public int getKeyLength() {
int length = 40;
int len = library.getInt(entries, LENGTH_KEY);
if (len != 0) {
length = len;
}
return length;
}
/**
* Entries added for standard encryption dictionaries
*/
/**
* Gets the revision number of the standard security handler.
*
* @return revision number.
*/
public int getRevisionNumber() {
return library.getInt(entries, R_KEY);
}
/**
* Gets the 32-byte string used for verifying the owner password.
*
* @return 32-byte string representing the key O.
*/
public String getBigO() {
Object tmp = library.getObject(entries, O_KEY);
return getLiteralString(tmp);
}
/**
* Gets the 32-byte string used for verifying the user password.
*
* @return 32-byte string representing the key U.
*/
public String getBigU() {
Object tmp = library.getObject(entries, U_KEY);
return getLiteralString(tmp);
}
/**
* Gets the integer flag which specifies the operation permitted when the
* document is opened with user access.
*
* @return return flag specifying user access.
*/
public int getPermissions() {
return library.getInt(entries, P_KEY);
}
/**
* (Optional; meaningful only when the value of V is 4; PDF 1.5)
* A dictionary whose keys shall be crypt filter names and whose values
* shall be the corresponding crypt filter dictionaries (see Table 25).
* Every crypt filter used in the document shall have an entry in this
* dictionary, except for the standard crypt filter names (see Table 26).
* <br>
* The conforming reader shall ignore entries in CF dictionary with the keys
* equal to those listed in Table 26 and use properties of the respective
* standard crypt filters.
*
* @return crypt filter object if found, null otherwise.
*/
public CryptFilter getCryptFilter() {
if (cryptFilter == null) {
HashMap tmp = (HashMap) library.getObject(entries, CF_KEY);
if (tmp != null) {
cryptFilter = new CryptFilter(library, tmp);
return cryptFilter;
}
}
return cryptFilter;
}
/**
* (Optional; meaningful only when the value of V is 4; PDF 1.5)
* The name of the crypt filter that shall be used by default when decrypting
* streams. The name shall be a key in the CF dictionary or a standard crypt
* filter name specified in Table 26. All streams in the document, except
* for cross-reference streams (see 7.5.8, "Cross-Reference Streams") or
* streams that have a Crypt entry in their Filterarray (see Table 6),
* shall be decrypted by the security handler, using this crypt filter.
* <br>
* Default value: Identity.
* <br>
*
* @return name of the default stream filter name.
*/
public Name getStmF() {
Object tmp = library.getObject(entries, STMF_KEY);
if (tmp != null && tmp instanceof Name) {
return (Name) tmp;
}
return null;
}
/**
* (Optional; meaningful only when the value of V is 4; PDF 1.5)
* The name of the crypt filter that shall be used when decrypting all
* strings in the document. The name shall be a key in the CF dictionary or
* a standard crypt filter name specified in Table 26.
* <br>
* Default value: Identity.
*
* @return name of the default string filter name.
*/
public Name getStrF() {
Object tmp = library.getObject(entries, STRF_KEY);
if (tmp != null && tmp instanceof Name) {
return (Name) tmp;
}
return null;
}
/**
* (Optional; meaningful only when the value of V is 4; PDF 1.6) The name
* of the crypt filter that shall be used when encrypting embedded file
* streams that do not have their own crypt filter specifier; it shall
* correspond to a key in the CFdictionary or a standard crypt filter name
* specified in Table 26.
* <br>
* This entry shall be provided by the security handler. Conforming writers
* shall respect this value when encrypting embedded files, except for
* embedded file streams that have their own crypt filter specifier. If
* this entry is not present, and the embedded file stream does not contain
* a crypt filter specifier, the stream shall be encrypted using the default
* stream crypt filter specified by StmF.
* <br>
* EFF:name
*/
public Name getEEF() {
Object tmp = library.getObject(entries, EEF_KEY);
if (tmp != null && tmp instanceof Name) {
return (Name) tmp;
}
return null;
}
/**
* Gets the 32-byte string, based on the owner and user passwords, that is
* used in the computing the encryption key.
*
* @return 32-byte string representing the key OE.
*/
public String getBigOE() {
Object tmp = library.getObject(entries, OE_KEY);
return getLiteralString(tmp);
}
/**
* Gets the 32-byte string, based on the user password, that is
* used in the computing the encryption key.
*
* @return 32-byte string representing the key UE.
*/
public String getBigUE() {
Object tmp = library.getObject(entries, UE_KEY);
return getLiteralString(tmp);
}
/**
* A16-byte string, encrypted with the file encryption key, that contains an
* encrypted copy of the permission flags.
*
* @return 16-byte string representing the key Perms.
*/
public String getPerms() {
Object tmp = library.getObject(entries, PERMS_KEY);
return getLiteralString(tmp);
}
public String getLiteralString(Object value){
if (value instanceof LiteralStringObject) {
return ((StringObject) value).getLiteralString();
} else if (value instanceof HexStringObject) {
return ((HexStringObject) value).getRawHexToString().toString();
} else {
return null;
}
}
/**
* Indicates whether the document-level metadata stream (see Section 10.2.2,
* "Metadata Streams") is to be encrypted. Applications should respect
* this value.
*
* @return true if document-level metadata is encrypted
*/
public boolean isEncryptMetaData() {
if (entries.containsKey(ENCRYPT_METADATA_KEY)) {
return library.getBoolean(entries, ENCRYPT_METADATA_KEY);
}else{
// default value if not specified.
return true;
}
}
protected boolean isAuthenticatedUserPassword() {
return isAuthenticatedUserPassword;
}
protected void setAuthenticatedUserPassword(boolean authenticatedUserPassword) {
isAuthenticatedUserPassword = authenticatedUserPassword;
}
protected boolean isAuthenticatedOwnerPassword() {
return isAuthenticatedOwnerPassword;
}
protected void setAuthenticatedOwnerPassword(boolean authenticatedOwnerPassword) {
isAuthenticatedOwnerPassword = authenticatedOwnerPassword;
}
/**
* Class utility methods
*/
/**
* Gets any dictionary key specified by the key parameter.
*
* @param key named key to retrieve from dictionary.
* @return return keys value if found; null, otherwise.
*/
public Object getValue(Object key) {
return entries.get(key);
}
public String toString() {
return "Encryption Dictionary: \n" +
" fileID: " + getFileID() + " \n" +
" Filter: " + getPreferredSecurityHandlerName() + " \n" +
" SubFilter: " + getPreferredSecurityHandlerSubName() + " \n" +
" V: " + getVersion() + " \n" +
" P: " + getPermissions() + " \n" +
" Length:" + getKeyLength() + " \n" +
" CF: " + cryptFilter + " \n" +
" StmF: " + getStmF() + " \n" +
" StrF: " + getStrF() + " \n" +
" R: " + getRevisionNumber() + " \n" +
" O: " + getBigO() + " \n" +
" U: " + getBigU() + " \n" +
" UE: " + getBigUE() + " \n" +
" OE: " + getBigOE() + " \n" +
" Recipients: " + "not done yet" + " \n" +
" ";
}
}