1package org.bouncycastle.cms;
2
3import java.util.Date;
4import java.util.Hashtable;
5import java.util.Map;
6
7import org.bouncycastle.asn1.DERObjectIdentifier;
8import org.bouncycastle.asn1.DEROctetString;
9import org.bouncycastle.asn1.DERSet;
10import org.bouncycastle.asn1.cms.Attribute;
11import org.bouncycastle.asn1.cms.AttributeTable;
12import org.bouncycastle.asn1.cms.CMSAttributes;
13import org.bouncycastle.asn1.cms.Time;
14
15/**
16 * Default signed attributes generator.
17 */
18public class DefaultSignedAttributeTableGenerator
19    implements CMSAttributeTableGenerator
20{
21    private final Hashtable table;
22
23    /**
24     * Initialise to use all defaults
25     */
26    public DefaultSignedAttributeTableGenerator()
27    {
28        table = new Hashtable();
29    }
30
31    /**
32     * Initialise with some extra attributes or overrides.
33     *
34     * @param attributeTable initial attribute table to use.
35     */
36    public DefaultSignedAttributeTableGenerator(
37        AttributeTable attributeTable)
38    {
39        if (attributeTable != null)
40        {
41            table = attributeTable.toHashtable();
42        }
43        else
44        {
45            table = new Hashtable();
46        }
47    }
48
49    /**
50     * Create a standard attribute table from the passed in parameters - this will
51     * normally include contentType, signingTime, and messageDigest. If the constructor
52     * using an AttributeTable was used, entries in it for contentType, signingTime, and
53     * messageDigest will override the generated ones.
54     *
55     * @param parameters source parameters for table generation.
56     *
57     * @return a filled in Hashtable of attributes.
58     */
59    protected Hashtable createStandardAttributeTable(
60        Map parameters)
61    {
62        Hashtable std = (Hashtable)table.clone();
63
64        if (!std.containsKey(CMSAttributes.contentType))
65        {
66            DERObjectIdentifier contentType = (DERObjectIdentifier)
67                parameters.get(CMSAttributeTableGenerator.CONTENT_TYPE);
68
69            // contentType will be null if we're trying to generate a counter signature.
70            if (contentType != null)
71            {
72                Attribute attr = new Attribute(CMSAttributes.contentType,
73                    new DERSet(contentType));
74                std.put(attr.getAttrType(), attr);
75            }
76        }
77
78        if (!std.containsKey(CMSAttributes.signingTime))
79        {
80            Date signingTime = new Date();
81            Attribute attr = new Attribute(CMSAttributes.signingTime,
82                new DERSet(new Time(signingTime)));
83            std.put(attr.getAttrType(), attr);
84        }
85
86        if (!std.containsKey(CMSAttributes.messageDigest))
87        {
88            byte[] messageDigest = (byte[])parameters.get(
89                CMSAttributeTableGenerator.DIGEST);
90            Attribute attr = new Attribute(CMSAttributes.messageDigest,
91                new DERSet(new DEROctetString(messageDigest)));
92            std.put(attr.getAttrType(), attr);
93        }
94
95        return std;
96    }
97
98    /**
99     * @param parameters source parameters
100     * @return the populated attribute table
101     */
102    public AttributeTable getAttributes(Map parameters)
103    {
104        return new AttributeTable(createStandardAttributeTable(parameters));
105    }
106}
107