private byte[] Encode()
        {
            // CertificationRequestInfo::= SEQUENCE {
            //   version INTEGER { v1(0) } (v1,...),
            //   subject Name,
            //   subjectPKInfo SubjectPublicKeyInfo{ { PKInfoAlgorithms } },
            //   attributes[0] Attributes{ { CRIAttributes } }
            // }
            //
            // Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}

            byte[][] attrSet = Attributes.SegmentedEncodeAttributeSet();

            // Replace the tag with ContextSpecific0.
            attrSet[0][0] = DerSequenceReader.ContextSpecificConstructedTag0;

            return(DerEncoder.ConstructSequence(
                       s_encodedVersion,
                       Subject.RawData.WrapAsSegmentedForSequence(),
                       PublicKey.SegmentedEncodeSubjectPublicKeyInfo(),
                       attrSet));
        }
示例#2
0
        private byte[] Encode(X509SignatureGenerator signatureGenerator, HashAlgorithmName hashAlgorithm)
        {
            // State validation should be runtime checks if/when this becomes public API
            Debug.Assert(Subject != null);
            Debug.Assert(PublicKey != null);

            // Under a public API model we could allow these to be null for a self-signed case.
            Debug.Assert(SerialNumber != null);
            Debug.Assert(Issuer != null);

            List <byte[][]> encodedFields = new List <byte[][]>();

            byte version = Version;

            if (version != 0)
            {
                byte[][] encodedVersion = DerEncoder.ConstructSegmentedSequence(
                    DerEncoder.SegmentedEncodeUnsignedInteger(new[] { version }));

                encodedVersion[0][0] = DerSequenceReader.ContextSpecificConstructedTag0;

                encodedFields.Add(encodedVersion);
            }

            encodedFields.Add(DerEncoder.SegmentedEncodeUnsignedInteger(SerialNumber));

            // SignatureAlgorithm: Use the specified value, or ask the generator (without mutating the class)
            byte[] signatureAlgorithm = SignatureAlgorithm ?? signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm);
            EncodingHelpers.ValidateSignatureAlgorithm(signatureAlgorithm);

            encodedFields.Add(signatureAlgorithm.WrapAsSegmentedForSequence());

            // For public API allowing self-sign ease-of-use, this could be (Issuer ?? Subject).
            encodedFields.Add(Issuer.RawData.WrapAsSegmentedForSequence());

            encodedFields.Add(
                DerEncoder.ConstructSegmentedSequence(
                    EncodeValidityField(NotBefore, nameof(NotBefore)),
                    EncodeValidityField(NotAfter, nameof(NotAfter))));

            encodedFields.Add(Subject.RawData.WrapAsSegmentedForSequence());

            encodedFields.Add(PublicKey.SegmentedEncodeSubjectPublicKeyInfo());

            // Issuer and Subject Unique ID values would go here, if they were supported.

            if (Extensions.Count > 0)
            {
                Debug.Assert(version >= 2);

                List <byte[][]> encodedExtensions = new List <byte[][]>(Extensions.Count);

                // extensions[3]  Extensions OPTIONAL
                //
                // Since this doesn't say IMPLICIT, it will look like
                //
                // A3 [length]
                //   30 [length]
                //     First Extension
                //     Second Extension
                //     ...

                // An interesting quirk of skipping null values here is that
                // Extensions.Count == 0 => no extensions
                // Extensions.ContainsOnly(null) => empty extensions list

                HashSet <string> usedOids = new HashSet <string>(Extensions.Count);

                foreach (X509Extension extension in Extensions)
                {
                    if (extension == null)
                    {
                        continue;
                    }

                    if (!usedOids.Add(extension.Oid.Value))
                    {
                        throw new InvalidOperationException(
                                  SR.GetString(SR.Cryptography_CertReq_DuplicateExtension, extension.Oid.Value));
                    }

                    encodedExtensions.Add(extension.SegmentedEncodedX509Extension());
                }

                byte[][] extensionField = DerEncoder.ConstructSegmentedSequence(
                    DerEncoder.ConstructSegmentedSequence(encodedExtensions));
                extensionField[0][0] = DerSequenceReader.ContextSpecificConstructedTag3;

                encodedFields.Add(extensionField);
            }

            return(DerEncoder.ConstructSequence(encodedFields));
        }