Парсинг CSR библиотекой bouncy castle в С#

89
03 декабря 2020, 04:40

Есть необходимость проверять запросы на сертификаты(CSR). Сам запрос раскладываю так:

    public static Pkcs10CertificationRequest Request (string request)
    {
        string selectedPath = Loader.requestDirectory.FullName + request;
        string csr = File.ReadAllText(selectedPath);
        char[] characters =
            csr.Replace("-----BEGIN NEW CERTIFICATE REQUEST-----", "")
            .Replace("-----END NEW CERTIFICATE REQUEST-----", "")
            .ToCharArray();
        byte[] csrEncode = Convert.FromBase64CharArray(characters, 0, characters.Length);
        Pkcs10CertificationRequest decodedCsr = new Pkcs10CertificationRequest(csrEncode);
        return decodedCsr;
    }
Pkcs10CertificationRequest decodedCsr = Request(*сюда попадет сертификат выбранной из формы*);
CertificationRequestInfo requestInfo = decodedCsr.GetCertificationRequestInfo();

Проверка происходит сравнением данных в запросе и в шаблоне по определенным полям. В случае успеха во всех пунктах возвращается true, т.е. всё ок. Проблема в том, что библиотека неоднозначно возвращает поля. Я увидел два способа: 1.

requestInfo.Subject.ToString();
//1.2.643.100.3=тут инн,1.2.643.100.1=тут огрн,1.2.643.3.131.1.1=тут тоже инн,E=мыло,C=RU,ST=78 г. Санкт-Петербург,L=Санкт-Петербург,O=название орг,OU=отдел,CN=имя,STREET=адрес и вот тут проблема(ниже опишу),GIVENNAME=Иван Иваныч,SURNAME=Иванов

Я сначала подумал, что можно сделать сплит по запятой, т.к. она есть после каждого поля, но в адреса может быть запись "улица, дом 55" - и тогда она тоже разобьет. Тогда я решил сделать:

requestInfo.Subject.GetValueList();

Но в выводе я полую список ТОЛЬКО значений, без пояснения полей, т.к. метод реализуется через интерфейс IList, что в итоге тоже не применимо, т.к. не ясно какое это поле и что с ним сравнивать, т.к. 1.2.643.100.3 - может быть 10, а может 12. И если он вдруг окажется не первый в списке, или другие поля сдвинуться - получится беда.

Как выйти из этой ситуации? Или может не bouncy castle использовать? У кого был опыт работы с запросами, подскажите. Я ещё думал о том, чтобы перебор Subject сделать с реакцией на = и значением после. Типа:

  • Берем набор символов до =
  • Записываем в ключ
  • Берем после = и до =,
  • Записываем в значение
  • и т.д.

Но это чет выглядит как-то убого. Может есть способ для идиотов вроде меня?

Answer 1

Я сделал в итоге так: Добавил метод расширения для Subject

    public static Dictionary<string, string> SubjectFriendlyInfo(this X509Name subject)
    {
        Dictionary<string, string> collection = new Dictionary<string, string>();
        int valueCount = subject.GetOidList().ToList().Count;
        for (int i = 0; i < valueCount; i++)
        {
            collection.Add(subject.GetOidList().ToList()[i], subject.GetValueList().ToList()[i]);
        }
        return collection;
    }

В моих влажных мечтах он собирает пару ключ(OID)-значение(значение). Надеюсь я не наступлю на какие-нибудь грабли.

Answer 2

Подключил nuget в linqpad, поковырял немного. Образца запроса нет, поэтому пример немного синтетический, взят из вопроса с en so:

string subject = "CN=Name,O=Org,C=IN,ST=KA,OU=OrgUn,PostalCode=560103";
X509Name sub = new X509Name(subject);
var oidList = sub.GetOidList();
var oidsVal = sub.GetValueList();
oidList.Dump();
oidsVal.Dump();

Выведет:

Пример взят наощупь, но есть уверенность, что заработает, т.к. тип вашего csr.GetCertificationRequestInfo().Subject такой же - X509Name:

Кстати, и на ваших данных работает:

string subject = "1.2.643.100.3=тут инн,1.2.643.100.1=тут огрн,1.2.643.3.131.1.1=тут тоже инн,E=мыло,C=RU,ST=78 г. Санкт-Петербург,L=Санкт-Петербург,O=название орг,OU=отдел,CN=имя,STREET=адрес и вот тут проблема(ниже опишу),GIVENNAME=Иван Иваныч,SURNAME=Иванов";

В описании методов написано, что порядок будет строго такой, в каком встретились в строке:

 getOIDs
    return a vector of the oids in the name, in the order they were found.
getValues
    return a vector of the values found in the name, in the order they were found. 

Со словарём:

public static Dictionary<string, string> SubjectFriendlyInfo(this X509Name subject)
{
    var result = new Dictionary<string, string>();
    var oids = subject.GetOidList();
    var vals = subject.GetValueList();
    var size = oids.Count;
    for (int i = 0; i < size; i++)
    {
        result.Add(oids[i].ToString(), vals[i].ToString());
    }
    return result;
}
READ ALSO
Запуск jar с помощью C#

Запуск jar с помощью C#

Всем доброго времени сутокДолго ломаю голову (я в шарпах не спец), почему это не работает

103
Как изменить цвет фрейма?

Как изменить цвет фрейма?

Хочу изменить цвет фрейма/рамки у формыБольшая кастомизация не требуется и убирать рамку и делать свою тоже не нужно

134
Кастомный UI для видеоплеера(MpvPlayerUI.NET) на WPF

Кастомный UI для видеоплеера(MpvPlayerUI.NET) на WPF

В общем на GitGub нашел библиотеку MpvPlayerUINET https://github

101
Обратная транслитерация

Обратная транслитерация

Пишу транслитератор, а точнее, пытаюсь уже обработанное слово перевести на русский язык

91