17.04.2003 12:56:11Создание цифровой подписи и подписывание ей моих сообщений Ответов: 16
Levitov Valentin
Здравствуйте, уважаемые коллеги. Я уже весь замучился, помогите, плз...
Передо мной стоит задача. Есть некий административный узел, на котором создаётся, скажем, программа. Эта программа должна быть подписана уникальной подписью администратора, которая должна создаваться по его желанию(лучше, чтобы это был Self Signed Сертификат), закодирована(желательно) и отправлена на удалённый
узел по Email. На этом удалённом узле должен храниться список администраторов(что это за список - сертификаты, или ещё что - я не знаю). Там подпись должна быть верифицирована, и, в случае успеха, программа выполняется...
Всё это должно делаться програмно.
Трудности следующие:
Кое-как мне удалось создать SelfSigned сертификт - с помощью программы csptest - сертификат создался, а к нему - какой-то файл с каким-то публичным ключём. Как теперь использовать этот сертификат с этим ключём мне абсолютно не понятно. Насколько я понимаю, чтобы подписать мой пакет с помощью этого сертификата, нужен некий приватный ключ, который будет храниться на машине администратора, а с помощью публичного ключа - верифицировать, что сообщение пришло именно от этого администратора на удалённой машине. Но - увы - приватный ключ не создаётся... Что же мне делать? Про мыло и верёвку я уже думал...
Командная строка (при создании сертификата):
-makecert CN=SuperAdmin -s md5 -m 1 -ca 1 -u 8 -ex "c:\Certificates\CertificatM.cer" "d:\Certificates\CertificatM.pub" 111
Последовательность действий при этом примерно следующая:
...
bResult = CertStrToName(X509_ASN_ENCODING,SuperAdmin,CERT_X500_NAME_STR,NULL,(LPBYTE)pbNameBlob,&dwSize,NULL);//Получили имя
....
HCRYPTPROV hTemp;
/* Create Temporary Provider*/
bResult = CryptAcquireContext(&hTemp,"Temp000",MS_DEF_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET);
...
/* Place random data in Uuid*/
/* Could have used UuidCreate but it is not supported*/
/* under Win9x.*/
bResult = CryptGenRandom(hTemp, sizeof(Uuid), (LPBYTE)&Uuid);
...
/* convert random uuid to a string, we will use it as a container*/
Status = UuidToString(&Uuid, (unsigned char **)&szContainer);
...
/* Generate Private/Public key pair*/
bResult = CryptGenKey(hProv, dwKeyType/*=1*/, CRYPT_EXPORTABLE+(wBits<<16), &hPubKey);
//Здесь-то видимо, и происходит генерация пары ключей...
...
/* Create Random Serial Number*/
bResult = CryptGenRandom(hProv, 8, SerialNumber);
...
/* Get Public Key Info*/
bResult = CryptExportPublicKeyInfo(hProv, dwKeyType/*=1*/,X509_ASN_ENCODING,PublicKeyInfo, &dwSize);
...
/* Create Hash*/
bResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
...
/* Hash Public Key Info*/
bResult = CryptHashData(hHash, (LPBYTE)PublicKeyInfo, dwSize, 0);
...
/* Get Hash of Public Key Info*/
bResult = CryptGetHashParam(hHash, HP_HASHVAL, pbKeyIdentifier, &dwSize, 0);
...
/* Get Subject Key Identifier Extension*/
bResult = CryptEncodeObject(ENCODING,
szOID_SUBJECT_KEY_IDENTIFIER,
(LPVOID)&CertKeyIdentifier,
SubjectKeyIdentifier, &dwSize);

