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