Exemplo n.º 1
0
        public static readonly PemKind PgpMessagePartX;  // How to handle this?

        /// <summary>
        /// Initializes the <see cref="PemKind"/> class.
        /// </summary>
        static PemKind()
        {
            registry = new Dictionary <string, PemKind>();

            X509Certificate               = new PemKind("CERTIFICATE", "Stores a X509 Certificate");
            X509CertificatePair           = new PemKind("CERTIFICATE PAIR", "Stores a pair of X509 Certificates");
            X509TrustedCertificate        = new PemKind("TRUSTED CERTIFICATE", "Stores a trusted X509 Certificate");
            X509CertificateRequest        = new PemKind("CERTIFICATE REQUEST", "Stores a X509 Certificate Signature Request"); // PKCS #10
            X509CertificateRevocationList = new PemKind("X509 CRL", "Stores a X509 Certificate Revocation List");

            AnyPrivateKey   = new PemKind("ANY PRIVATE KEY", "Stores a private key");
            PublicKey       = new PemKind("PUBLIC KEY", "Stores a public key");
            RsaPrivateKey   = new PemKind("RSA PRIVATE KEY", "Stores a RSA private key");
            RsaPublicKey    = new PemKind("RSA PUBLIC KEY", "Stores a RSA public key");
            DsaPrivateKey   = new PemKind("DSA PRIVATE KEY", "Stores a DSA private key");
            DsaPublicKey    = new PemKind("DSA PUBLIC KEY", "Stores a DSA public key");
            DsaParameters   = new PemKind("DSA PARAMETERS", "Stores DSA parameters");
            EcdsaPrivateKey = new PemKind("EC PRIVATE KEY", "Stores a ECDSA private key");
            EcdsaPublicKey  = new PemKind("ECDSA PUBLIC KEY", "Stores a ECDSA public key");
            EcdsaParameters = new PemKind("EC PARAMETERS", "Stores ECDSA parameters");
            Parameters      = new PemKind("PARAMETERS", "Stores a cryptographic algorithm parameters");

            Pkcs7       = new PemKind("PKCS7", "Stores a PKCS #7 message");
            Pkcs7Signed = new PemKind("PKCS #7 SIGNED DATA", "Stores a signed PKCS #7 message");

            Pkcs8Encrypted = new PemKind("ENCRYPTED PRIVATE KEY", "Stores an encrypted PKCS #8 key pair");
            Pkcs8          = new PemKind("PRIVATE KEY", "Stores a PKCS #8 key pair");

            DiffieHelmmanPkcs3 = new PemKind("DH PARAMETERS", "Stores Diffie–Hellman Key Agreement parameters according to the scheme specified by PKCS #3");
            DiffieHelmmanX942  = new PemKind("X9.42 DH PARAMETERS", "Stores Diffie–Hellman Key Agreement parameters according to the scheme specified in ANSI X9.42");

            SslSession = new PemKind("SSL SESSION PARAMETERS", "Stores the parameters of a SSL session");

            Cms = new PemKind("CMS", "Stores Cryptographic Message Syntax data");

            X509CertificateOld        = new PemKind("X509 CERTIFICATE", "Stores a X509 Certificate; obsolete, prefer 'CERTIFICATE'", true);
            X509CertificateRequestOld = new PemKind("NEW CERTIFICATE REQUEST", "Stores a X509 Certificate Request; obsolete, prefer 'CERTIFICATE REQUEST'", true);

            // Below are other common PEM Headers (but not grabbed from OpenSSL)
            Ssh2PublicKeyRfc4716 = new PemKind("SSH2 PUBLIC KEY", "Stores an SSH2 Public Key according to RFC 4716");

            // ASCII-armored PGP files
            PgpPublicKey     = new PemKind("PGP PUBLIC KEY BLOCK", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true);
            PgpPrivateKey    = new PemKind("PGP PRIVATE KEY BLOCK", "Stores a PGP Private Key and its checksum", hasPgpChecksum: true);
            PgpSignature     = new PemKind("PGP SIGNATURE", "Stores a PGP Signature and its checksum", hasPgpChecksum: true);
            PgpMessage       = new PemKind("PGP MESSAGE", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true);
            PgpMessagePartXY = new PemKind("PGP MESSAGE, PART {0}/{1}", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true); // how to handle this?
            PgpMessagePartX  = new PemKind("PGP MESSAGE, PART {0}", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true);     // how to handle this?
        }
