Methods Summary |
---|
public static org.bouncycastle.cms.SignerInformation | addCounterSigners(org.bouncycastle.cms.SignerInformation signerInformation, SignerInformationStore counterSigners)Return a signer information object with passed in SignerInformationStore representing counter
signatures attached as an unsigned attribute.
SignerInfo sInfo = signerInformation.info;
AttributeTable unsignedAttr = signerInformation.getUnsignedAttributes();
ASN1EncodableVector v;
if (unsignedAttr != null)
{
v = unsignedAttr.toASN1EncodableVector();
}
else
{
v = new ASN1EncodableVector();
}
ASN1EncodableVector sigs = new ASN1EncodableVector();
for (Iterator it = counterSigners.getSigners().iterator(); it.hasNext();)
{
sigs.add(((SignerInformation)it.next()).toSignerInfo());
}
v.add(new Attribute(CMSAttributes.counterSignature, new DERSet(sigs)));
return new SignerInformation(
new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(),
sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), new DERSet(v)),
signerInformation.contentType, signerInformation.content, null);
|
private org.bouncycastle.asn1.x509.DigestInfo | derDecode(byte[] encoding)
if (encoding[0] != (DERTags.CONSTRUCTED | DERTags.SEQUENCE))
{
throw new IOException("not a digest info object");
}
ASN1InputStream aIn = new ASN1InputStream(encoding);
DigestInfo digInfo = new DigestInfo((ASN1Sequence)aIn.readObject());
// length check to avoid Bleichenbacher vulnerability
if (digInfo.getEncoded().length != encoding.length)
{
throw new CMSException("malformed RSA signature");
}
return digInfo;
|
private boolean | doVerify(java.security.PublicKey key, org.bouncycastle.asn1.cms.AttributeTable signedAttrTable, java.security.Provider sigProvider)
String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(this.getDigestAlgOID());
String signatureName = digestName + "with" + CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID());
Signature sig = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, sigProvider);
MessageDigest digest = CMSSignedHelper.INSTANCE.getDigestInstance(digestName, sigProvider);
// TODO [BJA-109] Note: PSSParameterSpec requires JDK1.4+
/*
try
{
DERObjectIdentifier sigAlgOID = encryptionAlgorithm.getObjectId();
DEREncodable sigParams = this.encryptionAlgorithm.getParameters();
if (sigAlgOID.equals(PKCSObjectIdentifiers.id_RSASSA_PSS))
{
// RFC 4056
// When the id-RSASSA-PSS algorithm identifier is used for a signature,
// the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
if (sigParams == null)
{
throw new CMSException(
"RSASSA-PSS signature must specify algorithm parameters");
}
AlgorithmParameters params = AlgorithmParameters.getInstance(
sigAlgOID.getId(), sig.getProvider().getName());
params.init(sigParams.getDERObject().getEncoded(), "ASN.1");
PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class);
sig.setParameter(spec);
}
else
{
// TODO Are there other signature algorithms that provide parameters?
if (sigParams != null)
{
throw new CMSException("unrecognised signature parameters provided");
}
}
}
catch (IOException e)
{
throw new CMSException("error encoding signature parameters.", e);
}
catch (InvalidAlgorithmParameterException e)
{
throw new CMSException("error setting signature parameters.", e);
}
catch (InvalidParameterSpecException e)
{
throw new CMSException("error processing signature parameters.", e);
}
*/
try
{
sig.initVerify(key);
if (signedAttributes == null)
{
if (content != null)
{
content.write(
new CMSSignedDataGenerator.SigOutputStream(sig));
content.write(
new CMSSignedDataGenerator.DigOutputStream(digest));
resultDigest = digest.digest();
}
else
{
resultDigest = digestCalculator.getDigest();
// need to decrypt signature and check message bytes
return verifyDigest(resultDigest, key, this.getSignature(), sigProvider);
}
}
else
{
byte[] hash;
if (content != null)
{
content.write(
new CMSSignedDataGenerator.DigOutputStream(digest));
hash = digest.digest();
}
else if (digestCalculator != null)
{
hash = digestCalculator.getDigest();
}
else
{
hash = null;
}
resultDigest = hash;
Attribute dig = signedAttrTable.get(
CMSAttributes.messageDigest);
Attribute type = signedAttrTable.get(
CMSAttributes.contentType);
if (dig == null)
{
throw new SignatureException("no hash for content found in signed attributes");
}
if (type == null && !contentType.equals(CMSAttributes.counterSignature))
{
throw new SignatureException("no content type id found in signed attributes");
}
DERObject hashObj = dig.getAttrValues().getObjectAt(0).getDERObject();
if (hashObj instanceof ASN1OctetString)
{
byte[] signedHash = ((ASN1OctetString)hashObj).getOctets();
if (!MessageDigest.isEqual(hash, signedHash))
{
throw new SignatureException("content hash found in signed attributes different");
}
}
else if (hashObj instanceof DERNull)
{
if (hash != null)
{
throw new SignatureException("NULL hash found in signed attributes when one expected");
}
}
if (type != null)
{
DERObjectIdentifier typeOID = (DERObjectIdentifier)type.getAttrValues().getObjectAt(0);
if (!typeOID.equals(contentType))
{
throw new SignatureException("contentType in signed attributes different");
}
}
sig.update(this.getEncodedSignedAttributes());
}
return sig.verify(this.getSignature());
}
catch (InvalidKeyException e)
{
throw new CMSException(
"key not appropriate to signature in message.", e);
}
catch (IOException e)
{
throw new CMSException(
"can't process mime object to create signature.", e);
}
catch (SignatureException e)
{
throw new CMSException(
"invalid signature format in message: " + e.getMessage(), e);
}
|
private byte[] | encodeObj(org.bouncycastle.asn1.DEREncodable obj)
if (obj != null)
{
return obj.getDERObject().getEncoded();
}
return null;
|
public byte[] | getContentDigest()return the content digest that was calculated during verification.
if (resultDigest == null)
{
throw new IllegalStateException("method can only be called after verify.");
}
return (byte[])resultDigest.clone();
|
public SignerInformationStore | getCounterSignatures()Return a SignerInformationStore containing the counter signatures attached to this
signer. If no counter signatures are present an empty store is returned.
AttributeTable unsignedAttributeTable = getUnsignedAttributes();
if (unsignedAttributeTable == null)
{
return new SignerInformationStore(new ArrayList(0));
}
List counterSignatures = new ArrayList();
Attribute counterSignatureAttribute = unsignedAttributeTable.get(CMSAttributes.counterSignature);
if (counterSignatureAttribute != null)
{
ASN1Set values = counterSignatureAttribute.getAttrValues();
counterSignatures = new ArrayList(values.size());
for (Enumeration en = values.getObjects(); en.hasMoreElements();)
{
SignerInfo si = SignerInfo.getInstance(en.nextElement());
String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(si.getDigestAlgorithm().getObjectId().getId());
counterSignatures.add(new SignerInformation(si, CMSAttributes.counterSignature, null, new CounterSignatureDigestCalculator(digestName, null, getSignature())));
}
}
return new SignerInformationStore(counterSignatures);
|
public java.lang.String | getDigestAlgOID()return the object identifier for the signature.
return digestAlgorithm.getObjectId().getId();
|
public byte[] | getDigestAlgParams()return the signature parameters, or null if there aren't any.
try
{
return encodeObj(digestAlgorithm.getParameters());
}
catch (Exception e)
{
throw new RuntimeException("exception getting digest parameters " + e);
}
|
public byte[] | getEncodedSignedAttributes()return the DER encoding of the signed attributes.
if (signedAttributes != null)
{
return signedAttributes.getEncoded(ASN1Encodable.DER);
}
return null;
|
public java.lang.String | getEncryptionAlgOID()return the object identifier for the signature.
return encryptionAlgorithm.getObjectId().getId();
|
public byte[] | getEncryptionAlgParams()return the signature/encryption algorithm parameters, or null if
there aren't any.
try
{
return encodeObj(encryptionAlgorithm.getParameters());
}
catch (Exception e)
{
throw new RuntimeException("exception getting encryption parameters " + e);
}
|
public SignerId | getSID()
return sid;
|
public byte[] | getSignature()return the encoded signature
return (byte[])signature.clone();
|
public org.bouncycastle.asn1.cms.AttributeTable | getSignedAttributes()return a table of the signed attributes - indexed by
the OID of the attribute.
if (signedAttributes == null)
{
return null;
}
return new AttributeTable(signedAttributes);
|
public org.bouncycastle.asn1.cms.AttributeTable | getUnsignedAttributes()return a table of the unsigned attributes indexed by
the OID of the attribute.
if (unsignedAttributes == null)
{
return null;
}
return new AttributeTable(unsignedAttributes);
|
public int | getVersion()return the version number for this objects underlying SignerInfo structure.
return info.getVersion().getValue().intValue();
|
private boolean | isNull(org.bouncycastle.asn1.DEREncodable o)
return (o instanceof ASN1Null) || (o == null);
|
public static org.bouncycastle.cms.SignerInformation | replaceUnsignedAttributes(org.bouncycastle.cms.SignerInformation signerInformation, org.bouncycastle.asn1.cms.AttributeTable unsignedAttributes)Return a signer information object with the passed in unsigned
attributes replacing the ones that are current associated with
the object passed in.
SignerInfo sInfo = signerInformation.info;
ASN1Set unsignedAttr = null;
if (unsignedAttributes != null)
{
unsignedAttr = new DERSet(unsignedAttributes.toASN1EncodableVector());
}
return new SignerInformation(
new SignerInfo(sInfo.getSID(), sInfo.getDigestAlgorithm(),
sInfo.getAuthenticatedAttributes(), sInfo.getDigestEncryptionAlgorithm(), sInfo.getEncryptedDigest(), unsignedAttr),
signerInformation.contentType, signerInformation.content, null);
|
public org.bouncycastle.asn1.cms.SignerInfo | toSignerInfo()Return the base ASN.1 CMS structure that this object contains.
return info;
|
public boolean | verify(java.security.PublicKey key, java.lang.String sigProvider)verify that the given public key succesfully handles and confirms the
signature associated with this signer.
return doVerify(key, this.getSignedAttributes(), CMSUtils.getProvider(sigProvider));
|
public boolean | verify(java.security.PublicKey key, java.security.Provider sigProvider)verify that the given public key succesfully handles and confirms the
signature associated with this signer.
return doVerify(key, this.getSignedAttributes(), sigProvider);
|
public boolean | verify(java.security.cert.X509Certificate cert, java.lang.String sigProvider)verify that the given certificate successfully handles and confirms
the signature associated with this signer and, if a signingTime
attribute is available, that the certificate was valid at the time the
signature was generated.
return verify(cert, CMSUtils.getProvider(sigProvider));
|
public boolean | verify(java.security.cert.X509Certificate cert, java.security.Provider sigProvider)verify that the given certificate successfully handles and confirms
the signature associated with this signer and, if a signingTime
attribute is available, that the certificate was valid at the time the
signature was generated.
AttributeTable attr = this.getSignedAttributes();
if (attr != null)
{
ASN1EncodableVector v = attr.getAll(CMSAttributes.signingTime);
switch (v.size())
{
case 0:
break;
case 1:
{
Attribute t = (Attribute)v.get(0);
// assert t != null;
ASN1Set attrValues = t.getAttrValues();
if (attrValues.size() != 1)
{
throw new CMSException("A signing-time attribute MUST have a single attribute value");
}
Time time = Time.getInstance(attrValues.getObjectAt(0).getDERObject());
cert.checkValidity(time.getDate());
break;
}
default:
throw new CMSException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the signing-time attribute");
}
}
return doVerify(cert.getPublicKey(), attr, sigProvider);
|
private boolean | verifyDigest(byte[] digest, java.security.PublicKey key, byte[] signature, java.security.Provider sigProvider)
String algorithm = CMSSignedHelper.INSTANCE.getEncryptionAlgName(this.getEncryptionAlgOID());
try
{
if (algorithm.equals("RSA"))
{
Cipher c;
if (sigProvider != null)
{
c = Cipher.getInstance("RSA/ECB/PKCS1Padding", sigProvider);
}
else
{
c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
}
c.init(Cipher.DECRYPT_MODE, key);
DigestInfo digInfo = derDecode(c.doFinal(signature));
if (!digInfo.getAlgorithmId().getObjectId().equals(digestAlgorithm.getObjectId()))
{
return false;
}
if (!isNull(digInfo.getAlgorithmId().getParameters()))
{
return false;
}
byte[] sigHash = digInfo.getDigest();
return MessageDigest.isEqual(digest, sigHash);
}
else if (algorithm.equals("DSA"))
{
Signature sig;
if (sigProvider != null)
{
sig = Signature.getInstance("NONEwithDSA", sigProvider);
}
else
{
sig = Signature.getInstance("NONEwithDSA");
}
sig.initVerify(key);
sig.update(digest);
return sig.verify(signature);
}
else
{
throw new CMSException("algorithm: " + algorithm + " not supported in base signatures.");
}
}
catch (GeneralSecurityException e)
{
throw new CMSException("Exception processing signature: " + e, e);
}
catch (IOException e)
{
throw new CMSException("Exception decoding signature: " + e, e);
}
|