예제 #1
0
        protected Stream Open(Stream outStr, AlgorithmIdentifier macAlgId, ICipherParameters cipherParameters, Asn1EncodableVector recipientInfos)
        {
            Stream result;

            try
            {
                BerSequenceGenerator berSequenceGenerator = new BerSequenceGenerator(outStr);
                berSequenceGenerator.AddObject(CmsObjectIdentifiers.AuthenticatedData);
                BerSequenceGenerator berSequenceGenerator2 = new BerSequenceGenerator(berSequenceGenerator.GetRawOutputStream(), 0, true);
                berSequenceGenerator2.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));
                Stream        rawOutputStream = berSequenceGenerator2.GetRawOutputStream();
                Asn1Generator asn1Generator   = this._berEncodeRecipientSet ? new BerSetGenerator(rawOutputStream) : new DerSetGenerator(rawOutputStream);
                foreach (Asn1Encodable obj in recipientInfos)
                {
                    asn1Generator.AddObject(obj);
                }
                asn1Generator.Close();
                berSequenceGenerator2.AddObject(macAlgId);
                BerSequenceGenerator berSequenceGenerator3 = new BerSequenceGenerator(rawOutputStream);
                berSequenceGenerator3.AddObject(CmsObjectIdentifiers.Data);
                Stream output = CmsUtilities.CreateBerOctetOutputStream(berSequenceGenerator3.GetRawOutputStream(), 0, false, this._bufferSize);
                IMac   mac    = MacUtilities.GetMac(macAlgId.ObjectID);
                mac.Init(cipherParameters);
                Stream macStream = new TeeOutputStream(output, new MacOutputStream(mac));
                result = new CmsAuthenticatedDataStreamGenerator.CmsAuthenticatedDataOutputStream(macStream, mac, berSequenceGenerator, berSequenceGenerator2, berSequenceGenerator3);
            }
            catch (SecurityUtilityException e)
            {
                throw new CmsException("couldn't create cipher.", e);
            }
            catch (InvalidKeyException e2)
            {
                throw new CmsException("key invalid in message.", e2);
            }
            catch (IOException e3)
            {
                throw new CmsException("exception decoding algorithm parameters.", e3);
            }
            return(result);
        }
예제 #2
0
		protected Stream Open(
			Stream        			outStr,
			AlgorithmIdentifier		macAlgId,
			ICipherParameters		cipherParameters,
			Asn1EncodableVector		recipientInfos)
		{
			try
			{
				//
				// ContentInfo
				//
				BerSequenceGenerator cGen = new BerSequenceGenerator(outStr);

				cGen.AddObject(CmsObjectIdentifiers.AuthenticatedData);

				//
				// Authenticated Data
				//
				BerSequenceGenerator authGen = new BerSequenceGenerator(
					cGen.GetRawOutputStream(), 0, true);

				authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));

				Stream authRaw = authGen.GetRawOutputStream();
				Asn1Generator recipGen = _berEncodeRecipientSet
					?	(Asn1Generator) new BerSetGenerator(authRaw)
					:	new DerSetGenerator(authRaw);

				foreach (Asn1Encodable ae in recipientInfos)
				{
					recipGen.AddObject(ae);
				}

				recipGen.Close();

				authGen.AddObject(macAlgId);

				BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw);
				eiGen.AddObject(CmsObjectIdentifiers.Data);

				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
					eiGen.GetRawOutputStream(), 0, false, _bufferSize);

				IMac mac = MacUtilities.GetMac(macAlgId.ObjectID);
				// TODO Confirm no ParametersWithRandom needed
	            mac.Init(cipherParameters);
				Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac));

				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
			}
			catch (SecurityUtilityException e)
			{
				throw new CmsException("couldn't create cipher.", e);
			}
			catch (InvalidKeyException e)
			{
				throw new CmsException("key invalid in message.", e);
			}
			catch (IOException e)
			{
				throw new CmsException("exception decoding algorithm parameters.", e);
			}
		}
예제 #3
0
        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);
            }
        }
예제 #4
0
        /**
         * generate an enveloped object that contains an CMS Enveloped Data
         * object using the given provider and the passed in key generator.
         */
        private CmsAuthenticatedData Generate(
            CmsProcessable content,
            string macOid,
            CipherKeyGenerator keyGen)
        {
            AlgorithmIdentifier macAlgId;
            KeyParameter        encKey;
            Asn1OctetString     encContent;
            Asn1OctetString     macResult;

            try
            {
                // FIXME Will this work for macs?
                byte[] encKeyBytes = keyGen.GenerateKey();
                encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);

                Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);

                ICipherParameters cipherParameters;
                macAlgId = GetAlgorithmIdentifier(
                    macOid, encKey, asn1Params, out cipherParameters);

                IMac mac = MacUtilities.GetMac(macOid);
                // TODO Confirm no ParametersWithRandom needed
                // FIXME Only passing key at the moment
