/*
* 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.acroform;
import org.icepdf.core.pobjects.Dictionary;
import org.icepdf.core.pobjects.HexStringObject;
import org.icepdf.core.pobjects.Name;
import org.icepdf.core.pobjects.StringObject;
import org.icepdf.core.util.Library;
import org.icepdf.core.util.Utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* A digital signature (PDF 1.3) may be used to authenticate the identity of a user and the document’s contents. It stores
* information about the signer and the state of the document when it was signed. The signature may be purely mathematical,
* such as a public/private-key encrypted document digest, or it may be a biometric form of identification, such as a
* handwritten signature, fingerprint, or retinal scan. The specific form of authentication used shall be implemented by
* a special software module called a signature handler.
*
* The SignatureDictionary store root data for signing and verifying signature in a document.
*/
public class SignatureDictionary extends Dictionary {
/**
* (Required; inheritable) The name of the preferred signature handler to use when validating this signature.
* If the Prop_Build entry is not present, it shall be also the name of the signature handler that was used to
* create the signature. If Prop_Build is present, it may be used to determine the name of the handler that
* created the signature (which is typically the same as Filter but is not needed to be). A conforming reader may
* substitute a different handler when verifying the signature, as long as it supports the specified SubFilter
* format. Example signature handlers are Adobe.PPKLite, Entrust.PPKEF, CICI.SignIt, and VeriSign.PPKVS. The name
* of the filter (i.e. signature handler) shall be identified in accordance with the rules defined in Annex E.
*/
public static final Name FILTER_KEY = new Name("Filter");
/**
* (Optional) A name that describes the encoding of the signature value and key information in the signature dictionary.
* A conforming reader may use any handler that supports this format to validate the signature.
* <br>
* (PDF 1.6) The following values for public-key cryptographic signatures shall be used: adbe.x509.rsa_sha1,
* adbe.pkcs7.detached, and adbe.pkcs7.sha1 (see 12.8.3, Signature Interoperability). Other values may be defined
* by developers, and when used, shall be prefixed with the registered developer identification. All prefix names
* shall be registered (see Annex E). The prefix adbe has been registered by Adobe Systems and the three subfilter
* names listed above and defined in 12.8.3, Signature Interoperability may be used by any developer.
*/
public static final Name SUB_FILTER_KEY = new Name("SubFilter");
/**
* (Required) The signature value. When ByteRange is present, the value shall be a hexadecimal string (see 7.3.4.3,
* "Hexadecimal Strings") representing the value of the byte range digest.
* <br>
* For public-key signatures, Contents should be either a DER-encoded PKCS#1 binary data object or a DER-encoded
* PKCS#7 binary data object.
* Space for the Contents value must be allocated before the message digest is computed. (See 7.3.4, String Objects)
*/
public static final Name CONTENTS_KEY = new Name("Contents");
/**
* (Required when SubFilter is adbe.x509.rsa_sha1) An array of byte strings that shall represent the X.509
* certificate chain used when signing and verifying signatures that use public-key cryptography, or a byte
* string if the chain has only one entry. The signing certificate shall appear first in the array; it shall
* be used to verify the signature value in Contents, and the other certificateChain shall be used to verify the
* authenticity of the signing certificate.
* <br>
* If SubFilter is adbe.pkcs7.detached or adbe.pkcs7.sha1, this entry shall not be used, and the certificate chain
* shall be put in the PKCS#7 envelope in Contents.
*/
public static final Name CERT_KEY = new Name("Cert");
/**
* (Required for all signatures that are part of a signature field and usage rights signatures referenced from the
* UR3 entry in the permissions dictionary) An array of pairs of integers (starting byte offset, length in bytes)
* that shall describe the exact byte range for the digest calculation. Multiple discontiguous byte ranges shall
* be used to describe a digest that does not include the signature value (theContents entry) itself.
*/
public static final Name BYTE_RANGE_KEY = new Name("ByteRange");
/**
* (Optional; PDF 1.5) An array of signature reference dictionaries (see Table 253).
*/
public static final Name REFERENCE_KEY = new Name("Reference");
/**
* (Optional) An array of three integers that shall specify changes to the document that have been made between the
* previous signature and this signature: in this order, the number of pages altered, the number of fields altered,
* and the number of fields filled in.
* <br>
* The ordering of signatures shall be determined by the value of ByteRange. Since each signature results in an
* incremental save, later signatures have a greater length value.
*/
public static final Name CHANGES_KEY = new Name("Changes");
/**
* (Optional) The name of the person or authority signing the document. This value should be used only when it is
* not possible to extract the name from the signature.
* <br>
* EXAMPLE 1 <br>
* From the certificate of the signer.
*/
public static final Name NAME_KEY = new Name("Name");
/**
* (Optional) The time of signing. Depending on the signature handler, this may be a normal unverified computer
* time or a time generated in a verifiable way from a secure time server.
* <br>
* This value should be used only when the time of signing is not available in the signature.
* <br>
* EXAMPLE 2<br>
* A time stamp can be embedded in a PKCS#7 binary data object
* (see 12.8.3.3, PKCS#7 Signatures as used in ISO 32000).
*/
public static final Name M_KEY = new Name("M");
/**
* (Optional) The CPU host name or physical location of the signing.
*/
public static final Name LOCATION_KEY = new Name("Location");
/**
* (Optional) The reason for the signing, such as (I agree).
*/
public static final Name REASON_KEY = new Name("Reason");
/**
* (Optional) The version of the signature handler that was used to create the signature. (PDF 1.5) This entry
* shall not be used, and the information shall be stored in the Prop_Build dictionary.
*/
public static final Name R_KEY = new Name("R");
/**
* (Optional; PDF 1.5) The version of the signature dictionary format. It corresponds to the usage of the signature
* dictionary in the context of the value of SubFilter. The value is 1 if the Reference dictionary shall be
* considered critical to the validation of the signature.
* <br>
* Default value: 0.
*/
public static final Name V_KEY = new Name("V");
/**
* (Optional; PDF 1.5) A dictionary that may be used by a signature handler to record information that captures the
* state of the computer environment used for signing, such as the name of the handler used to create the signature,
* software build date, version, and operating system.
* <br>
* The PDF Signature Build Dictionary Specification, provides implementation guidelines for the use of this dictionary.
*/
public static final Name PROP_BUILD_KEY = new Name("Prop_Build");
/**
* (Optional; PDF 1.5) The number of seconds since the signer was last authenticated, used in claims of signature
* repudiation. It should be omitted if the value is unknown.
*/
public static final Name PROP_AUTH_TYPE_KEY = new Name("Prop_AuthType");
/**
* Optional; PDF 1.5) The method that shall be used to authenticate the signer, used in claims of signature
* repudiation. Valid values shall be PIN, Password, and Fingerprint.
*/
public static final Name PROP_AUTH_TIME_KEY = new Name("Prop_AuthTime");
/**
* (Optional) Information provided by the signer to enable a recipient to contact the signer to verify the signature.
* <br>
* EXAMPLE 3<br>
* A phone number.
*/
public static final Name CONTACT_INFO_KEY = new Name("ContactInfo");
public SignatureDictionary(Library library, HashMap entries) {
super(library, entries);
}
public Name getFilter() {
return library.getName(entries, FILTER_KEY);
}
public void setFilter(Name filterName) {
entries.put(FILTER_KEY, filterName);
}
public Name getSubFilter() {
return library.getName(entries, SUB_FILTER_KEY);
}
public void setSubFilter(Name filterName) {
entries.put(SUB_FILTER_KEY, filterName);
}
public HexStringObject getContents() {
Object tmp = library.getObject(entries, CONTENTS_KEY);
if (tmp instanceof HexStringObject) {
return (HexStringObject) tmp;
} else {
return null;
}
}
public void setContents(HexStringObject hexString) {
entries.put(CONTENTS_KEY, hexString);
}
public boolean isCertArray() {
return library.getObject(entries, CERT_KEY) instanceof List;
}
public boolean isCertString() {
return library.getObject(entries, CERT_KEY) instanceof StringObject;
}
public ArrayList<StringObject> getCertArray() {
Object tmp = library.getObject(entries, CERT_KEY);
if (tmp instanceof List) {
return (ArrayList) tmp;
} else {
return null;
}
}
public StringObject getCertString() {
Object tmp = library.getObject(entries, CERT_KEY);
if (tmp instanceof StringObject) {
return (StringObject) tmp;
} else {
return null;
}
}
public void setCert(Object cert) {
entries.put(CERT_KEY, cert);
}
public ArrayList<Integer> getByteRange() {
Object tmp = library.getObject(entries, BYTE_RANGE_KEY);
if (tmp instanceof List) {
return (ArrayList) tmp;
} else {
return null;
}
}
public void setByteRangeKey(ArrayList<Integer> range) {
entries.put(BYTE_RANGE_KEY, range);
}
public ArrayList<SignatureReferenceDictionary> getReferences() {
List<HashMap> tmp = library.getArray(entries, REFERENCE_KEY);
if (tmp != null && tmp.size() > 0) {
ArrayList<SignatureReferenceDictionary> references = new ArrayList<SignatureReferenceDictionary>(tmp.size());
for (HashMap reference : tmp) {
references.add(new SignatureReferenceDictionary(library, reference));
}
return references;
} else {
return null;
}
}
public ArrayList<Integer> getChanges() {
Object tmp = library.getArray(entries, CHANGES_KEY);
if (tmp instanceof ArrayList) {
return (ArrayList<Integer>) tmp;
} else {
return null;
}
}
public String getName() {
Object tmp = library.getObject(entries, NAME_KEY);
if (tmp instanceof StringObject) {
return Utils.convertStringObject(library, (StringObject) tmp);
} else {
return null;
}
}
public String getDate() {
return library.getString(entries, M_KEY);
}
public String getLocation() {
Object tmp = library.getObject(entries, LOCATION_KEY);
if (tmp instanceof StringObject) {
return Utils.convertStringObject(library, (StringObject) tmp);
} else {
return null;
}
}
public String getReason() {
Object tmp = library.getObject(entries, REASON_KEY);
if (tmp instanceof StringObject) {
return Utils.convertStringObject(library, (StringObject) tmp);
} else {
return null;
}
}
public String getContactInfo() {
Object tmp = library.getObject(entries, CONTACT_INFO_KEY);
if (tmp instanceof StringObject) {
return Utils.convertStringObject(library, (StringObject) tmp);
} else {
return null;
}
}
public int getHandlerVersion() {
return library.getInt(entries, R_KEY);
}
public int getDictionaryVersion() {
return library.getInt(entries, V_KEY);
}
public HashMap getBuildDictionary() {
return library.getDictionary(entries, PROP_BUILD_KEY);
}
public int getAuthTime() {
return library.getInt(entries, PROP_AUTH_TIME_KEY);
}
public Name getAuthType() {
return library.getName(entries, PROP_AUTH_TYPE_KEY);
}
}