Возможно, будет полезно разработчикам, ведь в спецификации формата SIS-файла про это не сказано ни слова:) В данной статье предполагается, что разработчик уже изучил структуру SIS-файла и примерно представляет, что и как)) Итак, наиболее часто встречающиеся сертификаты для подписи имеют тип DSA и RSA. Соответственно, они имеют свои тонкости при подписи. Для подписи необходимы файлы *.key и *.cer Структура файла *.key:
-----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,220EF1BCF6603EAF
*данные, зашифрованные по алгаритму BASE64
-----END DSA PRIVATE KEY----- Где: "-----BEGIN DSA PRIVATE KEY-----" и "-----END DSA PRIVATE KEY-----" - обозначают начало и конец сертификата "Proc-Type: 4,ENCRYPTED" - может отсутствовать. Если эта строчка есть, то файл ключа зашифрован. "DEK-Info: DES-EDE3-CBC,220EF1BCF6603EAF" - есть, только если файл ключа зашифрован. "DES-EDE3-CBC" - означает, что ключ зашифрован по алгаритму Triple DES, EDE3 - шифровка-расшифровка-шифровка с тремя разными ключами. CBC - режим сцепления блоков (СВС — Cipher Block Chaining), 220EF1BCF6603EAF - это своеобразный ключ к расшифровке в режиме CBC. Подробнее читайте документации по алгаритмам DES и 3DES. Итак, мы расшифровали ключ, либо он уже был расшифрован. Ключ записан в формате ASN.1 в виде нескольких чисел типа Integer. Для подписи нам понадобятся числа под номерами: Алгаритм DSA: 1 (p), 2 (q), 3 (g), 5 (x) Алгаритм RSA: 1 (n), 3 (d)
Структура файла *.cer: Файл аналогичен файлу *.key, только он не шифруется и хранятся в нём данные о компании, которая подписала сертификат, кто заказывал подпись, а так же необходимые ключи для проверки подлинности подписи и указание типа сертификата. Ну, и кое-какие данные, например свой собственный хэш, версия сертификата. Этот файл после расшифровки просто вписывается в поле SISController.SISSignatureCertificeteChain.SISCertificateChain.SISBlob
Общая схема подписи: - Сначала мы формируем контроллер, который нам необходимо подписать. Причём, нам не нужны: номер поля (у контроллера оно равно 13) и длина поля, а так же: в подписи не участвует поле SISDataIndex, так как оно может меняться при встраивании одного SIS-файла в другой.
- Теперь по сформированным данным мы считаем хэш по алгаритму SHA-1. Этот хэш мы и будем подписывать (RSA - немного сложнее, но об этом далее)
- По алгаритмам RSA или DSA получаем сигнатуру подписи:
DSA - будут числа r и s (они записываются опять же в формате ASN.1) RSA - только одно число s (будет просто записано) - Сигнатура вписывается в поле SISController.SISSignatureCertificeteChain.SISArray(of SISSignature).SISBlob
Зачем массив, я не знаю... Всегда пишу в нулевой элемент массива и всё работает. - В поле SISController.SISSignatureCertificeteChain.SISArray(of SISSignature).SISSignatureAlgorithm.SISString вписываем строку:
"1.2.840.113549.1.1.5" - в случа SHA-1 with RSA signature "1.2.840.10040.4.3" - в случае SHA-1 with DSA signature - Всё! Подпись завершена.
В случае RSA подписывается не сам хэш, а его модификация:
m:=pkcs1Digest(m,nlen); Сами функции: function pkcs1Pad(data:string; lMod:integer):string; var lenPad,i:integer; buf:string; begin lenPad:=lMod-3-length(data) div 2; for i:=1 to lenPad do begin buf:=buf+'FF' end; result:='01'+buf+'00'+data; end;
function pkcs1Digest(HASH:string; lMod:integer):string; const ID_SHA1 = '3021300906052b0e03021a05000414'; begin result:=pkcs1Pad(ID_SHA1+HASH,lMod); end;
Где: lMod - длина числа n в битах, HASH - хэш контроллера в виде HEX-строки. На выходе получается опять же HEX-строка. Внимание! В данном случае использовался алгаритм подписи по стандарту PKCS #1 v2.1. Возможно использование другого стандарта! В общем, на этом всё! Надеюсь, вам всё понятно;) Если что, пишите на почту sevastyanov_ks@mail.ru, постараюсь пояснить непонятные моменты!
|