//	            mac.Init(cipherParameters);
                mac.Init(encKey);

                MemoryStream bOut = new MemoryStream();
                Stream       mOut = new TeeOutputStream(bOut, new MacOutputStream(mac));

                content.Write(mOut);

                mOut.Close();
                bOut.Close();

                encContent = new BerOctetString(bOut.ToArray());

                byte[] macOctets = MacUtilities.DoFinal(mac);
                macResult = new DerOctetString(macOctets);
            }
            catch (SecurityUtilityException e)
            {
                throw new CmsException("couldn't create cipher.", e);
            }
            catch (InvalidKeyException e)
            {
                throw new CmsException("key invalid in message.", e);
            }
            catch (IOException e)
            {
                throw new CmsException("exception decoding algorithm parameters.", e);
            }

            Asn1EncodableVector recipientInfos = new Asn1EncodableVector();

            foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
            {
                try
                {
                    recipientInfos.Add(rig.Generate(encKey, rand));
                }
                catch (InvalidKeyException e)
                {
                    throw new CmsException("key inappropriate for algorithm.", e);
                }
                catch (GeneralSecurityException e)
                {
                    throw new CmsException("error making encrypted content.", e);
                }
            }

            ContentInfo eci = new ContentInfo(CmsObjectIdentifiers.Data, encContent);

            ContentInfo contentInfo = new ContentInfo(
                CmsObjectIdentifiers.AuthenticatedData,
                new AuthenticatedData(null, new DerSet(recipientInfos), macAlgId, null, eci, null, macResult, null));

            return(new CmsAuthenticatedData(contentInfo));
        }
        /**
         * generate a signed object that for a CMS Signed Data
         * object using the given provider - 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.
         * @param out stream the CMS object is to be written to.
         * @param signedContentType OID for data to be signed.
         * @param encapsulate true if data should be encapsulated.
         * @param dataOutputStream output stream to copy the data being signed to.
         */
        public Stream Open(
            Stream outStream,
            string signedContentType,
            bool encapsulate,
            Stream dataOutputStream)
        {
            if (outStream == null)
            {
                throw new ArgumentNullException("outStream");
            }
            if (!outStream.CanWrite)
            {
                throw new ArgumentException("Expected writeable stream", "outStream");
            }
            if (dataOutputStream != null && !dataOutputStream.CanWrite)
            {
                throw new ArgumentException("Expected writeable stream", "dataOutputStream");
            }

            _messageDigestsLocked = true;

            //
            // ContentInfo
            //
            BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);

            sGen.AddObject(CmsObjectIdentifiers.SignedData);

            //
            // Signed Data
            //
            BerSequenceGenerator sigGen = new BerSequenceGenerator(
                sGen.GetRawOutputStream(), 0, true);

            sigGen.AddObject(CalculateVersion(signedContentType));

            Asn1EncodableVector digestAlgs = new Asn1EncodableVector();

            foreach (string digestOid in _messageDigestOids)
            {
                digestAlgs.Add(
                    new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
            }

            {
                byte[] tmp = new DerSet(digestAlgs).GetEncoded();
                sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
            }

            BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());

            eiGen.AddObject(new DerObjectIdentifier(signedContentType));

            Stream digStream;

            if (encapsulate)
            {
                BerOctetStringGenerator octGen = new BerOctetStringGenerator(
                    eiGen.GetRawOutputStream(), 0, true);

                digStream = octGen.GetOctetOutputStream(_bufferSize);

                if (dataOutputStream != null)
                {
                    digStream = new TeeOutputStream(dataOutputStream, digStream);
                }
            }
            else
            {
                if (dataOutputStream != null)
                {
                    digStream = dataOutputStream;
                }
                else
                {
                    digStream = new NullOutputStream();
                }
            }

            foreach (IDigest d in _messageDigests.Values)
            {
                digStream = new DigestStream(digStream, null, d);
            }

            return(new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen));
        }
        private CmsAuthenticatedData Generate(CmsProcessable content, string macOid, CipherKeyGenerator keyGen)
        {
            KeyParameter        keyParameter;
            AlgorithmIdentifier algorithmIdentifier;
            Asn1OctetString     content2;
            Asn1OctetString     mac2;

            try
            {
                byte[] array = keyGen.GenerateKey();
                keyParameter = ParameterUtilities.CreateKeyParameter(macOid, array);
                Asn1Encodable     asn1Params = this.GenerateAsn1Parameters(macOid, array);
                ICipherParameters cipherParameters;
                algorithmIdentifier = this.GetAlgorithmIdentifier(macOid, keyParameter, asn1Params, out cipherParameters);
                IMac mac = MacUtilities.GetMac(macOid);
                mac.Init(keyParameter);
                MemoryStream memoryStream = new MemoryStream();
                Stream       stream       = new TeeOutputStream(memoryStream, new MacOutputStream(mac));
                content.Write(stream);
                stream.Close();
                memoryStream.Close();
                content2 = new BerOctetString(memoryStream.ToArray());
                byte[] str = MacUtilities.DoFinal(mac);
                mac2 = new DerOctetString(str);
            }
            catch (SecurityUtilityException e)
            {
                throw new CmsException("couldn't create cipher.", e);
            }
            catch (InvalidKeyException e2)
            {
                throw new CmsException("key invalid in message.", e2);
            }
            catch (IOException e3)
            {
                throw new CmsException("exception decoding algorithm parameters.", e3);
            }
            Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(new Asn1Encodable[0]);

            foreach (RecipientInfoGenerator recipientInfoGenerator in this.recipientInfoGenerators)
            {
                try
                {
                    asn1EncodableVector.Add(new Asn1Encodable[]
                    {
                        recipientInfoGenerator.Generate(keyParameter, this.rand)
                    });
                }
                catch (InvalidKeyException e4)
                {
                    throw new CmsException("key inappropriate for algorithm.", e4);
                }
                catch (GeneralSecurityException e5)
                {
                    throw new CmsException("error making encrypted content.", e5);
                }
            }
            ContentInfo encapsulatedContent = new ContentInfo(CmsObjectIdentifiers.Data, content2);
            ContentInfo contentInfo         = new ContentInfo(CmsObjectIdentifiers.AuthenticatedData, new AuthenticatedData(null, new DerSet(asn1EncodableVector), algorithmIdentifier, null, encapsulatedContent, null, mac2, null));

            return(new CmsAuthenticatedData(contentInfo));
        }