You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2017/10/29 19:05:18 UTC

svn commit: r1813701 - in /pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox: cos/COSName.java pdmodel/interactive/digitalsignature/PDSeedValue.java pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java

Author: tilman
Date: Sun Oct 29 19:05:18 2017
New Revision: 1813701

URL: http://svn.apache.org/viewvc?rev=1813701&view=rev
Log:
PDFBOX-3971: add class and methods for certificate seed value dictionary, by Hossam Hazem

Added:
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java   (with props)
Modified:
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValue.java

Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1813701&r1=1813700&r2=1813701&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Sun Oct 29 19:05:18 2017
@@ -116,6 +116,7 @@ public final class COSName extends COSBa
     public static final COSName CCITTFAX_DECODE = new COSName("CCITTFaxDecode");
     public static final COSName CCITTFAX_DECODE_ABBREVIATION = new COSName("CCF");
     public static final COSName CENTER_WINDOW = new COSName("CenterWindow");
+    public static final COSName CERT = new COSName("Cert");
     public static final COSName CF = new COSName("CF");
     public static final COSName CFM = new COSName("CFM");
     //** Acro form field type for choice fields.
@@ -292,6 +293,7 @@ public final class COSName extends COSBa
     public static final COSName INTERPOLATE = new COSName("Interpolate");
     public static final COSName IT = new COSName("IT");
     public static final COSName ITALIC_ANGLE = new COSName("ItalicAngle");
+    public static final COSName ISSUER = new COSName("Issuer");
     // J
     public static final COSName JAVA_SCRIPT = new COSName("JavaScript");
     public static final COSName JBIG2_DECODE = new COSName("JBIG2Decode");
@@ -301,6 +303,7 @@ public final class COSName extends COSBa
     // K
     public static final COSName K = new COSName("K");
     public static final COSName KEYWORDS = new COSName("Keywords");
+    public static final COSName KEY_USAGE = new COSName("KeyUsage");
     public static final COSName KIDS = new COSName("Kids");
     // L
     public static final COSName L = new COSName("L");
@@ -369,6 +372,7 @@ public final class COSName extends COSBa
     public static final COSName OCGS = new COSName("OCGs");
     public static final COSName OCPROPERTIES = new COSName("OCProperties");
     public static final COSName OE = new COSName("OE");