...
/* Get Key Usage Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_KEY_USAGE,
(LPVOID)&KeyUsage,
pbKeyUsage, &dwSize);
...
/* Get Enhanced Key Usage Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_ENHANCED_KEY_USAGE,
(LPVOID)&CertEnhKeyUsage,
pbEnhKeyUsage, &dwSize);
...
/* Get Basic Constraints Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_BASIC_CONSTRAINTS2,
(LPVOID)&BasicConstraints,
pbBasicConstraints, &dwSize);
...
/* Get Authority Key Id blob*/
bResult = CryptEncodeObject(ENCODING,
X509_AUTHORITY_KEY_ID,
(LPVOID)&AuthorityKeyId,
pbAuthorityKeyId, &dwSize);
...
/* Sign and Encode certificate*/
bResult = CryptSignAndEncodeCertificate(hProv, dwKeyType,
X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
(LPVOID)&CertInfo,
&(CertInfo.SignatureAlgorithm),
NULL, bpEncodedCert, &dwSize);
//Получили сертификат, видимо...
...
/* Write encoded Certificate to file*/
bResult = WriteFile(hCertFile, (LPVOID)bpEncodedCert, dwSize, &dwWritten, NULL);
//Сохранили сертификат в файле...
...
/* Create hash*/
bResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
/* Hash password*/
bResult = CryptHashData(hHash, (LPBYTE)szPassword/*=111*/, strlen(szPassword), 0);
/* Derive Session Key from hash*/
bResult = CryptDeriveKey(hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &hSessionKey);
//Получили сеансовый ключ, типа...
...
/* Get exported key blob*/
bResult = CryptExportKey(hPubKey, hSessionKey, PRIVATEKEYBLOB,
0, pbExportedKey, &dwSize);
...
/* Write exported key to file*/
bResult = WriteFile(hKeyFile, (LPVOID)pbExportedKey, dwSize, &dwWritten, NULL);
//Сохранили публичный, видимо, ключ в файле

/* Create new crypto context*/
bResult = CryptAcquireContext(&hProv,
szContainer,
szProvider,
dwProviderType,
CRYPT_DELETEKEYSET | dwAcquireFlags);
//Это ещё зачем - непонятно...


В итоге - получается два файла - сертификата и публичного ключа... Объясните мне, дураку, можно ли, и если можно, то как же с их помощью подписывать программу(вообще-то - cab-файлы), а затем - верифицировать?
 
Ответы:
17.04.2003 16:38:18Uri
А может Вы не с того конца подошли к этой проблеме :-))
Есть микрософтовская технология Authenticode, которая как раз предназначена для таких задач, в том числе подписывания и проверке кабинетных файлов.
Одним из элементов технологии является использование службы certification authority (CA). А программулька MakeCert - это создание ТЕСТОВЫХ сертификатов без использования СА.
Поэтому:
1. Сгенерите ключи и получите тестовый сертификат на нашем тестовом СА http://www.cryptopro.ru/certsrv/. В назначении сертификата укажите "другой" и код 1.3.6.1.5.5.7.3.3. Это OID для подписывания кода.
2. С помощью SignCode.exe подпишите кабинетный файл.
3. С помощью ChkTrust.exe проверяйте подписи

Подробнее читайте в MSDN

