Пример #1
0
        internal void Decode(ReadOnlyMemory <byte> encodedMessage)
        {
            AsnValueReader reader = new AsnValueReader(encodedMessage.Span, AsnEncodingRules.BER);

            // Windows (and thus NetFx) reads the leading data and ignores extra.
            // So use the Decode overload which doesn't throw on extra data.
            ContentInfoAsn.Decode(
                ref reader,
                encodedMessage,
                out ContentInfoAsn contentInfo);

            if (contentInfo.ContentType != Oids.Pkcs7Signed)
            {
                throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
            }

            // Hold a copy of the SignedData memory so we are protected against memory reuse by the caller.
            _heldData        = contentInfo.Content.ToArray();
            _signedData      = SignedDataAsn.Decode(_heldData, AsnEncodingRules.BER);
            _contentType     = _signedData.EncapContentInfo.ContentType;
            _hasPkcs7Content = false;

            if (!Detached)
            {
                ReadOnlyMemory <byte>?content = _signedData.EncapContentInfo.Content;
                ReadOnlyMemory <byte> contentValue;

                if (content.HasValue)
                {
                    contentValue = GetContent(content.Value, _contentType);
                    // If no OCTET STRING was stripped off, we have PKCS7 interop concerns.
                    _hasPkcs7Content = content.Value.Length == contentValue.Length;
                }
                else
                {
                    contentValue = ReadOnlyMemory <byte> .Empty;
                }

                // This is in _heldData, so we don't need a defensive copy.
                _heldContent = contentValue;

                // The ContentInfo object/property DOES need a defensive copy, because
                // a) it is mutable by the user, and
                // b) it is no longer authoritative
                //
                // (and c: it takes a byte[] and we have a ReadOnlyMemory<byte>)
                ContentInfo = new ContentInfo(new Oid(_contentType), contentValue.ToArray());
            }
            else
            {
                // Hold a defensive copy of the content bytes, (Windows/NetFx compat)
                _heldContent = ContentInfo.Content.CloneByteArray();
            }

            Version  = _signedData.Version;
            _hasData = true;
        }
Пример #2
0
        public byte[] Encode()
        {
            if (!_hasData)
            {
                throw new InvalidOperationException(SR.Cryptography_Cms_MessageNotSigned);
            }

            try
            {
                using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
                {
                    _signedData.Encode(writer);
                    return(PkcsHelpers.EncodeContentInfo(writer.Encode(), Oids.Pkcs7Signed));
                }
            }
            catch (CryptographicException) when(!Detached)
            {
                // If we can't write the contents back out then the most likely culprit is an
                // indefinite length encoding in the content field.  To preserve as much input data
                // as possible while still maintaining our expectations of sorting any SET OF values,
                // do the following:
                // * Write the DER normalized version of the SignedData in detached mode.
                // * BER-decode that structure
                // * Copy the content field over
                // * BER-write the modified structure.

                SignedDataAsn copy = _signedData;

                copy.EncapContentInfo.Content = null;
                Debug.Assert(_signedData.EncapContentInfo.Content != null);

                using (AsnWriter detachedWriter = new AsnWriter(AsnEncodingRules.DER))
                {
                    copy.Encode(detachedWriter);
                    copy = SignedDataAsn.Decode(detachedWriter.Encode(), AsnEncodingRules.BER);
                }

                copy.EncapContentInfo.Content = _signedData.EncapContentInfo.Content;

                using (AsnWriter attachedWriter = new AsnWriter(AsnEncodingRules.BER))
                {
                    copy.Encode(attachedWriter);
                    return(PkcsHelpers.EncodeContentInfo(attachedWriter.Encode(), Oids.Pkcs7Signed));
                }
            }
        }
