Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.133.119.66] |
|
Сообщ.
#1
,
|
|
|
Добрый день. Возникла у меня такая задача: на входе строка с данными об издателе сертификата. Нужно получить массив байт в формате ASN.1. Все бы ничего, но: строка приходит в следующем виде:
issuer:CN="Тестовый УЦ ООО \"КРИПТО-ПРО\"", O="ООО \"КРИПТО-ПРО\"", C=RU, EMAILADDRESS=info@cryptopro.ru, L=Москва, ST=77 г. Москва, STREET="ул. Сущёвский вал, д. 18", OID.1.2.643.3.131.1.1=#120C303037373137313037393931, OID.1.2.643.100.1=#120D31303337373030303835343434 Соответственно мы видим Х509 строку и две строки с OID'ами. Ага, что делать? 1) Парсим строку. 2) Перегоняем в ASN.1 вызовом CertStrToNameW/*и ударом в бубен*/ #include <cstdio> #include <cstdlib> #include <iostream> #include <string> #include <wtypes.h> #include <wincrypt.h> #include <fstream> #pragma comment(lib, "crypt32.lib") #include <Windows.h> #include <vector> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define MY_STRING_TYPE (CERT_SIMPLE_NAME_STR) using ByteArray = std::vector<uint8_t>; static std::vector<uint8_t> read_file(const std::string& path) { std::ifstream file(path, std::ifstream::binary); if (!file) throw std::runtime_error("Couldn't open file: " + path); file.seekg(0, std::ios::end); std::vector<uint8_t> data(static_cast<size_t>(file.tellg())); file.seekg(0, std::ios::beg); file.read(reinterpret_cast<char*>(data.data()), data.size()); if (!file) throw std::runtime_error("Couldn't read file: " + path); file.close(); return data; }// read_file static ByteArray wstring2asn1(LPCWSTR pszString, int str_type) { ByteArray result; DWORD cbSize; CERT_NAME_BLOB blobEncodedIssuerName; if (!(CertStrToNameW( MY_ENCODING_TYPE, pszString, str_type, NULL, NULL, &cbSize, NULL))) { std::cout << "\nCould not get the length of the BLOB."; return result; } if (!(blobEncodedIssuerName.pbData = (LPBYTE)malloc(cbSize))) { std::cout << "\nMemory Allocation for the BLOB failed."; return result; } blobEncodedIssuerName.cbData = cbSize; if (!(CertStrToNameW( MY_ENCODING_TYPE | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, pszString, str_type, NULL, blobEncodedIssuerName.pbData, &blobEncodedIssuerName.cbData, NULL))) { std::cout << "\nCould not write the blob."; return result; } return ByteArray(blobEncodedIssuerName.pbData, blobEncodedIssuerName.pbData + blobEncodedIssuerName.cbData); }// wstring2asn1 int main(int argc, char* argv[]) { LPCWSTR oid1 = L"OID.1.2.643.3.131.1.1=#120C303037373137313037393931"; LPCWSTR oid2 = L"OID.1.2.643.100.1=#120D31303337373030303835343434"; LPCWSTR issuer = L"CN = \"Тестовый УЦ ООО КРИПТО-ПРО\", O = ООО КРИПТО-ПРО, C = RU, E = info@cryptopro.ru, L = Москва, ST = 77 г.Москва, STREET=\"ул.Сущёвский вал, д. 18\""; ByteArray result; auto b_issuer = wstring2asn1(issuer, CERT_X500_NAME_STR); auto b_oid1 = wstring2asn1(oid1, CERT_OID_NAME_STR); auto b_oid2 = wstring2asn1(oid2, CERT_OID_NAME_STR); result.insert(result.end(), b_issuer.begin(), b_issuer.end()); result.insert(result.end(), b_oid1.begin(), b_oid1.end()); result.insert(result.end(), b_oid2.begin(), b_oid2.end()); CERT_ISSUER_SERIAL_NUMBER cert_issuer_serial_number; auto serial_orig = read_file("C:\\test\\serial.txt");// здесь оригинальный серийник cert_issuer_serial_number.Issuer.pbData = result.data(); cert_issuer_serial_number.Issuer.cbData = static_cast<DWORD>(result.size()); cert_issuer_serial_number.SerialNumber.pbData = const_cast<BYTE*>(serial_orig.data()); cert_issuer_serial_number.SerialNumber.cbData = static_cast<DWORD>(serial_orig.size()); CERT_ID cert_id; cert_id.dwIdChoice = 1; cert_id.IssuerSerialNumber = cert_issuer_serial_number; HCERTSTORE store_handle; // Открываем хранилище сертификатов if (!(store_handle = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY"))) { std::cout << "cert not found"; } PCCERT_CONTEXT pCertCtx = CertFindCertificateInStore( store_handle, MY_ENCODING_TYPE, 0, CERT_FIND_CERT_ID, &cert_id, nullptr); if (!pCertCtx) { std::cout << "cert not found\n"; system("pause"); return 0; } std::cout << "cert found\n"; system("pause"); return 0; } |
Сообщ.
#2
,
|
|
|
Цитата kotmatroskin55 @ Строки нужно объединить, но объединить так, чтобы при этом изменился (правильно пересчитался) заголовок сообщения Нужны критерии изменения/правильного пересчета заголовка сообщения. |
Сообщ.
#3
,
|
|
|
Цитата JoeUser @ Нужны критерии изменения/правильного пересчета заголовка сообщения. Знал бы прикуп - жил бы в Сочи А если серьезно, то первая строка это SEQUENCE (7 elem) SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component) BMPString Тестовый УЦ ООО КРИПТО-ПРО SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component) BMPString ООО КРИПТО-ПРО SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component) PrintableString RU SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.840.113549.1.9.1 emailAddress (PKCS #9. Deprecated, use an altName extension instead) IA5String info@cryptopro.ru SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.7 localityName (X.520 DN component) BMPString Москва SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.8 stateOrProvinceName (X.520 DN component) BMPString 77 г.Москва SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.9 streetAddress (X.520 DN component) BMPString ул.Сущёвский вал, д. 18 вторая SEQUENCE (1 elem) SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.643.3.131.1.1 Offset: 6 Length: 2+8 Value: 1.2.643.3.131.1.1 OCTET STRING (1 elem) NumericString 007717107991 третья SEQUENCE (1 elem) SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.643.100.1 OCTET STRING (1 elem) NumericString 1037700085444 А должно получиться SEQUENCE (9 elem) SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.643.100.1 NumericString 1037700085444 SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.643.3.131.1.1 NumericString 007717107991 SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.9 streetAddress (X.520 DN component) BMPString ул. Сущёвский вал, д. 18 SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.8 stateOrProvinceName (X.520 DN component) BMPString 77 г. Москва SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.7 localityName (X.520 DN component) BMPString Москва SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 1.2.840.113549.1.9.1 emailAddress (PKCS #9. Deprecated, use an altName extension instead) IA5String info@cryptopro.ru SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.6 countryName (X.520 DN component) PrintableString RU SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.10 organizationName (X.520 DN component) Offset: 226 Length: 2+3 Value: 2.5.4.10 organizationName X.520 DN component BMPString ООО "КРИПТО-ПРО" SET (1 elem) SEQUENCE (2 elem) OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component) BMPString Тестовый УЦ ООО "КРИПТО-ПРО" более-менее вменяемый ман |
Сообщ.
#4
,
|
|
|
Проблема оказалась совсем не там, где ее искали. CertStrToNameW не хочет работать с кавычками. Точнее в документации сказано:
Цитата . Но видимо я чего-то недопонял. Quotation marks ("") are supported. A quotation can be included in a quoted value by using two sets of quotation marks, for example, CN="User ""one""". |