private CmsEnvelopedData doGenerate( ICmsTypedData content, ICipherBuilderWithKey<AlgorithmIdentifier> contentEncryptor) { Asn1EncodableVector recipientInfos = new Asn1EncodableVector(); AlgorithmIdentifier encAlgId; Asn1OctetString encContent; MemoryOutputStream bOut = new MemoryOutputStream(); try { ICipher cOut = contentEncryptor.BuildCipher(bOut); content.Write(cOut.Stream); cOut.Stream.Close(); } catch (IOException e) { throw new CmsException(e.Message, e); } byte[] encryptedContent = bOut.ToArray(); encAlgId = contentEncryptor.AlgorithmDetails; encContent = new BerOctetString(encryptedContent); ISymmetricKey encKey = contentEncryptor.Key; for (IEnumerator<IRecipientInfoGenerator> it = recipientInfoGenerators.GetEnumerator(); it.MoveNext();) { IRecipientInfoGenerator recipient = (IRecipientInfoGenerator)it.Current; recipientInfos.Add(recipient.Generate(encKey)); } EncryptedContentInfo eci = new EncryptedContentInfo( content.ContentType, encAlgId, encContent); Asn1Set unprotectedAttrSet = null; if (unprotectedAttributeGenerator != null) { Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(new Dictionary<string, object>()); unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector()); } ContentInfo contentInfo = new ContentInfo( CmsObjectIdentifiers.EnvelopedData, new EnvelopedData(originatorInfo, new DerSet(recipientInfos), eci, unprotectedAttrSet)); return new CmsEnvelopedData(contentInfo); }
private CmsEncryptedData doGenerate( ICmsTypedData content, ICipherBuilder <AlgorithmIdentifier> contentEncryptor) { AlgorithmIdentifier encAlgId; Asn1OctetString encContent; MemoryOutputStream bOut = new MemoryOutputStream(); try { ICipher cipher = contentEncryptor.BuildCipher(bOut); content.Write(cipher.Stream); cipher.Stream.Close(); } catch (IOException) { throw new CmsException(""); } byte[] encryptedContent = bOut.ToArray(); encAlgId = contentEncryptor.AlgorithmDetails; encContent = new BerOctetString(encryptedContent); EncryptedContentInfo eci = new EncryptedContentInfo( content.ContentType, encAlgId, encContent); Asn1Set unprotectedAttrSet = null; if (unprotectedAttributeGenerator != null) { Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(new Dictionary <string, object>()); unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector()); } ContentInfo contentInfo = new ContentInfo( CmsObjectIdentifiers.EncryptedData, new EncryptedData(eci, unprotectedAttrSet)); return(new CmsEncryptedData(contentInfo)); }
private bool doVerify(bool isRawVerifier, IVerifierFactory <AlgorithmIdentifier> verifierFactory, IDigestFactory <AlgorithmIdentifier> digestFactory) { IStreamCalculator <IVerifier> contentVerifier = verifierFactory.CreateCalculator(); Stream sigOut = contentVerifier.Stream; try { if (resultDigest == null) { IStreamCalculator <IBlockResult> calc = digestFactory.CreateCalculator(); if (content != null) { Stream digOut = calc.Stream; if (signedAttributeSet == null) { if (isRawVerifier) { content.Write(digOut); } else { Stream cOut = new TeeOutputStream(digOut, sigOut); content.Write(cOut); cOut.Close(); } } else { content.Write(digOut); byte[] enc = this.GetEncodedSignedAttributes(); sigOut.Write(enc, 0, enc.Length); } digOut.Close(); } else if (signedAttributeSet != null) { byte[] enc = this.GetEncodedSignedAttributes(); sigOut.Write(enc, 0, enc.Length); } else { // TODO Get rid of this exception and just treat content==null as empty not missing? throw new CmsException("data not encapsulated in signature - use detached constructor."); } resultDigest = calc.GetResult().Collect(); } else { if (signedAttributeSet == null) { if (content != null) { content.Write(sigOut); } } else { byte[] enc = this.GetEncodedSignedAttributes(); sigOut.Write(enc, 0, enc.Length); } } sigOut.Close(); } catch (Exception e) { throw new CmsException("can't process object to create signature.", e); } // RFC 3852 11.1 Check the content-type attribute is correct { Asn1Object validContentType = GetSingleValuedSignedAttribute( CmsAttributes.ContentType, "content-type"); if (validContentType == null) { if (!isCounterSignature && signedAttributeSet != null) { throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data"); } } else { if (isCounterSignature) { throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute"); } if (!(validContentType is DerObjectIdentifier)) { throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'"); } DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType; if (!signedContentType.Equals(contentType)) { throw new CmsException("content-type attribute value does not match eContentType"); } } } Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes; // RFC 6211 Validate Algorithm Identifier protection attribute if present { Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes; if (unsignedAttrTable != null && unsignedAttrTable.GetAll(CmsAttributes.CmsAlgorithmProtect).Count > 0) { throw new CmsException("A cmsAlgorithmProtect attribute MUST be a signed attribute"); } if (signedAttrTable != null) { Asn1EncodableVector protectionAttributes = signedAttrTable.GetAll(CmsAttributes.CmsAlgorithmProtect); if (protectionAttributes.Count > 1) { throw new CmsException("Only one instance of a cmsAlgorithmProtect attribute can be present"); } if (protectionAttributes.Count > 0) { Asn1.Cms.Attribute attr = Asn1.Cms.Attribute.GetInstance(protectionAttributes[0]); if (attr.AttrValues.Count != 1) { throw new CmsException("A cmsAlgorithmProtect attribute MUST contain exactly one value"); } CmsAlgorithmProtection algorithmProtection = CmsAlgorithmProtection.GetInstance(attr.AttrValues[0]); if (!CmsUtilities.IsEquivalent(algorithmProtection.DigestAlgorithm, info.DigestAlgorithm)) { throw new CmsException("CMS Algorithm Identifier Protection check failed for digestAlgorithm"); } if (!CmsUtilities.IsEquivalent(algorithmProtection.SignatureAlgorithm, info.DigestEncryptionAlgorithm)) { throw new CmsException("CMS Algorithm Identifier Protection check failed for signatureAlgorithm"); } } } } // RFC 3852 11.2 Check the message-digest attribute is correct { Asn1Encodable validMessageDigest = GetSingleValuedSignedAttribute( CmsAttributes.MessageDigest, "message-digest"); if (validMessageDigest == null) { if (signedAttributeSet != null) { throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present"); } } else { if (!(validMessageDigest is Asn1OctetString)) { throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'"); } Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest; if (!Arrays.ConstantTimeAreEqual(resultDigest, signedMessageDigest.GetOctets())) { throw new CmsSignerDigestMismatchException("message-digest attribute value does not match calculated value"); } } } // RFC 3852 11.4 Validate countersignature attribute(s) { if (signedAttrTable != null && signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0) { throw new CmsException("A countersignature attribute MUST NOT be a signed attribute"); } Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes; if (unsignedAttrTable != null) { Asn1EncodableVector csAttrs = unsignedAttrTable.GetAll(CmsAttributes.CounterSignature); for (int i = 0; i < csAttrs.Count; ++i) { Asn1.Cms.Attribute csAttr = Asn1.Cms.Attribute.GetInstance(csAttrs[i]); if (csAttr.AttrValues.Count < 1) { throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue"); } // Note: We don't recursively validate the countersignature value } } } try { if (signedAttributeSet == null && resultDigest != null) { if (isRawVerifier) { if (SignatureAlgorithmID.Algorithm.Equals(PkcsObjectIdentifiers.RsaEncryption)) { DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(digestAlgorithm.Algorithm, DerNull.Instance), resultDigest); byte[] data = digInfo.GetEncoded(Asn1Encodable.Der); sigOut.Write(data, 0, data.Length); sigOut.Close(); return(contentVerifier.GetResult().IsVerified(this.GetSignature())); } sigOut.Write(resultDigest, 0, resultDigest.Length); sigOut.Close(); return(contentVerifier.GetResult().IsVerified(this.GetSignature())); } } sigOut.Close(); return(contentVerifier.GetResult().IsVerified(this.GetSignature())); } catch (IOException e) { throw new CmsException("can't process mime object to create signature.", e); } }
/** * generate a signed object that for a CMS Signed Data * object - if encapsulate is true a copy * of the message will be included in the signature. The content type * is set according to the OID represented by the string signedContentType. */ public CmsSignedData Generate( // FIXME Avoid accessing more than once to support CmsProcessableInputStream ICmsTypedData content, bool encapsulate) { // TODO // if (signerInfs.isEmpty()) // { // /* RFC 3852 5.2 // * "In the degenerate case where there are no signers, the // * EncapsulatedContentInfo value being "signed" is irrelevant. In this // * case, the content type within the EncapsulatedContentInfo value being // * "signed" MUST be id-data (as defined in section 4), and the content // * field of the EncapsulatedContentInfo value MUST be omitted." // */ // if (encapsulate) // { // throw new IllegalArgumentException("no signers, encapsulate must be false"); // } // if (!DATA.equals(eContentType)) // { // throw new IllegalArgumentException("no signers, eContentType must be id-data"); // } // } // // if (!DATA.equals(eContentType)) // { // /* RFC 3852 5.3 // * [The 'signedAttrs']... // * field is optional, but it MUST be present if the content type of // * the EncapsulatedContentInfo value being signed is not id-data. // */ // // TODO signedAttrs must be present for all signers // } Asn1EncodableVector digestAlgs = new Asn1EncodableVector(); Asn1EncodableVector signerInfos = new Asn1EncodableVector(); _digests.Clear(); // clear the current preserved digest state // // add the precalculated SignerInfo objects. // for (IEnumerator it = _signers.GetEnumerator(); it.MoveNext();) { SignerInformation signer = (SignerInformation)it.Current; digestAlgs.Add(CmsUtilities.fixAlgID(signer.DigestAlgorithmID)); // TODO Verify the content type and calculated digest match the precalculated SignerInfo signerInfos.Add(signer.ToAsn1Structure()); } // // add the SignerInfo objects // DerObjectIdentifier contentTypeOID = content.ContentType; Asn1OctetString octs = null; if (content.GetContent() != null) { MemoryOutputStream bOut = null; if (encapsulate) { bOut = new MemoryOutputStream(); } Stream cOut = CmsUtilities.attachSignersToOutputStream(_signerGens, bOut); // Just in case it's unencapsulated and there are no signers! cOut = CmsUtilities.getSafeOutputStream(cOut); try { content.Write(cOut); cOut.Close(); } catch (IOException e) { throw new CmsException("data processing exception: " + e.Message, e); } if (encapsulate) { octs = new BerOctetString(bOut.ToArray()); } } for (IEnumerator it = _signerGens.GetEnumerator(); it.MoveNext();) { SignerInfoGenerator sGen = (SignerInfoGenerator)it.Current; SignerInfo inf = sGen.Generate(contentTypeOID); digestAlgs.Add(inf.DigestAlgorithm); signerInfos.Add(inf); byte[] calcDigest = sGen.getCalculatedDigest(); if (calcDigest != null) { _digests.Add(inf.DigestAlgorithm.Algorithm.Id, calcDigest); } } Asn1Set certificates = null; if (_certs.Count != 0) { certificates = CmsUtilities.CreateBerSetFromList(_certs); } Asn1Set certrevlist = null; if (_crls.Count != 0) { certrevlist = CmsUtilities.CreateBerSetFromList(_crls); } ContentInfo encInfo = new ContentInfo(contentTypeOID, octs); SignedData sd = new SignedData( new DerSet(digestAlgs), encInfo, certificates, certrevlist, new DerSet(signerInfos)); ContentInfo contentInfo = new ContentInfo( CmsObjectIdentifiers.SignedData, sd); return(new CmsSignedData(content, contentInfo)); }