Пример #3
0
        public void Decode(ReadOnlySpan <byte> encodedMessage)
        {
            // Hold a copy of the SignedData memory so we are protected against memory reuse by the caller.
            _heldData        = CopyContent(encodedMessage);
            _signedData      = SignedDataAsn.Decode(_heldData, AsnEncodingRules.BER);
            _contentType     = _signedData.EncapContentInfo.ContentType;
            _hasPkcs7Content = false;

            if (!Detached)
            {
                ReadOnlyMemory <byte>?content = _signedData.EncapContentInfo.Content;
                ReadOnlyMemory <byte> contentValue;

                if (content.HasValue)
                {
                    contentValue = GetContent(content.Value, _contentType);
                    // If no OCTET STRING was stripped off, we have PKCS7 interop concerns.
                    _hasPkcs7Content = content.Value.Length == contentValue.Length;
                }
                else
                {
                    contentValue = ReadOnlyMemory <byte> .Empty;
                }

                // This is in _heldData, so we don't need a defensive copy.
                _heldContent = contentValue;

                // The ContentInfo object/property DOES need a defensive copy, because
                // a) it is mutable by the user, and
                // b) it is no longer authoritative
                //
                // (and c: it takes a byte[] and we have a ReadOnlyMemory<byte>)
                ContentInfo = new ContentInfo(new Oid(_contentType), contentValue.ToArray());
            }
            else
            {
                // Hold a defensive copy of the content bytes, (Windows/NetFx compat)
                _heldContent = ContentInfo.Content.CloneByteArray();
            }

            Version  = _signedData.Version;
            _hasData = true;
Пример #4
0
        public static Pkcs12Info Decode(
            ReadOnlyMemory <byte> encodedBytes,
            out int bytesConsumed,
            bool skipCopy = false)
        {
            AsnReader reader = new AsnReader(encodedBytes, AsnEncodingRules.BER);

            // Trim it to the first value
            encodedBytes = reader.PeekEncodedValue();

            ReadOnlyMemory <byte> maybeCopy = skipCopy ? encodedBytes : encodedBytes.ToArray();
            PfxAsn pfx = PfxAsn.Decode(maybeCopy, AsnEncodingRules.BER);

            // https://tools.ietf.org/html/rfc7292#section-4 only defines version 3.
            if (pfx.Version != 3)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            ReadOnlyMemory <byte> authSafeBytes = ReadOnlyMemory <byte> .Empty;
            Pkcs12IntegrityMode   mode          = Pkcs12IntegrityMode.Unknown;

            if (pfx.AuthSafe.ContentType == Oids.Pkcs7Data)
            {
                authSafeBytes = PkcsHelpers.DecodeOctetStringAsMemory(pfx.AuthSafe.Content);

                if (pfx.MacData.HasValue)
                {
                    mode = Pkcs12IntegrityMode.Password;
                }
                else
                {
                    mode = Pkcs12IntegrityMode.None;
                }
            }
            else if (pfx.AuthSafe.ContentType == Oids.Pkcs7Signed)
            {
                SignedDataAsn signedData = SignedDataAsn.Decode(pfx.AuthSafe.Content, AsnEncodingRules.BER);

                mode = Pkcs12IntegrityMode.PublicKey;

                if (signedData.EncapContentInfo.ContentType == Oids.Pkcs7Data)
                {
                    authSafeBytes = signedData.EncapContentInfo.Content.GetValueOrDefault();
                }

                if (pfx.MacData.HasValue)
                {
                    throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                }
            }

            if (mode == Pkcs12IntegrityMode.Unknown)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            List <ContentInfoAsn> authSafeData   = new List <ContentInfoAsn>();
            AsnReader             authSafeReader = new AsnReader(authSafeBytes, AsnEncodingRules.BER);
            AsnReader             sequenceReader = authSafeReader.ReadSequence();

            authSafeReader.ThrowIfNotEmpty();
            while (sequenceReader.HasData)
            {
                ContentInfoAsn.Decode(sequenceReader, out ContentInfoAsn contentInfo);
                authSafeData.Add(contentInfo);
            }

            ReadOnlyCollection <Pkcs12SafeContents> authSafe;

            if (authSafeData.Count == 0)
            {
                authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(Array.Empty <Pkcs12SafeContents>());
            }
            else
            {
                Pkcs12SafeContents[] contentsArray = new Pkcs12SafeContents[authSafeData.Count];

                for (int i = 0; i < contentsArray.Length; i++)
                {
                    contentsArray[i] = new Pkcs12SafeContents(authSafeData[i]);
                }

                authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(contentsArray);
            }

            bytesConsumed = encodedBytes.Length;

            return(new Pkcs12Info
            {
                AuthenticatedSafe = authSafe,
                IntegrityMode = mode,
                _decoded = pfx,
                _authSafeContents = authSafeBytes,
            });
        }