public Rfc3161TimestampRequest(
            byte[] messageHash,
            HashAlgorithmName hashAlgorithm,
            Oid requestedPolicyId              = null,
            byte[] nonce                       = null,
            bool requestSignerCertificates     = false,
            X509ExtensionCollection extensions = null)
        {
            if (messageHash == null)
            {
                throw new ArgumentNullException(nameof(messageHash));
            }

            int    expectedSize;
            string algorithmIdentifier;

            if (!ResolveAlgorithm(hashAlgorithm, out expectedSize, out algorithmIdentifier))
            {
                throw new ArgumentOutOfRangeException(
                          nameof(hashAlgorithm),
                          hashAlgorithm,
                          "Hash algorithm is not supported by this method");
            }

            if (messageHash.Length != expectedSize)
            {
                throw new ArgumentException("Hash is not the correct size for the identified algorithm", nameof(messageHash));
            }

            if (requestedPolicyId != null && !Rfc3161TimestampUtils.IsLegalOid(requestedPolicyId.Value))
            {
                throw new ArgumentException("Value is not a legal object identifier", nameof(requestedPolicyId));
            }

            if (nonce != null && nonce.Length == 0)
            {
                throw new ArgumentException("Nonce must be null or non-empty", nameof(nonce));
            }

            var data = new DataType
            {
                _version                  = 1,
                _hash                     = (byte[])messageHash.Clone(),
                _hashAlgorithm            = OpportunisticOid(algorithmIdentifier),
                _nonce                    = (byte[])nonce?.Clone(),
                _requestSignerCertificate = requestSignerCertificates,
                _extensions               = Rfc3161TimestampTokenInfo.ShallowCopy(extensions, preserveNull: true),
            };

            if (requestedPolicyId != null)
            {
                data._requestedPolicyId = new Oid(requestedPolicyId.Value, requestedPolicyId.FriendlyName);
            }

            RawData = Encode(data);
        }
        public Rfc3161TimestampRequest(
            byte[] messageHash,
            Oid hashAlgorithmId,
            Oid requestedPolicyId              = null,
            byte[] nonce                       = null,
            bool requestSignerCertificates     = false,
            X509ExtensionCollection extensions = null)
        {
            if (messageHash == null)
            {
                throw new ArgumentNullException(nameof(messageHash));
            }
            if (hashAlgorithmId == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithmId));
            }
            if (!Rfc3161TimestampUtils.IsLegalOid(hashAlgorithmId.Value))
            {
                throw new ArgumentException("Value is not a legal object identifier", nameof(hashAlgorithmId));
            }

            if (requestedPolicyId != null && !Rfc3161TimestampUtils.IsLegalOid(requestedPolicyId.Value))
            {
                throw new ArgumentException("Value is not a legal object identifier", nameof(requestedPolicyId));
            }

            if (nonce != null && nonce.Length == 0)
            {
                throw new ArgumentException("Nonce must be null or non-empty", nameof(nonce));
            }

            DataType data = new DataType
            {
                _version                  = 1,
                _hash                     = (byte[])messageHash.Clone(),
                _hashAlgorithm            = new Oid(hashAlgorithmId.Value, hashAlgorithmId.FriendlyName),
                _nonce                    = (byte[])nonce?.Clone(),
                _requestSignerCertificate = requestSignerCertificates,
                _extensions               = Rfc3161TimestampTokenInfo.ShallowCopy(extensions, preserveNull: true),
            };

            if (requestedPolicyId != null)
            {
                data._requestedPolicyId = new Oid(requestedPolicyId.Value, requestedPolicyId.FriendlyName);
            }

            _data   = data;
            RawData = Encode(data);
        }
        public Rfc3161TimestampTokenInfo(
            string policyId,
            Oid hashAlgorithmId,
            byte[] messageHash,
            byte[] serialNumber,
            DateTimeOffset timestamp,
            long?accuracyInMicroseconds = null,
            bool isOrdering             = false,
            byte[] nonce   = null,
            byte[] tsaName = null,
            X509ExtensionCollection extensions = null)
            : base(TimestampTokenInfoId, new byte[] { })
        {
            if (policyId == null)
            {
                throw new ArgumentNullException(nameof(policyId));
            }
            if (!Rfc3161TimestampUtils.IsLegalOid(policyId))
            {
                throw new ArgumentException("Policy identifier does not represent a legal value", nameof(hashAlgorithmId));
            }
            if (hashAlgorithmId == null)
            {
                throw new ArgumentNullException(nameof(hashAlgorithmId));
            }
            if (!Rfc3161TimestampUtils.IsLegalOid(hashAlgorithmId.Value))
            {
                throw new ArgumentException("Hash algorithm does not represent a legal value", nameof(hashAlgorithmId));
            }
            if (messageHash == null)
            {
                throw new ArgumentNullException(nameof(messageHash));
            }
            if (messageHash.Length == 0)
            {
                throw new ArgumentException("Non-empty array is required", nameof(messageHash));
            }
            if (serialNumber == null)
            {
                throw new ArgumentNullException(nameof(serialNumber));
            }
            if (serialNumber.Length == 0)
            {
                throw new ArgumentException("Non-empty array is required", nameof(serialNumber));
            }

            var accuracy = accuracyInMicroseconds.GetValueOrDefault();

            if (accuracy < 0 || accuracy > 4294967295000000)
            {
                throw new ArgumentOutOfRangeException(nameof(accuracyInMicroseconds));
            }

            var tstInfo = new TstInfo
            {
                Version                = 1,
                PolicyId               = policyId,
                HashAlgorithmId        = new Oid(hashAlgorithmId.Value, hashAlgorithmId.FriendlyName),
                HashedMessage          = (byte[])messageHash.Clone(),
                SerialNumber           = (byte[])serialNumber.Clone(),
                Timestamp              = timestamp.ToUniversalTime(),
                AccuracyInMicroseconds = accuracyInMicroseconds,
                IsOrdering             = isOrdering,
                Nonce      = (byte[])nonce?.Clone(),
                TsaName    = (byte[])tsaName?.Clone(),
                Extensions = ShallowCopy(extensions, preserveNull: true),
            };

            RawData  = Encode(tstInfo);
            _decoded = tstInfo;
        }