How to extract the Email from a X509 Certificate in .NET?

2.1k views Asked by At

I'm looking for the way to get the Email (string) from X509 Certificate. I can't find ready property or method for this. So the best for me (most flexible for future tasks) is to get the value by ASN OID (1.2.840.113549.1.9.1). How can I do this using native .NET class?

I tried to use AsnEncodedData.format but without any effect. Is there a way to do this?

1

There are 1 answers

0
Crypt32 On

If it is ok to use 3rd party tools, then you may look at my Powershell PKI module. This module contains a PKI.Core.dll library which is a set of API. APIs are fairly well documented in the Library documentation

With thid library I would go with the following static method and custom class:

using PKI.ASN;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace MyNamespace {
    public class RdnAttribute {
        public Oid OID { get; set; }
        public String Value { get; set; }
    }
    public class MyClass {
        public static List<RdnAttribute> GetRdnAttributes(X500DistinguishedName name) {
            List<RdnAttribute> retValue = new List<RdnAttribute>();
            ASN1 asn = new ASN1(name.RawData);
            asn.MoveNext();
            do {
                ASN1 asn2 = new ASN1(asn.Payload);
                asn2.MoveNext();
                List<Byte> oidRawData = new List<Byte>(asn2.Header);
                oidRawData.AddRange(asn2.Payload);
                Oid oid = ASN1.DecodeObjectIdentifier(oidRawData.ToArray());
                asn2.MoveNext();
                String value;
                switch (asn2.Tag) {
                    case (Byte)ASN1Tags.UniversalString:
                        value = Encoding.UTF32.GetString(asn2.Payload);
                        break;
                    case (Byte)ASN1Tags.BMPString:
                        value = Encoding.BigEndianUnicode.GetString(asn2.Payload);
                        break;
                    default:
                        value = Encoding.UTF8.GetString(asn2.Payload);
                        break;
                }
                retValue.Add(new RdnAttribute { OID = oid, Value = value });
            } while (asn.MoveNextCurrentLevel());
            return retValue;
        }
    }
}

The method returns an array (unordered) of RDN attributes, where OID property contains RDN object identifier and Value property contains RDN text value. If you can use Linq, then you can quickly search through collection: somearray.Where(x => x.OID.Value == "1.2.840.113549.1.9.1");. Note that particular RDN attributes may appear multiple times, therefore you should not use First* or Single* Linq methods.