Рассмотрим сертификаты электронной подписи через призму стандарта ASN.1

Любой сертификат цифровой подписи или любой документ представляет собой данные в виде байт, массива байт. Нам необходимо знать хэш алгоритм, необходимо знать издателя сертификата, публичный /закрытый ключ, цепочку сертификатов, срок действия и тд. Сертификаты определяются по стандарту X.509, в системе хранятся в виде массива байт по стандарту ASN.1, что соответствует TLV структуре.
У каждого сертификата есть один из важных параметров : OID, Object identifier. Например, OID хеш алгоритма Sha256 в человеческом виде будет (1.2.840.113549.2.9), в Hex формате 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09.
Возьмем публичный ключ, декодируем его из base 64 в byte массив, размер массива будет равен 162 байта. Пример:
30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 81 8D 00 30 81 89 02 81 81 00 C2 AC 3D E3 D3 43 2C 88 4D 0C 7C 4C 3D AC 14 95 20 A6 45 11 B6 D3 BC 90….
Как мы уже знаем, 30 — секвенция, значит это не примитивный тип, после размера будет хранится ссылка на следующий блок информации. 81 размер, но ссылка, что следующий блок больше 0x80, но меньше 0х100. в 10 виде это 159 меньше чем 256. Проваливаемся дальше. Нам важно найти 0х06 идентификатор с OID. Кажется мы его нашли 06 09 2A 86 48 86 F7 0D 01 01 01. Это алгоритм 1 2 840 113549 1 1 11 т е sha256WithRSAEncryption. Дальше ищем RSA параметры с тегом 0х02 или 0x03 (бит стринг или целочисленное значение). d — частная экспонтента, dp, dq, exponent, modulus, inverseq, p, q. Экспортируем это все в структуру параметров. В публичном ключе нам важны два параметра modulus и exponent. В закрытом ключе нужны все параметры (поскольку это контейнер с ссылкой на все выпущенные публичные сертификаты). А дальше работаем на уровне Cryptoapi или на уровне CLI С#, JRM.