예제 #1
0
        public string ExportPkcs7Pem()
        {
            byte[]? pkcs7 = Export(X509ContentType.Pkcs7);

            if (pkcs7 is null)
            {
                throw new CryptographicException(SR.Cryptography_X509_ExportFailed);
            }

            int encodedSize = PemEncoding.GetEncodedSize(PemLabels.Pkcs7Certificate.Length, pkcs7.Length);

            return(string.Create(encodedSize, pkcs7, static (destination, pkcs7) => {
예제 #2
0
        /// <summary>
        /// Attempts to export the public X.509 certificates, encoded as PEM.
        /// </summary>
        /// <param name="destination">The buffer to receive the PEM encoded certificates.</param>
        /// <param name="charsWritten">When this method returns, the total number of characters written to <paramref name="destination" />.</param>
        /// <returns>
        ///   <see langword="true"/> if <paramref name="destination"/> was large enough to receive the encoded PEMs;
        ///   otherwise, <see langword="false" />.
        /// </returns>
        /// <exception cref="CryptographicException">
        /// A certificate is corrupt, in an invalid state, or could not be exported
        /// to PEM.
        /// </exception>
        /// <remarks>
        /// <p>
        ///   A PEM-encoded X.509 certificate collection will contain certificates
        ///   where each certificate begins with <c>-----BEGIN CERTIFICATE-----</c>
        ///   and ends with <c>-----END CERTIFICATE-----</c>, with the base64 encoded DER
        ///   contents of the certificate between the PEM boundaries. Each certificate is
        ///   separated by a single line-feed character.
        /// </p>
        /// <p>
        ///   Certificates are encoded according to the IETF RFC 7468 &quot;strict&quot;
        ///   encoding rules.
        /// </p>
        /// </remarks>
        public bool TryExportCertificatePems(Span <char> destination, out int charsWritten)
        {
            Span <char> buffer  = destination;
            int         written = 0;

            for (int i = 0; i < Count; i++)
            {
                ReadOnlyMemory <byte> certData = this[i].RawDataMemory;
                int certSize = PemEncoding.GetEncodedSize(PemLabels.X509Certificate.Length, certData.Length);

                // If we ran out of space in the destination, return false. It's okay
                // that we may have successfully written data to the destination
                // already. Since certificates only contain "public" information,
                // we don't need to clear what has been written already.
                if (buffer.Length < certSize)
                {
                    charsWritten = 0;
                    return(false);
                }

                if (!PemEncoding.TryWrite(PemLabels.X509Certificate, certData.Span, buffer, out int certWritten) ||
                    certWritten != certSize)
                {
                    Debug.Fail("Presized buffer is too small or did not write the correct amount.");
                    throw new CryptographicException();
                }

                buffer   = buffer.Slice(certWritten);
                written += certWritten;

                // write a new line if not the last certificate.
                if (i < Count - 1)
                {
                    if (buffer.IsEmpty)
                    {
                        charsWritten = 0;
                        return(false);
                    }

                    // Always use Unix line endings between certificates to match the
                    // behavior of PemEncoding.TryWrite, which is following RFC 7468.
                    buffer[0] = '\n';
                    buffer    = buffer.Slice(1);
                    written++;
                }
            }

            charsWritten = written;
            return(true);
        }
예제 #3
0
        internal static string CreatePemFromData(string label, ReadOnlyMemory <byte> data)
        {
            int pemSize = PemEncoding.GetEncodedSize(label.Length, data.Length);

            return(string.Create(pemSize, (label, data), static (destination, args) =>
            {
                (string label, ReadOnlyMemory <byte> data) = args;

                if (!PemEncoding.TryWrite(label, data.Span, destination, out int charsWritten) ||
                    charsWritten != destination.Length)
                {
                    Debug.Fail("Pre-allocated buffer was not the correct size.");
                    throw new CryptographicException();
                }
            }));
예제 #4
0
        private int GetCertificatePemsSize()
        {
            checked
            {
                int size = 0;

                for (int i = 0; i < Count; i++)
                {
                    size += PemEncoding.GetEncodedSize(PemLabels.X509Certificate.Length, this[i].RawDataMemory.Length);

                    // Add a \n character between each certificate, except the last one.
                    if (i < Count - 1)
                    {
                        size += 1;
                    }
                }

                return(size);
            }
        }
예제 #5
0
 public static void GetEncodedSize_LabelLength_Negative()
 {
     AssertExtensions.Throws <ArgumentOutOfRangeException>("labelLength",
                                                           () => PemEncoding.GetEncodedSize(labelLength: -1, dataLength: 0));
 }
예제 #6
0
        public static void GetEncodedSize_Boundaries(int labelLength, int dataLength, int expectedSize)
        {
            int size = PemEncoding.GetEncodedSize(labelLength, dataLength);

            Assert.Equal(expectedSize, size);
        }
예제 #7
0
        public static void GetEncodedSize_Empty()
        {
            int size = PemEncoding.GetEncodedSize(labelLength: 0, dataLength: 0);

            Assert.Equal(31, size);
        }