+    public static final COSName OID = new COSName("OID");
     
     /**
      * "OFF", to be used for OCGs, not for Acroform
@@ -489,9 +493,11 @@ public final class COSName extends COSBa
     public static final COSName SUB_FILTER = new COSName("SubFilter");
     public static final COSName SUBJ = new COSName("Subj");
     public static final COSName SUBJECT = new COSName("Subject");
+    public static final COSName SUBJECT_DN = new COSName("SubjectDN");
     public static final COSName SUBTYPE = new COSName("Subtype");
     public static final COSName SUPPLEMENT = new COSName("Supplement");
     public static final COSName SV = new COSName("SV");
+    public static final COSName SV_CERT = new COSName("SVCert");
     public static final COSName SW = new COSName("SW");
     public static final COSName SY = new COSName("Sy");
     public static final COSName SYNCHRONOUS = new COSName("Synchronous");
@@ -532,6 +538,7 @@ public final class COSName extends COSBa
     public static final COSName UNIX = new COSName("Unix");
     public static final COSName URI = new COSName("URI");
     public static final COSName URL = new COSName("URL");
+    public static final COSName URL_TYPE = new COSName("URLType");
     // V
     public static final COSName V = new COSName("V");
     public static final COSName VERISIGN_PPKVS = new COSName("VeriSign.PPKVS");

Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValue.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValue.java?rev=1813701&r1=1813700&r2=1813701&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValue.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValue.java Sun Oct 29 19:05:18 2017
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.common.COSArrayList;
@@ -476,6 +477,35 @@ public class PDSeedValue implements COSO
     }
 
     /**
+     * (Optional) A certificate seed value dictionary containing information about the certificate
+     * to be used when signing.
+     *
+     * @return dictionary
+     */
+    public PDSeedValueCertificate getSeedValueCertificate()
+    {
+        COSBase base = dictionary.getDictionaryObject(COSName.CERT);
+        PDSeedValueCertificate certificate = null;
+        if (base instanceof COSDictionary)
+        {
+            COSDictionary dict = (COSDictionary) base;
+            certificate = new PDSeedValueCertificate(dict);
+        }
+        return certificate;
+    }
+
+    /**
+     * (Optional) A certificate seed value dictionary containing information about the certificate
+     * to be used when signing.
+     *
+     * @param certificate dictionary
+     */
+    public void setSeedValueCertificate(PDSeedValueCertificate certificate)
+    {
+        dictionary.setItem(COSName.CERT, certificate);
+    }
+
+    /**
      * <p>(Optional; PDF 1.6) A time stamp dictionary containing two entries. URL which
      * is a ASCII string specifying the URL to a rfc3161 conform timestamp server and Ff
      * to indicate if a timestamp is required or optional.</p>

Added: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java?rev=1813701&view=auto
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java (added)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java Sun Oct 29 19:05:18 2017
@@ -0,0 +1,685 @@
+/*
+ * Copyright 2017 The Apache Software Foundation.
+ *
+ * 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.apache.pdfbox.pdmodel.interactive.digitalsignature;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.common.COSArrayList;
+import org.apache.pdfbox.pdmodel.common.COSObjectable;
+
+/**
+ * This class represents a certificate seed value dictionary that is in the seed value which puts
+ * constraints on certificates when signing documents.
+ *
+ * @author Hossam Hazem
+ */
+public class PDSeedValueCertificate implements COSObjectable
+{
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_SUBJECT = 1;
+
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_ISSUER = 1 << 1;
+
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_OID = 1 << 2;
+
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_SUBJECT_DN = 1 << 3;
+
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_KEY_USAGE = 1 << 5;
+
+    /**
+     * A Ff flag.
+     */
+    public static final int FLAG_URL = 1 << 6;
+    private final COSDictionary dictionary;
+
+    /**
+     * Default constructor.
+     */
+    public PDSeedValueCertificate()
+    {
+        this.dictionary = new COSDictionary();
+        this.dictionary.setItem(COSName.TYPE, COSName.SV_CERT);
+        this.dictionary.setDirect(true);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param dict The certificate seed value dictionary.
+     */
+    public PDSeedValueCertificate(COSDictionary dict)
+    {
+        this.dictionary = dict;
+        this.dictionary.setDirect(true);
+    }
+
+    /**
+     * Convert this standard java object to a COS dictionary.
+     *
+     * @return The COS dictionary that matches this Java object.
+     */
+    @Override
+    public COSDictionary getCOSObject()
+    {
+        return dictionary;
+    }
+
+    /**
+     *
+     * @return true if the Subject is required
+     */
+    public boolean isSubjectRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_SUBJECT);
+    }
+
+    /**
+     * set true if subject shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified Subject shall be enforced as a constraint.
+     */
+    public void setSubjectRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_SUBJECT, flag);
+    }
+
+    /**
+     *
+     * @return true if the Issuer is required
+     */
+    public boolean isIssuerRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_ISSUER);
+    }
+
+    /**
+     * set true if Issuer shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified Issuer shall be enforced as a constraint.
+     */
+    public void setIssuerRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_ISSUER, flag);
+    }
+
+    /**
+     *
+     * @return true if the OID is required
+     */
+    public boolean isOIDRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_OID);
+    }
+
+    /**
+     * set true if OID shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified OID shall be enforced as a constraint.
+     */
+    public void setOIDRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_OID, flag);
+    }
+
+    /**
+     *
+     * @return true if the Subject DN is required
+     */
+    public boolean isSubjectDNRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_SUBJECT_DN);
+    }
+
+    /**
+     * set true if subject DN shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified Subject DN shall be enforced as a constraint.
+     */
+    public void setSubjectDNRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_SUBJECT_DN, flag);
+    }
+
+    /**
+     *
+     * @return true if the KeyUsage is required
+     */
+    public boolean isKeyUsageRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_KEY_USAGE);
+    }
+
+    /**
+     * set true if KeyUsage shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified KeyUsage shall be enforced as a constraint.
+     */
+    public void setKeyUsageRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_KEY_USAGE, flag);
+    }
+
+    /**
+     *
+     * @return true if the URL is required
+     */
+    public boolean isURLRequired()
+    {
+        return this.getCOSObject().getFlag(COSName.FF, FLAG_URL);
+    }
+
+    /**
+     * set true if URL shall be required as a constraint on signature.
+     *
+     * @param flag if true, the specified URL shall be enforced as a constraint.
+     */
+    public void setURLRequired(boolean flag)
+    {
+        this.getCOSObject().setFlag(COSName.FF, FLAG_URL, flag);
+    }
+
+    /**
+     * Returns list of byte arrays that contains DER-encoded X.509v3 certificates
+     */
+    public List<byte[]> getSubject()
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.SUBJECT);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            return getListOfByteArraysFromCOSArray(array);
+        }
+        return null;
+    }
+
+    /**
+     * (Optional) A list of byte arrays containing DER-encoded X.509v3 certificates that are
+     * acceptable for signing. if
+     * <b>Subject</b> is not null and {@link #isSubjectRequired()} is true then the subject
+     * constraint is enforced on the subjects in this array subjects.
+     *
+     * @param subjects list of byte arrays containing DER-encoded X.509v3 certificates that are
+     * acceptable for signing.
+     */
+    public void setSubject(List<byte[]> subjects)
+    {
+        COSArray array = new COSArray();
+        for (byte[] subject : subjects)
+        {
+            array.add(new COSString(subject));
+        }
+        this.dictionary.setItem(COSName.SUBJECT, array);
+    }
+
+    /**
+     * (Optional) byte array containing DER-encoded X.509v3 certificate that is acceptable for
+     * signing. works like {@link #setSubject(List)} but one byte array
+     *
+     * @param subject byte array containing DER-encoded X.509v3 certificate
+     */
+    public void addSubject(byte[] subject)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.SUBJECT);
+        COSArray array;
+        if (base instanceof COSArray)
+        {
+            array = (COSArray) base;
+        }
+        else
+        {
+            array = new COSArray();
+        }
+        COSString string = new COSString(subject);
+        array.add(string);
+        this.dictionary.setItem(COSName.SUBJECT, array);
+    }
+
+    /**
+     * removes a subject from the list
+     *
+     * @param subject byte array containing DER-encoded X.509v3 certificate
+     */
+    public void removeSubject(byte[] subject)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.SUBJECT);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            array.remove(new COSString(subject));
+        }
+    }
+
+    /**
+     * Returns list of maps that contains subject distinguished names like [(cn: John Doe, o: Doe),
+     * (cn: John Smith)] both keys are typically of the form 'cn', 'o', 'email', '2.5.4.43'; and
+     * values are text strings.
+     */
+    public List<Map<String, String>> getSubjectDN()
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.SUBJECT_DN);
+        if (base instanceof COSArray)
+        {
+            COSArray cosArray = (COSArray) base;
+            List subjectDNList = cosArray.toList();
+            List<Map<String, String>> result = new LinkedList<Map<String, String>>();
+            for (Object subjectDNItem : subjectDNList)
+            {
+                if (subjectDNItem instanceof COSDictionary)
+                {
+                    COSDictionary subjectDNItemDict = (COSDictionary) subjectDNItem;
+                    Map<String, String> subjectDNMap = new HashMap<String, String>();
+                    for (COSName key : subjectDNItemDict.keySet())
+                    {
+                        subjectDNMap.put(key.getName(), subjectDNItemDict.getString(key));
+                    }
+                    result.add(subjectDNMap);
+                }
+            }
+            return result;
+        }
+        return null;
+    }
+
+    /**
+     * (Optional; PDF 1.7) A list of maps, where each map contains key value pairs, that specify the
+     * Subject Distinguished Name (DN) that must be present within the certificate for it to be
+     * acceptable for signing. The certificate must at a minimum contain all the attributes
+     * specified in one of the maps entered.
+     *
+     * @param subjectDN list of maps that contains subject distinguished names
+     */
+    public void setSubjectDN(List<Map<String, String>> subjectDN)
+    {
+        List<COSDictionary> subjectDNDict = new LinkedList<COSDictionary>();
+        for (Map<String, String> subjectDNItem : subjectDN)
+        {
+            COSDictionary dict = new COSDictionary();
+            for (Map.Entry<String, String> entry : subjectDNItem.entrySet())
+            {
+                dict.setItem(entry.getKey(), new COSString(entry.getValue()));
+            }
+            subjectDNDict.add(dict);
+        }
+        this.dictionary.setItem(COSName.SUBJECT_DN,
+                COSArrayList.converterToCOSArray(subjectDNDict));
+    }
+
+    /**
+     * Returns list of key usages of certificate strings where each string is 9 characters long and
+     * each character is one of these values {0, 1, X} 0 for must not set, 1 for must set, X for
+     * don't care. each index in the string represents a key usage:
+     * <ol>
+     * <li>digitalSignature</li>
+     * <li>non-Repudiation</li>
+     * <li>keyEncipherment</li>
+     * <li>dataEncipherment</li>
+     * <li>keyAgreement</li>
+     * <li>keyCertSign</li>
+     * <li>cRLSign</li>
+     * <li>encipherOnly</li>
+     * <li>decipherOnly</li>
+     * </ol>
+     */
+    public List<String> getKeyUsage()
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.KEY_USAGE);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            List<String> keyUsageExtensions = new LinkedList<String>();
+            for (COSBase item : array)
+            {
+                if (item instanceof COSString)
+                {
+                    keyUsageExtensions.add(((COSString) item).getString());
+                }
+            }
+            return keyUsageExtensions;
+        }
+        return null;
+    }
+
+    /**
+     * (Optional; PDF 1.7) A List of ASCII strings, where each string specifies an acceptable
+     * key-usage extension that must be present in the signing certificate. Multiple strings specify
+     * a range of acceptable key-usage extensions; where each string 9 characters long and each
+     * character is one of these values {0, 1, X} 0 for must not set, 1 for must set, X for don't
+     * care. each index in the string represents a key usage:
+     * <ol>
+     * <li>digitalSignature</li>
+     * <li>non-Repudiation</li>
+     * <li>keyEncipherment</li>
+     * <li>dataEncipherment</li>
+     * <li>keyAgreement</li>
+     * <li>keyCertSign</li>
+     * <li>cRLSign</li>
+     * <li>encipherOnly</li>
+     * <li>decipherOnly</li>
+     * </ol>
+     *
+     * @param keyUsageExtensions list of ASCII strings that consists only of {0, 1, X}
+     */
+    public void setKeyUsage(List<String> keyUsageExtensions)
+    {
+        this.dictionary.setItem(COSName.KEY_USAGE,
+                COSArrayList.converterToCOSArray(keyUsageExtensions));
+    }
+
+    /**
+     * (Optional; PDF 1.7) specifies an acceptable key-usage extension that must be presennt in the
+     * signing certificate for works like {@link #setKeyUsage(List)} but takes only one string
+     *
+     * @param keyUsageExtension String that consist only of {0, 1, X}
+     */
+    public void addKeyUsage(String keyUsageExtension)
+    {
+        String allowedChars = "01X";
+        for (int c = 0; c < keyUsageExtension.length(); c++)
+        {
+            if (allowedChars.indexOf(keyUsageExtension.charAt(c)) == -1)
+            {
+                throw new IllegalArgumentException("characters can only be 0, 1, X");
+            }
+        }
+        COSBase base = this.dictionary.getDictionaryObject(COSName.KEY_USAGE);
+        COSArray array;
+        if (base instanceof COSArray)
+        {
+            array = (COSArray) base;
+        }
+        else
+        {
+            array = new COSArray();
+        }
+        COSString string = new COSString(keyUsageExtension);
+        array.add(string);
+        this.dictionary.setItem(COSName.KEY_USAGE, array);
+    }
+
+    /**
+     * works like {@link #addKeyUsage(String)} but enters each character separately
+     *
+     * @param digitalSignature char that is one of {0, 1, X}
+     * @param nonRepudiation char that is one of {0, 1, X}
+     * @param keyEncipherment char that is one of {0, 1, X}
+     * @param dataEncipherment char that is one of {0, 1, X}
+     * @param keyAgreement char that is one of {0, 1, X}
+     * @param keyCertSign char that is one of {0, 1, X}
+     * @param cRLSign char that is one of {0, 1, X}
+     * @param encipherOnly char that is one of {0, 1, X}
+     * @param decipherOnly char that is one of {0, 1, X}
+     */
+    public void addKeyUsage(char digitalSignature, char nonRepudiation, char keyEncipherment,
+            char dataEncipherment, char keyAgreement, char keyCertSign, char cRLSign,
+            char encipherOnly, char decipherOnly)
+    {
+        String string = "" + digitalSignature + nonRepudiation + keyEncipherment + dataEncipherment
+                + keyAgreement + keyCertSign + cRLSign + encipherOnly + decipherOnly;
+        addKeyUsage(string);
+    }
+
+    /**
+     * Removes a key usage extension
+     *
+     * @param keyUsageExtension ASCII string that consists of {0, 1, X}
+     */
+    public void removeKeyUsage(String keyUsageExtension)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.KEY_USAGE);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            array.remove(new COSString(keyUsageExtension));
+        }
+    }
+
+    /**
+     * Returns list of array of bytes of DER-encoded X.509v3 certificates
+     */
+    public List<byte[]> getIssuer()
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.ISSUER);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            return getListOfByteArraysFromCOSArray(array);
+        }
+        return null;
+    }
+
+    /**
+     * (Optional) A list of array of bytes containing DER-encoded X.509v3 certificates of acceptable
+     * issuers. If the signer’s certificate chains up to any of the specified issuers (either
+     * directly or indirectly), the certificate is considered acceptable for signing.
+     *
+     * @param issuers A list of byte array containing DER-encoded X.509v3 certificates
+     */
+    public void setIssuer(List<byte[]> issuers)
+    {
+        COSArray array = new COSArray();
+        for (byte[] issuer : issuers)
+        {
+            array.add(new COSString(issuer));
+        }
+        this.dictionary.setItem(COSName.ISSUER, array);
+    }
+
+    /**
+     * array of bytes containing DER-encoded X.509v3 certificates of acceptable issuers. If the
+     * signer’s certificate chains up to any of the specified issuers (either directly or
+     * indirectly), the certificate is considered acceptable for signing.
+     *
+     * @param issuer A byte array containing DER-encoded X.509v3 certificate
+     */
+    public void addIssuer(byte[] issuer)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.ISSUER);
+        COSArray array;
+        if (base instanceof COSArray)
+        {
+            array = (COSArray) base;
+        }
+        else
+        {
+            array = new COSArray();
+        }
+        COSString string = new COSString(issuer);
+        array.add(string);
+        this.dictionary.setItem(COSName.ISSUER, array);
+    }
+
+    /**
+     * Removes an issuer from the issuers list
+     *
+     * @param issuer A byte array containing DER-encoded X.509v3 certificate
+     */
+    public void removeIssuer(byte[] issuer)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.ISSUER);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            array.remove(new COSString(issuer));
+        }
+    }
+
+    /**
+     * Returns A list of array of bytes that contain Object Identifiers (OIDs) of the certificate
+     * policies that must be present in the signing certificate
+     */
+    public List<byte[]> getOID()
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.OID);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            return getListOfByteArraysFromCOSArray(array);
+        }
+        return null;
+    }
+
+    /**
+     * (Optional) A list of byte arrays that contain Object Identifiers (OIDs) of the certificate
+     * policies that must be present in the signing certificate. This field is only applicable if
+     * the value of Issuer is not empty.
+     *
+     * @param oidByteStrings list of byte arrays that contain OIDs
+     */
+    public void setOID(List<byte[]> oidByteStrings)
+    {
+        COSArray array = new COSArray();
+        for (byte[] oid : oidByteStrings)
+        {
+            array.add(new COSString(oid));
+        }
+        this.dictionary.setItem(COSName.OID, array);
+    }
+
+    /**
+     * works like {@link #setOID(List)} but for one object
+     *
+     * @param oid
+     */
+    public void addOID(byte[] oid)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.OID);
+        COSArray array;
+        if (base instanceof COSArray)
+        {
+            array = (COSArray) base;
+        }
+        else
+        {
+            array = new COSArray();
+        }
+        COSString string = new COSString(oid);
+        array.add(string);
+        this.dictionary.setItem(COSName.OID, array);
+    }
+
+    /**
+     * removes an OID from the list
+     *
+     * @param oid
+     */
+    public void removeOID(byte[] oid)
+    {
+        COSBase base = this.dictionary.getDictionaryObject(COSName.OID);
+        if (base instanceof COSArray)
+        {
+            COSArray array = (COSArray) base;
+            array.remove(new COSString(oid));
+        }
+    }
+
+    /**
+     * returns String of the URL
+     */
+    public String getURL()
+    {
+        return this.dictionary.getString(COSName.URL);
+    }
+
+    /**
+     * (Optional) A URL, the use for which is defined by the URLType entry.
+     *
+     * @param url String of the URL
+     */
+    public void setURL(String url)
+    {
+        this.dictionary.setString(COSName.URL, url);
+    }
+
+    /**
+     * A name indicating the usage of the URL entry. There are standard uses and there can be
+     * implementation-specific use for this URL. The following value specifies a valid standard
+     * usage:
+     * <ul>
+     * <li>Browser, The URL references content that should be displayed in a web browser to allow
+     * enrolling for a new credential if a matching credential is not found. The Ff attribute’s URL
+     * bit is ignored for this usage.</li>
+     * <li>ASSP, The URL references a signature web service that can be used for server-based
+     * signing. If the Ff attribute’s URL bit indicates that this is a required constraint, this
+     * implies that the credential used when signing must come from this server.</li>
+     * </ul>
+     *
+     * @return string of URL type
+     */
+    public String getURLType()
+    {
+        return this.dictionary.getNameAsString(COSName.URL_TYPE);
+    }
+
+    /**
+     * (Optional; PDF 1.7) A name indicating the usage of the URL entry. There are standard uses and
+     * there can be implementation-specific uses for this URL. The following value specifies a valid
+     * standard usage:
+     * <ul>
+     * <li>Browser, The URL references content that should be displayed in a web browser to allow
+     * enrolling for a new credential if a matching credential is not found. The Ff attribute’s URL
+     * bit is ignored for this usage.</li>
+     * <li>ASSP, The URL references a signature web service that can be used for server-based
+     * signing. If the Ff attribute’s URL bit indicates that this is a required constraint, this
+     * implies that the credential used when signing must come from this server.</li>
+     * </ul>
+     * Third parties can extend the use of this attribute with their own attribute values, which
+     * must conform to the guidelines specified in
+     * <a href="http://www.adobe.com/content/dam/acom/en/devnet/pdf/PDF32000_2008.pdf#page=681">PDF
+     * Spec 1.7 Appendix E (PDF Name Registry)</a>
+     * if urlType is not set the default is Browser for URL
+     *
+     * @param urlType String of the urlType
+     */
+    public void setURLType(String urlType)
+    {
+        this.dictionary.setName(COSName.URL_TYPE, urlType);
+    }
+
+    private static List<byte[]> getListOfByteArraysFromCOSArray(COSArray array)
+    {
+        List<byte[]> result = new LinkedList<byte[]>();
+        for (COSBase item : array)
+        {
+            if (item instanceof COSString)
+            {
+                result.add(((COSString) item).getBytes());
+            }
+        }
+        return result;
+    }
+
+}

Propchange: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSeedValueCertificate.java
------------------------------------------------------------------------------
    svn:eol-style = native