И все!!! Зачем писать свои коды?!
17.04.2003 17:03:54Levitov Valentin
Нет, так не пойдёт. Этими программульками я могу пользоваться только при тестировании. Дело всё в том, что весь процесс происходит в автоматическом режиме: Админ создаёт cab, подписывает его(выбрав из списка уже подготовленных подписей) и отправляет удалённому узлу определённым образом отформатированное сообщение, содержащее в том числе и этот cab. Всё. Далее в дело вступает автоматика - на удалённом узле сидит малоквалифицированный юзер, которому нет дела до того, чего там пришло. Он играет в карты. Вместо него работает обработчик сообщения, который принимает это сообщение(это всё реализовано), и далее - должен ПРОВЕРИТЬ сертификат, при этом он не должен моргать глазами, вываливать тревожные MessageBox-ы, пугая спящего оператора... Он всё должен делать сам, а именно:
1) Проверить подпись.
2) Если подпись разрешённая(список разрешённых подписей заполняется при установке софта), распаковать cab, и выполнить хранящийся в нём сценарий. При этом никакие чужие сертификаты и левые программульки ни мне, ни заказчику, ни продолжающему спать оператору удалённого узла не нужны.
При этом всё должно работать на ОС Windows, начиная с Win95(с 5-м IE).
Мне удалось создать SelfSigned сертификат и пару ключей к нему, а также - подписать сообщение(cab). Теперь рою носом и думаю - что же должно быть на удалённом узле, чтобы верифицировать пришедший пакет? Что? Файл сертификата? Public Key? Private Key???!!! Или оба? Или все трое??? Или ещё что???? У меня уже голова пирамидальная от долгого долбления в угол а реального результата пока нету... Может, уволиться и уйти в лётчики...
17.04.2003 17:04:08Levitov Valentin
Нет, так не пойдёт. Этими программульками я могу пользоваться только при тестировании. Дело всё в том, что весь процесс происходит в автоматическом режиме: Админ создаёт cab, подписывает его(выбрав из списка уже подготовленных подписей) и отправляет удалённому узлу определённым образом отформатированное сообщение, содержащее в том числе и этот cab. Всё. Далее в дело вступает автоматика - на удалённом узле сидит малоквалифицированный юзер, которому нет дела до того, чего там пришло. Он играет в карты. Вместо него работает обработчик сообщения, который принимает это сообщение(это всё реализовано), и далее - должен ПРОВЕРИТЬ сертификат, при этом он не должен моргать глазами, вываливать тревожные MessageBox-ы, пугая спящего оператора... Он всё должен делать сам, а именно:
1) Проверить подпись.
2) Если подпись разрешённая(список разрешённых подписей заполняется при установке софта), распаковать cab, и выполнить хранящийся в нём сценарий. При этом никакие чужие сертификаты и левые программульки ни мне, ни заказчику, ни продолжающему спать оператору удалённого узла не нужны.
При этом всё должно работать на ОС Windows, начиная с Win95(с 5-м IE).
Мне удалось создать SelfSigned сертификат и пару ключей к нему, а также - подписать сообщение(cab). Теперь рою носом и думаю - что же должно быть на удалённом узле, чтобы верифицировать пришедший пакет? Что? Файл сертификата? Public Key? Private Key???!!! Или оба? Или все трое??? Или ещё что???? У меня уже голова пирамидальная от долгого долбления в угол а реального результата пока нету... Может, уволиться и уйти в лётчики...
17.04.2003 17:04:37Levitov
Нет, так не пойдёт. Этими программульками я могу пользоваться только при тестировании. Дело всё в том, что весь процесс происходит в автоматическом режиме: Админ создаёт cab, подписывает его(выбрав из списка уже подготовленных подписей) и отправляет удалённому узлу определённым образом отформатированное сообщение, содержащее в том числе и этот cab. Всё. Далее в дело вступает автоматика - на удалённом узле сидит малоквалифицированный юзер, которому нет дела до того, чего там пришло. Он играет в карты. Вместо него работает обработчик сообщения, который принимает это сообщение(это всё реализовано), и далее - должен ПРОВЕРИТЬ сертификат, при этом он не должен моргать глазами, вываливать тревожные MessageBox-ы, пугая спящего оператора... Он всё должен делать сам, а именно:
1) Проверить подпись.
2) Если подпись разрешённая(список разрешённых подписей заполняется при установке софта), распаковать cab, и выполнить хранящийся в нём сценарий. При этом никакие чужие сертификаты и левые программульки ни мне, ни заказчику, ни продолжающему спать оператору удалённого узла не нужны.
При этом всё должно работать на ОС Windows, начиная с Win95(с 5-м IE).
Мне удалось создать SelfSigned сертификат и пару ключей к нему, а также - подписать сообщение(cab). Теперь рою носом и думаю - что же должно быть на удалённом узле, чтобы верифицировать пришедший пакет? Что? Файл сертификата? Public Key? Private Key???!!! Или оба? Или все трое??? Или ещё что???? У меня уже голова пирамидальная от долгого долбления в угол а реального результата пока нету... Может, уволиться и уйти в лётчики...
17.04.2003 17:13:01Levitov Valentin
PS
Прошу прощения за множественную передачу моих сообщений - вываливалось окно, мол, "Сервер вернул ошибочный результат...", и я подумал, что сообщение не отправляется.
17.04.2003 18:36:16Uri
Ну тогда ой! :-)
При проверке нужен сертификат. Он содержит открытый ключ. Передайте его после формирования на комп игрока в карты. Закрытый ключ не передается, он только у отправителя. Понятно, что ключи и сертификат надо делать один раз и использовать, пока не наступит период плановой смены ключей.
Один не понятный вопрос: "Админ создаёт cab, подписывает его(выбрав из списка уже подготовленных подписей)" Это наврное опечатка? Подпись нельзя заранее подготовить. ;-)
И вообще, пользуйтесь тогда простым PKCS#7 с помощью CAPICOM или высокоуровневых функций из CryptoAPI. И не парьтесь со всякими там MakeCert. Для генерации ключей и сертификатов админу воспользуйтесь службой CA из Windows 2000 Server. Зачем тогда такие сложности с низкоуровневыми функциями?! Хотя... есть любители и ассемблера для работы с базами данных...
18.04.2003 10:07:00Левитов Валентин
Спасибо за реальный ответ. Обнаружил сеёчас ошибку в своём первом сообщении. Для создания сертификата я пользовался не програмкой MakeCert, а скачанной с этого (уже уважаемого мною) сайта программой csptest.exe. Насчёт создания сертификатов на Win2000 Server - не пойдёт по двум причинам:
1) Админ должен сам создавать свои сертификаты, поскольку априоре в задаче стоит условие, что он не доверяет никому, в том числе - и мне.
2) Создавать он их должен мочь :-))) на Win9x - дополнительным условием может стать установка любого Explorer-а, но никак не операционной системы.
Т.е., сертификаты, и пары ключей к ним должны создаваться в рамках моего софта.
CAPICOM я попробовал первым делом. В общем-то - неплохо, но во-первых - не создаёт сертификаты, во-вторых - неизвестно, как отнесётся руководство к использованию такого софта. Согласитесь - одно дело приаттачивать к своему продукту свободно распространяемый официальный mdac, и другое дело - какой-то CAPICOM.dll.
Задача ведь тривиальная в общем-то...
Есть два Actor-а - админ и оператор.
У оператора есть три штучки - приватный и публичный ключи и сообщение... Насколько я понимаю - приватным он подписывает своё сообщение, и, отправив перед этим заранее и один раз публичный ключ оператору, отправляет своё подписанное сообщение. На стороне оператора с помощью публичного ключа, это составное сообщение верифицируется(либо нет). И всё. На словах у меня всё просто, однако сегодня начался уже четвёртый день моих поисков, как это нормально и правильно сделать, чтобы всем было хорошо и удобно... И война чтобы кончилась...
P.S.
Насчёт заранее подготовленных подписей я, конечно, перегнул. Я имел ввиду заранее подготовленные сертификаты вместе с их парами ключей.
18.04.2003 10:26:17Uri
Беда с самоподписанными сертификатами в том, что недоверчивый админ им доверяет, т.к. сам их делал, а вот оператор, играющий в карты, и получивший некий сертификат, никем не заверенный, должен ему будет поверить и считать, что это сертификат администратора. Что-то он уж очень доверчивый! Да и игрок к тому же... ;-)
18.04.2003 10:44:06Левитов Валентин
Как я себе это представляю (конечно, могу быть не прав) - сертификаты устанавливаются на машине оператора админом в момент установки программы, т.е. админ делает свой сертификат, оставляет приватный его ключ на своей машине, собирает вещички, кладёт в чемодан дискетку с сертификатом, публичным ключём и программой. Едет в Караганду, ставит там программу, и когда она запрашивает список сертификатов, которым можно доверять, достаёт дискетку и устанавливает свой сертификат (и публичный ключ, если надо - честно говоря - не знаю). Всё. Далее никакой установки сертификатов не производится (даже если они пачками летят на компьютер бедного оператора - в гробу перевернётся). Потом админ возвращается из Караганды в Мухосранск, где родилась его бабушка, и отправляет пачками свои сценарии, подписанные его сертификатом с приватным ключём в Караганду. А там они верифицируются, либо нет.
Вот примерно такую схему мне и нужно реализовать.
Поскольку я абсолютно некомпетентен в делах сертификации (4 дня пустого долбления тупоголовой башкой ничего не меняют), то хотел бы спросить:
1) Могут ли быть дыры при такой реализации?
2) Возможна ли такая реализация?
3) Если ответ на второй вопрос - положительный, то как??? (здесь - по сценарию - истерика и слёзы)...
18.04.2003 10:59:19Uri
Минусы:
1. Админ потерял свой приватный ключ. Что делать? Как оповестить об этом оператора? Как продолжить работы не ездя заново из Мухосранска в Караганду?
2. Как уберечь сертификат админа, установленный в компьютер оператора от подмены? Ведь есть доступ к его компу других лиц. А среди них может быть и шутник и злоумышленник...
3. Админ уже который год пользуется своим ключом... Он начинает сомневаться, что за столь долгий срок с его ключа могли снять копию... Нужно осуществить смену ключа. И что, для этого опять тратить денюжки и время в богом забытую Караганду? Кайфа нет т.к. водка там теплая, женщины страшные...
Что делать? Этот вопрос задавали еще классики!!! И они же придумали ответ в виде PKI :-) Но Левитов Валентин решил опять пройти тяжелым путем поиска истины, спотыкаясь по кочкам :-) Не обижайтесь, шутка...
Все эти проблемы исчезнут, если сделать некий СА, который будет выдавать сертификаты открытого ключа подписи админу и периодически издавать список отозванных сертификатов (CRL).
При этом потребуется только один раз отвезти в Караганду сертификат открытого ключа СА.
Админ будет подписывать сценарий своим приватным ключом и прикладывать к каждой подписи свой сертификат.
А оператор на каждой подписи будет проверять: кем издан сертификат подписи админа и нет ли его в CRL.
Просто до безумия!!! :-)
18.04.2003 11:08:29Левитов Валентин
Ок. Каким образом осуществляется "...оператор на каждой подписи будет проверять: кем издан сертификат подписи админа..." - это при каждом получении подписанного сообщения запрашивать по интернету - действительно ли сообщение подписано админом? или я опять чего-то не понял?
18.04.2003 11:21:57Uri
Нет конечно!
1. Посмотреть кем издан сертификат подписи. Если издан сертификатом СА, котрый ему привезли, то проверка успешна.
2. Если CommonName из SubjectDN содержит слово "Проигравшийся админ" то проверка прошла успешна
3. Берет локальный CRL и проверяет, нет ли сертификата подписи в списке. Если нет, то проверка прошла успешно.

