Какова структура открытого ключа подписанной сборки в C#?

Используя этот код для получения байтов открытого ключа...

var pubKey = 
    AppDomain.CurrentDomain.DomainManager.EntryAssembly
        .GetName().GetPublicKey();

Что это за общая структура в начале (первые 32 байта) ключа? Это не ASN.1, и он не может быть переменным. Я могу погуглить и получить повторы.

// 00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 00 24 00 00 52 53 41 31

Это все наоборот или только часть (например, модуль в конце)? 52 53 41 31 — это строка RSA1. Модуль моего ключа составляет 1024 бита, поэтому я искал что-то, описывающее длину. 0x0400 (00 04 BE) будет 1024 (бит), 0x80 будет 128 (байт, 1024/8).

// 00 04 00 00 01 00 01 00

Являются ли последние от 4 до 6 публичным показателем? Большой или маленький порядок байтов? Является ли последний нуль терминатором или разделителем?

Исследования реализации (.NET и Mono) RSAPKCS1SignatureFormatter и RSAPKCS1SignatureDeformatter идут непросто.

Удаленные правки, ответ на собственный вопрос... если кто-то не предложит лучший ответ или не добавит деталей, включая почему.


person TylerY86    schedule 21.02.2015    source источник


Ответы (1)


Я не мог перестать грызть ногти, пытаясь работать в обратном направлении от CALG_RSA_SIGN = 0x00002400, и наткнулся на RSAPUBKEY, затем на PUBLICKEYSTRUC и, наконец, на PublicKeyBlob. Теперь я могу разобрать его формально. Интересно, есть ли уже какая-либо структура в .NET Framework для обработки этого?

https://msdn.microsoft.com/en-us/library/ee442238.aspx

О, эти волшебные числа кажутся знакомыми. Что они имеют в виду...

Это https://msdn.microsoft.com/en-us/library/ms232463.aspx ?

// 00 24 00 00 // 0x00002400 LE // PublicKeyBlob  SigAlgId ALG_ID = CALG_RSA_SIGN 
// 04 80 00 00 // 0x00008004 LE // PublicKeyBlob  HashAlgId ALG_ID = CALG_SHA1
// 94 00 00 00 // 0x00000094 LE // PublicKeyBlob  cbPublicKey dword = 148
// sizeof(PUBLICKEYSTRUC) is 8 + sizeof(RSAPUBKEY) is 12 + sizeof(modulus) is 128 = 148
// 06          // 0x06          // PUBLICKEYSTRUC bType byte = PUBLICKEYBLOB
// 02          // 0x02          // PUBLICKEYSTRUC bVersion byte = CUR_BLOB_VERSION
// 00 00       // 0x0000 LE     // PUBLICKEYSTRUC reserved word = 0
// 00 24 00 00 // 0x00002400 LE // PUBLICKEYSTRUC aiKeyAlg ALG_ID = CALG_RSA_SIGN 
// 52 53 41 31 // 'RSA1'        // RSAPUBKEY magic dword
// 00 04 00 00 // 0x00000400 LE // RSAPUBKEY bitlen dword
// 01 00 01 00 // 0x00010001 LE // RSAPUBKEY pubexp dword
// public modulus reversed follows in (bitlen/8) bytes

Итак, используя эту информацию (не удалось заставить rsaCsp.ImportParameters работать правильно)...

var rsaCsp = new RSACryptoServiceProvider(BitLength);
rsaCsp.FromXmlString(string.Format(
    "<RSAKeyValue><Modulus>{1}</Modulus><Exponent>{0}</Exponent></RSAKeyValue>",
    Convert.ToBase64String(PubExp), Convert.ToBase64String(PubMod)));

Теперь у вас есть действующий rsaCsp для аутентификации по подписи из PK SN вашей сборки.

person TylerY86    schedule 21.02.2015
comment
Еще одно предостережение... PubExp необходимо преобразовать в байты и удалить начальные нулевые байты (обрезать старшие 0 байтов, например, 01 00 01 00 -> 01 00 01 -> AQAB, а не AQABAA==). - person TylerY86; 16.03.2015