Exemplo n.º 2
0
        public static readonly PemKind PgpMessagePartX; // How to handle this?

        /// <summary>
        /// Initializes the <see cref="PemKind"/> class.
        /// </summary>
        static PemKind()
        {
            registry = new Dictionary<string, PemKind>();

            X509Certificate = new PemKind("CERTIFICATE", "Stores a X509 Certificate");
            X509CertificatePair = new PemKind("CERTIFICATE PAIR", "Stores a pair of X509 Certificates");
            X509TrustedCertificate = new PemKind("TRUSTED CERTIFICATE", "Stores a trusted X509 Certificate");
            X509CertificateRequest = new PemKind("CERTIFICATE REQUEST", "Stores a X509 Certificate Signature Request"); // PKCS #10
            X509CertificateRevocationList = new PemKind("X509 CRL", "Stores a X509 Certificate Revocation List");

            AnyPrivateKey = new PemKind("ANY PRIVATE KEY", "Stores a private key");
            PublicKey = new PemKind("PUBLIC KEY", "Stores a public key");
            RsaPrivateKey = new PemKind("RSA PRIVATE KEY", "Stores a RSA private key");
            RsaPublicKey = new PemKind("RSA PUBLIC KEY", "Stores a RSA public key");
            DsaPrivateKey = new PemKind("DSA PRIVATE KEY", "Stores a DSA private key");
            DsaPublicKey = new PemKind("DSA PUBLIC KEY", "Stores a DSA public key");
            DsaParameters = new PemKind("DSA PARAMETERS", "Stores DSA parameters");
            EcdsaPrivateKey = new PemKind("EC PRIVATE KEY", "Stores a ECDSA private key");
            EcdsaPublicKey = new PemKind("ECDSA PUBLIC KEY", "Stores a ECDSA public key");
            EcdsaParameters = new PemKind("EC PARAMETERS", "Stores ECDSA parameters");
            Parameters = new PemKind("PARAMETERS", "Stores a cryptographic algorithm parameters");

            Pkcs7 = new PemKind("PKCS7", "Stores a PKCS #7 message");
            Pkcs7Signed = new PemKind("PKCS #7 SIGNED DATA", "Stores a signed PKCS #7 message");

            Pkcs8Encrypted = new PemKind("ENCRYPTED PRIVATE KEY", "Stores an encrypted PKCS #8 key pair");
            Pkcs8 = new PemKind("PRIVATE KEY", "Stores a PKCS #8 key pair");

            DiffieHelmmanPkcs3 = new PemKind("DH PARAMETERS", "Stores Diffie–Hellman Key Agreement parameters according to the scheme specified by PKCS #3");
            DiffieHelmmanX942 = new PemKind("X9.42 DH PARAMETERS", "Stores Diffie–Hellman Key Agreement parameters according to the scheme specified in ANSI X9.42");

            SslSession = new PemKind("SSL SESSION PARAMETERS", "Stores the parameters of a SSL session");

            Cms = new PemKind("CMS", "Stores Cryptographic Message Syntax data");

            X509CertificateOld = new PemKind("X509 CERTIFICATE", "Stores a X509 Certificate; obsolete, prefer 'CERTIFICATE'", true);
            X509CertificateRequestOld = new PemKind("NEW CERTIFICATE REQUEST", "Stores a X509 Certificate Request; obsolete, prefer 'CERTIFICATE REQUEST'", true);

            // Below are other common PEM Headers (but not grabbed from OpenSSL)
            Ssh2PublicKeyRfc4716 = new PemKind("SSH2 PUBLIC KEY", "Stores an SSH2 Public Key according to RFC 4716");

            // ASCII-armored PGP files
            PgpPublicKey = new PemKind("PGP PUBLIC KEY BLOCK", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true);
            PgpPrivateKey = new PemKind("PGP PRIVATE KEY BLOCK", "Stores a PGP Private Key and its checksum", hasPgpChecksum: true);
            PgpSignature = new PemKind("PGP SIGNATURE", "Stores a PGP Signature and its checksum", hasPgpChecksum: true);
            PgpMessage = new PemKind("PGP MESSAGE", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true);
            PgpMessagePartXY = new PemKind("PGP MESSAGE, PART {0}/{1}", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true); // how to handle this?
            PgpMessagePartX = new PemKind("PGP MESSAGE, PART {0}", "Stores a PGP Public Key and its checksum", hasPgpChecksum: true); // how to handle this?
        }
        private PemInfo Decode()
        {
            if (dirty)
            {
                throw new InvalidOperationException("A PemDecoder instance should only be used once.");
            }
            dirty = true;

            var strings = ReadAllLines(TextData);

            if (strings == null || strings.Length == 0)
            {
                AddError("No data.");
                return(null);
            }

            var altHeader = false;

            FullHeader = strings[0];
            if (!IsHeader(FullHeader, out altHeader))
            {
                AddError("First line does not contain a PEM Header.");
                return(null);
            }

            var altFooter             = false;
            var index                 = 1;
            var workloadLines         = new List <string>();
            var additionalDataBuilder = new StringBuilder();

            while (index < strings.Length)
            {
                var current = strings[index];
                var tag     = string.Empty;
                var content = string.Empty;
                if (IsAdditionalHeader(current, out tag, out content))
                {
                    AddAdditionalHeader(tag, content);
                }
                else if (string.IsNullOrWhiteSpace(current))
                {
                    // ignore white lines
                }
                else if (!IsFooter(current, out altFooter))
                {
                    if (string.IsNullOrEmpty(FullFooter))
                    {
                        workloadLines.Add(current);
                    }
                    else
                    {
                        additionalDataBuilder.AppendLine(current);
                    }
                }
                else
                {
                    FullFooter = current;
                }
                index++;
            }

            // All data was read, now go check consistency.

            if (altHeader != altFooter)
            {
                AddWarning(altHeader ?
                           "PEM inconsistency: header uses the alternate form ('---- BEGIN') whereas footer does not ('-----END')." :
                           "PEM inconsistency: header uses the normal form ('-----BEGIN') whereas footer does not ('---- END').");
            }

            var header = ExtractHeader(FullHeader, altHeader);
            var footer = ExtractFooter(FullFooter, altFooter);

            if (header != footer)
            {
                AddWarning(string.Format(
                               "PEM inconsistency: header ({0}) does not match footer ({1}).", header, footer));
            }

            Kind = PemKind.Find(header);
            if (Kind == null)
            {
                AddWarning(string.Format("PEM header {0} is not a well-known PEM header.", header));
                Kind = PemKind.GetCustom(header, "Not a well-known PEM header.");
            }

            // convert the lines list to a string builder.
            IEnumerable <string> lines = Kind.HasPgpChecksum ? // if PGP-like PEM, last line is a checksum, not part of the real workload
                                         Enumerable.Range(0, workloadLines.Count - 1).Select(i => workloadLines[i]) :
                                         workloadLines;

            var base64Builder = new StringBuilder();

            foreach (var line in lines)
            {
                base64Builder.Append(line);
            }

            if (Kind.HasPgpChecksum)
            {
                try
                {
                    // PGP Checksums starts with a '=' character
                    var checksum = workloadLines[workloadLines.Count - 1];
                    checksum    = checksum.TrimStart('=');
                    PgpChecksum = Convert.FromBase64String(checksum);
                }
                catch (Exception ex)
                {
                    AddWarning(string.Format("Could not decode PGP Checksum from input Base64 data: {0}", ex.Message));
                }
            }

            try
            {
                Workload = Convert.FromBase64String(base64Builder.ToString());
            }
            catch (Exception ex)
            {
                AddError(string.Format("Could not decode input Base64 data: {0}", ex.Message));
            }

            // TODO: validates PGP checksums

            AdditionalText = additionalDataBuilder.ToString();

            return(new PemInfo(this));
        }