Если все проверки успешны то это сертификат администратора.
18.04.2003 11:46:35Левитов
Все эти пункты будут выполняться автоматически (без участия пьяного оператора)?
И если да, то что надо делать? Как я узнал, в головной компании админа есть служба, которая издаёт сертификаты.
То есть - он берёт сертификат головной компании, отвозит его в Караганду и устанавливает его там.
Затем - получает сертификат, подписанный Супер-Админом из головной компании на своё имя, подписывает с его помощью свои сценарии, и отправляет подписанное - вместе со своим сертификатом - в Караганду по почте?
Если да, то где хранятся ключи (приватный и публичный)...
Нет, не так вопрос ставлю.
Не могли бы Вы объяснить мне предназначение приватного ключа, публичного ключа и сертификата? Что нужно оператору для верификации - нужен ли ему приватный ключ? Как я понимаю - приватным можно подписать, а публичным - верифицировать - это так?
18.04.2003 11:50:26Юрий Маслов
Прошу прощения, но наша беседа уже начинает походить на учебный курс, а это не входит в задачи этого форума.
Позвоните мне в офис (933-1168) и я Вам быстро отвечу на вопросы. К сожалению, у меня мало времени.
18.04.2003 11:59:07Левитов
Спосибо большое за Ваше терпение - я просто обнаглел и обленился. Кое-что мне стало понятно, появились определённые просветлённые пятна в головной коробке, хотя воспалённая больная фантазия продолжает выталкивать из своих недр дурные мысли. Если уж совсем будет невмоготу - позвоню...
18.04.2003 12:39:43Uri
Главное помнить - сертификат содержит публичный ключ, поэтому публичный ключ никуда отправлять не нуно! :-)