1e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompackage org.bouncycastle.cms; 2e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 3e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.IOException; 4e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.OutputStream; 5e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.ArrayList; 6e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Enumeration; 7e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Iterator; 8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.List; 9e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 10e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Encodable; 11e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1EncodableVector; 12e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Encoding; 13e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier; 14e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString; 15e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Primitive; 16e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Set; 1770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.asn1.DERNull; 18e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.DERSet; 19e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.Attribute; 20e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.AttributeTable; 21e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.CMSAttributes; 22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.IssuerAndSerialNumber; 23e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignerIdentifier; 24e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignerInfo; 25e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.Time; 26e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x509.AlgorithmIdentifier; 27e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x509.DigestInfo; 28e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.cert.X509CertificateHolder; 29e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.ContentVerifier; 30e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.DigestCalculator; 31e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.OperatorCreationException; 32e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.operator.RawContentVerifier; 33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.util.Arrays; 3470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.util.io.TeeOutputStream; 35e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 36e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom/** 37e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * an expanded SignerInfo block from a CMS Signed message 38e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 39e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompublic class SignerInformation 40e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom{ 41e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private SignerId sid; 42e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private SignerInfo info; 43e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private AlgorithmIdentifier digestAlgorithm; 44e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private AlgorithmIdentifier encryptionAlgorithm; 45e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private final ASN1Set signedAttributeSet; 46e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private final ASN1Set unsignedAttributeSet; 47e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private CMSProcessable content; 48e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private byte[] signature; 49e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private ASN1ObjectIdentifier contentType; 50e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private byte[] resultDigest; 51e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 52e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // Derived 53e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private AttributeTable signedAttributeValues; 54e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private AttributeTable unsignedAttributeValues; 55e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private boolean isCounterSignature; 56e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 57e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInformation( 58e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInfo info, 59e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1ObjectIdentifier contentType, 60e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom CMSProcessable content, 61e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom byte[] resultDigest) 62e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 63e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.info = info; 64e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.contentType = contentType; 65e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.isCounterSignature = contentType == null; 66e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 67e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerIdentifier s = info.getSID(); 68e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 69e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (s.isTagged()) 70e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 71e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1OctetString octs = ASN1OctetString.getInstance(s.getId()); 72e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 73e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom sid = new SignerId(octs.getOctets()); 74e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 75e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 76e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 77e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom IssuerAndSerialNumber iAnds = IssuerAndSerialNumber.getInstance(s.getId()); 78e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 79e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom sid = new SignerId(iAnds.getName(), iAnds.getSerialNumber().getValue()); 80e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 81e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 82e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.digestAlgorithm = info.getDigestAlgorithm(); 83e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.signedAttributeSet = info.getAuthenticatedAttributes(); 84e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.unsignedAttributeSet = info.getUnauthenticatedAttributes(); 85e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.encryptionAlgorithm = info.getDigestEncryptionAlgorithm(); 86e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.signature = info.getEncryptedDigest().getOctets(); 87e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 88e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.content = content; 89e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom this.resultDigest = resultDigest; 90e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 91e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 92e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public boolean isCounterSignature() 93e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 94e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return isCounterSignature; 95e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 96e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 97e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public ASN1ObjectIdentifier getContentType() 98e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 99e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return this.contentType; 100e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 101e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 102e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private byte[] encodeObj( 103e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Encodable obj) 104e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throws IOException 105e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 106e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (obj != null) 107e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 108e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return obj.toASN1Primitive().getEncoded(); 109e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 110e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 111e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return null; 112e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 113e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 114e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public SignerId getSID() 115e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 116e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return sid; 117e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 118e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 119e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 120e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the version number for this objects underlying SignerInfo structure. 121e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 122e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public int getVersion() 123e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 124e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return info.getVersion().getValue().intValue(); 125e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 126e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 127e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AlgorithmIdentifier getDigestAlgorithmID() 128e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 129e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return digestAlgorithm; 130e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 131e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 132e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 133e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the object identifier for the signature. 134e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 135e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public String getDigestAlgOID() 136e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 13770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return digestAlgorithm.getAlgorithm().getId(); 138e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 139e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 140e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 141e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the signature parameters, or null if there aren't any. 142e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 143e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public byte[] getDigestAlgParams() 144e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 145e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom try 146e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 147e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return encodeObj(digestAlgorithm.getParameters()); 148e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 149e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (Exception e) 150e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 151e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new RuntimeException("exception getting digest parameters " + e); 152e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 153e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 154e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 155e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 156e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the content digest that was calculated during verification. 157e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 158e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public byte[] getContentDigest() 159e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 160e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (resultDigest == null) 161e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 162e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new IllegalStateException("method can only be called after verify."); 163e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 164e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 1655db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return Arrays.clone(resultDigest); 166e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 167e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 168e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 169e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the object identifier for the signature. 170e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 171e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public String getEncryptionAlgOID() 172e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 17370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return encryptionAlgorithm.getAlgorithm().getId(); 174e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 175e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 176e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 177e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the signature/encryption algorithm parameters, or null if 178e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * there aren't any. 179e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 180e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public byte[] getEncryptionAlgParams() 181e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 182e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom try 183e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 184e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return encodeObj(encryptionAlgorithm.getParameters()); 185e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 186e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (Exception e) 187e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 188e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new RuntimeException("exception getting encryption parameters " + e); 189e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 190e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 191e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 192e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 193e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return a table of the signed attributes - indexed by 194e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * the OID of the attribute. 195e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 196e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable getSignedAttributes() 197e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 198e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signedAttributeSet != null && signedAttributeValues == null) 199e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 200e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom signedAttributeValues = new AttributeTable(signedAttributeSet); 201e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 202e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 203e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return signedAttributeValues; 204e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 205e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 206e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 207e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return a table of the unsigned attributes indexed by 208e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * the OID of the attribute. 209e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 210e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public AttributeTable getUnsignedAttributes() 211e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 212e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttributeSet != null && unsignedAttributeValues == null) 213e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 214e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom unsignedAttributeValues = new AttributeTable(unsignedAttributeSet); 215e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 216e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 217e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return unsignedAttributeValues; 218e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 219e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 220e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 221e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the encoded signature 222e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 223e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public byte[] getSignature() 224e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 2255db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return Arrays.clone(signature); 226e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 227e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 228e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 229e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return a SignerInformationStore containing the counter signatures attached to this 230e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * signer. If no counter signatures are present an empty store is returned. 231e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 232e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public SignerInformationStore getCounterSignatures() 233e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 234e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // TODO There are several checks implied by the RFC3852 comments that are missing 235e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 236e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /* 237e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom The countersignature attribute MUST be an unsigned attribute; it MUST 238e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom NOT be a signed attribute, an authenticated attribute, an 239e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom unauthenticated attribute, or an unprotected attribute. 240e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 241e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable unsignedAttributeTable = getUnsignedAttributes(); 242e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttributeTable == null) 243e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 244e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return new SignerInformationStore(new ArrayList(0)); 245e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 246e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 247e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom List counterSignatures = new ArrayList(); 248e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 249e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /* 250e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom The UnsignedAttributes syntax is defined as a SET OF Attributes. The 251e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom UnsignedAttributes in a signerInfo may include multiple instances of 252e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom the countersignature attribute. 253e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 254e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector allCSAttrs = unsignedAttributeTable.getAll(CMSAttributes.counterSignature); 255e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 256e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (int i = 0; i < allCSAttrs.size(); ++i) 257e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 258e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute counterSignatureAttribute = (Attribute)allCSAttrs.get(i); 259e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 260e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /* 261e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom A countersignature attribute can have multiple attribute values. The 262e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom syntax is defined as a SET OF AttributeValue, and there MUST be one 263e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom or more instances of AttributeValue present. 264e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 265e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Set values = counterSignatureAttribute.getAttrValues(); 266e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (values.size() < 1) 267e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 268e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // TODO Throw an appropriate exception? 269e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 270e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 271e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (Enumeration en = values.getObjects(); en.hasMoreElements();) 272e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 273e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /* 274e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Countersignature values have the same meaning as SignerInfo values 275e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for ordinary signatures, except that: 276e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 277e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 1. The signedAttributes field MUST NOT contain a content-type 278e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom attribute; there is no content type for countersignatures. 279e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 280e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 2. The signedAttributes field MUST contain a message-digest 281e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom attribute if it contains any other attributes. 282e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 283e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 3. The input to the message-digesting process is the contents 284e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom octets of the DER encoding of the signatureValue field of the 285e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInfo value with which the attribute is associated. 286e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 287e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInfo si = SignerInfo.getInstance(en.nextElement()); 288e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 289e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom counterSignatures.add(new SignerInformation(si, null, new CMSProcessableByteArray(getSignature()), null)); 290e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 291e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 292e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 293e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return new SignerInformationStore(counterSignatures); 294e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 295e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 296e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 297e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * return the DER encoding of the signed attributes. 298e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @throws IOException if an encoding error occurs. 299e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 300e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public byte[] getEncodedSignedAttributes() 301e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throws IOException 302e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 303e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signedAttributeSet != null) 304e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 305e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return signedAttributeSet.getEncoded(); 306e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 307e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 308e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return null; 309e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 310e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 311e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private boolean doVerify( 312e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInformationVerifier verifier) 313e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throws CMSException 314e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 315e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom String encName = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID()); 31670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom ContentVerifier contentVerifier; 317e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 318e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom try 319e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 32070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom contentVerifier = verifier.getContentVerifier(encryptionAlgorithm, info.getDigestAlgorithm()); 32170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 32270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom catch (OperatorCreationException e) 32370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 32470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new CMSException("can't create content verifier: " + e.getMessage(), e); 32570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 32670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 32770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom try 32870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 32970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom OutputStream sigOut = contentVerifier.getOutputStream(); 33070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 331e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (resultDigest == null) 332e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 333e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom DigestCalculator calc = verifier.getDigestCalculator(this.getDigestAlgorithmID()); 334e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (content != null) 335e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 336e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom OutputStream digOut = calc.getOutputStream(); 337e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 33870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (signedAttributeSet == null) 33970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 34070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (contentVerifier instanceof RawContentVerifier) 34170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 34270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom content.write(digOut); 34370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 34470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 34570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 34670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom OutputStream cOut = new TeeOutputStream(digOut, sigOut); 34770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 34870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom content.write(cOut); 34970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 35070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom cOut.close(); 35170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 35270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 35370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 35470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 35570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom content.write(digOut); 35670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom sigOut.write(this.getEncodedSignedAttributes()); 35770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 358e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 359e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom digOut.close(); 360e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 36170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else if (signedAttributeSet != null) 36270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 36370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom sigOut.write(this.getEncodedSignedAttributes()); 36470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 36570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 366e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 367e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // TODO Get rid of this exception and just treat content==null as empty not missing? 368e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("data not encapsulated in signature - use detached constructor."); 369e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 370e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 371e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom resultDigest = calc.getDigest(); 372e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 37370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 37470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 37570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (signedAttributeSet == null) 37670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 37770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (content != null) 37870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 37970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom content.write(sigOut); 38070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 38170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 38270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 38370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 38470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom sigOut.write(this.getEncodedSignedAttributes()); 38570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 38670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 38770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 38870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom sigOut.close(); 389e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 390e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (IOException e) 391e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 392e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("can't process mime object to create signature.", e); 393e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 394e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (OperatorCreationException e) 395e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 396e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("can't create digest calculator: " + e.getMessage(), e); 397e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 398e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 399e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // RFC 3852 11.1 Check the content-type attribute is correct 400e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 401e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Primitive validContentType = getSingleValuedSignedAttribute( 402e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom CMSAttributes.contentType, "content-type"); 403e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (validContentType == null) 404e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 405e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (!isCounterSignature && signedAttributeSet != null) 406e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 407e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); 408e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 409e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 410e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 411e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 412e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (isCounterSignature) 413e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 414e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); 415e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 416e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 41770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (!(validContentType instanceof ASN1ObjectIdentifier)) 418e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 419e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); 420e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 421e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 42270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom ASN1ObjectIdentifier signedContentType = (ASN1ObjectIdentifier)validContentType; 423e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 424e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (!signedContentType.equals(contentType)) 425e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 426e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("content-type attribute value does not match eContentType"); 427e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 428e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 429e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 430e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 431e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // RFC 3852 11.2 Check the message-digest attribute is correct 432e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 433e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Primitive validMessageDigest = getSingleValuedSignedAttribute( 434e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom CMSAttributes.messageDigest, "message-digest"); 435e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (validMessageDigest == null) 436e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 437e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signedAttributeSet != null) 438e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 439e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("the message-digest signed attribute type MUST be present when there are any signed attributes present"); 440e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 441e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 442e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 443e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 444e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (!(validMessageDigest instanceof ASN1OctetString)) 445e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 446e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); 447e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 448e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 449e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1OctetString signedMessageDigest = (ASN1OctetString)validMessageDigest; 450e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 451e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (!Arrays.constantTimeAreEqual(resultDigest, signedMessageDigest.getOctets())) 452e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 453e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSSignerDigestMismatchException("message-digest attribute value does not match calculated value"); 454e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 455e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 456e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 457e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 458e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // RFC 3852 11.4 Validate countersignature attribute(s) 459e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 460e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable signedAttrTable = this.getSignedAttributes(); 461e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signedAttrTable != null 462e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom && signedAttrTable.getAll(CMSAttributes.counterSignature).size() > 0) 463e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 464e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("A countersignature attribute MUST NOT be a signed attribute"); 465e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 466e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 467e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); 468e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttrTable != null) 469e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 470e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector csAttrs = unsignedAttrTable.getAll(CMSAttributes.counterSignature); 471e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (int i = 0; i < csAttrs.size(); ++i) 472e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 473e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute csAttr = (Attribute)csAttrs.get(i); 474e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (csAttr.getAttrValues().size() < 1) 475e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 476e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("A countersignature attribute MUST contain at least one AttributeValue"); 477e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 478e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 479e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // Note: We don't recursively validate the countersignature value 480e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 481e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 482e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 483e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 484e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom try 485e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 48670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (signedAttributeSet == null && resultDigest != null) 487e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 48870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (contentVerifier instanceof RawContentVerifier) 489e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 49070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom RawContentVerifier rawVerifier = (RawContentVerifier)contentVerifier; 491e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 49270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (encName.equals("RSA")) 49370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 49470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithm.getAlgorithm(), DERNull.INSTANCE), resultDigest); 495e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 49670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return rawVerifier.verify(digInfo.getEncoded(ASN1Encoding.DER), this.getSignature()); 497e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 498e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 49970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return rawVerifier.verify(resultDigest, this.getSignature()); 500e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 501e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 502e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 503e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return contentVerifier.verify(this.getSignature()); 504e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 505e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (IOException e) 506e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 507e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("can't process mime object to create signature.", e); 508e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 509e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 510e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 511e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 512e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Verify that the given verifier can successfully verify the signature on 513e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * this SignerInformation object. 514e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 515e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param verifier a suitably configured SignerInformationVerifier. 516e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return true if the signer information is verified, false otherwise. 517e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @throws org.bouncycastle.cms.CMSVerifierCertificateNotValidException if the provider has an associated certificate and the certificate is not valid at the time given as the SignerInfo's signing time. 518e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @throws org.bouncycastle.cms.CMSException if the verifier is unable to create a ContentVerifiers or DigestCalculators. 519e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 520e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public boolean verify(SignerInformationVerifier verifier) 521e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throws CMSException 522e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 523e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Time signingTime = getSigningTime(); // has to be validated if present. 524e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 525e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (verifier.hasAssociatedCertificate()) 526e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 527e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signingTime != null) 528e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 529e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom X509CertificateHolder dcv = verifier.getAssociatedCertificate(); 530e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 531e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (!dcv.isValidOn(signingTime.getDate())) 532e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 533e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSVerifierCertificateNotValidException("verifier not valid at signingTime"); 534e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 535e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 536e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 537e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 538e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return doVerify(verifier); 539e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 540e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 541e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 542e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return the underlying ASN.1 object defining this SignerInformation object. 543e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 544e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return a SignerInfo. 545e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 546e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public SignerInfo toASN1Structure() 547e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 548e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return info; 549e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 550e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 551e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private ASN1Primitive getSingleValuedSignedAttribute( 552e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1ObjectIdentifier attrOID, String printableName) 553e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throws CMSException 554e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 555e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable unsignedAttrTable = this.getUnsignedAttributes(); 556e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttrTable != null 557e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom && unsignedAttrTable.getAll(attrOID).size() > 0) 558e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 559e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("The " + printableName 560e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom + " attribute MUST NOT be an unsigned attribute"); 561e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 562e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 563e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable signedAttrTable = this.getSignedAttributes(); 564e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (signedAttrTable == null) 565e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 566e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return null; 567e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 568e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 569e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector v = signedAttrTable.getAll(attrOID); 570e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom switch (v.size()) 571e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 572e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom case 0: 573e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return null; 574e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom case 1: 575e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 576e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom Attribute t = (Attribute)v.get(0); 577e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Set attrValues = t.getAttrValues(); 578e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (attrValues.size() != 1) 579e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 580e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("A " + printableName 581e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom + " attribute MUST have a single attribute value"); 582e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 583e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 584e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return attrValues.getObjectAt(0).toASN1Primitive(); 585e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 586e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom default: 587e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the " 588e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom + printableName + " attribute"); 589e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 590e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 591e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 592e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom private Time getSigningTime() throws CMSException 593e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 594e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Primitive validSigningTime = getSingleValuedSignedAttribute( 595e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom CMSAttributes.signingTime, "signing-time"); 596e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 597e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (validSigningTime == null) 598e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 599e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return null; 600e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 601e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 602e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom try 603e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 604e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return Time.getInstance(validSigningTime); 605e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 606e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom catch (IllegalArgumentException e) 607e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 608e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom throw new CMSException("signing-time attribute value not a valid 'Time' structure"); 609e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 610e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 611e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 612e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 613e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return a signer information object with the passed in unsigned 614e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * attributes replacing the ones that are current associated with 615e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * the object passed in. 616e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 617e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param signerInformation the signerInfo to be used as the basis. 618e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param unsignedAttributes the unsigned attributes to add. 619e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return a copy of the original SignerInformationObject with the changed attributes. 620e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 621e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public static SignerInformation replaceUnsignedAttributes( 622e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInformation signerInformation, 623e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable unsignedAttributes) 624e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 625e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInfo sInfo = signerInformation.info; 626e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1Set unsignedAttr = null; 627e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 628e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttributes != null) 629e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 630e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom unsignedAttr = new DERSet(unsignedAttributes.toASN1EncodableVector()); 631e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 632e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 633e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return new SignerInformation( 634e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(), 635e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), unsignedAttr), 636e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom signerInformation.contentType, signerInformation.content, null); 637e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 638e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 639e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom /** 640e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * Return a signer information object with passed in SignerInformationStore representing counter 641e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * signatures attached as an unsigned attribute. 642e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * 643e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param signerInformation the signerInfo to be used as the basis. 644e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @param counterSigners signer info objects carrying counter signature. 645e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * @return a copy of the original SignerInformationObject with the changed attributes. 646e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */ 647e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom public static SignerInformation addCounterSigners( 648e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInformation signerInformation, 649e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInformationStore counterSigners) 650e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 651e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom // TODO Perform checks from RFC 3852 11.4 652e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 653e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom SignerInfo sInfo = signerInformation.info; 654e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom AttributeTable unsignedAttr = signerInformation.getUnsignedAttributes(); 655e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector v; 656e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 657e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom if (unsignedAttr != null) 658e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 659e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v = unsignedAttr.toASN1EncodableVector(); 660e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 661e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom else 662e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 663e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v = new ASN1EncodableVector(); 664e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 665e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 666e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom ASN1EncodableVector sigs = new ASN1EncodableVector(); 667e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 668e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom for (Iterator it = counterSigners.getSigners().iterator(); it.hasNext();) 669e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom { 67070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom sigs.add(((SignerInformation)it.next()).toASN1Structure()); 671e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 672e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 673e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom v.add(new Attribute(CMSAttributes.counterSignature, new DERSet(sigs))); 674e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom 675e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom return new SignerInformation( 676e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(), 677e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), new DERSet(v)), 678e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom signerInformation.contentType, signerInformation.content, null); 679e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom } 680e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom} 681