powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Cryptoapi не импортируется public key
2 сообщений из 2, страница 1 из 1
Cryptoapi не импортируется public key
    #38453872
fetterless
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В общем, есть функция подписи текста и верификации. Первая работает, а вот вторая нет, заканчиваясь выводом сообщения "Public key import failed". Помогите найти ошибку.

Функция подписи.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
void MainWindow::on_signButton_clicked()
{
    ui->logBrowser->clear();

    //-------------------------------------------------------------------
    // Declare and initialize variables.

    #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

    HCRYPTPROV hProv;
    BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";
    DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    BYTE *pbKeyBlob;
    BYTE *pbSignature;
    DWORD dwSigLen;
    DWORD dwBlobLen;

    //-------------------------------------------------------------------
    // Acquire a cryptographic provider context handle.

    if(CryptAcquireContext(
       &hProv,
       L"test1", //container name
       NULL,
       PROV_RSA_FULL,   //provider type
       CRYPT_NEWKEYSET)) // new container
    {
         ui->logBrowser->append("CSP context acquired.");
    }
    else
    {
         HandleError("Error during CryptAcquireContext.");
         return;
    }
    //-------------------------------------------------------------------
    // Get the public at signature key. This is the public key
    // that will be used by the receiver of the hash to verify
    // the signature. In situations where the receiver could obtain the
    // sender's public key from a certificate, this step would not be
    // needed.

    CryptGenKey(hProv,
                CALG_RSA_SIGN,
                CRYPT_EXPORTABLE,
                &hKey);

    if(CryptGetUserKey(
       hProv,
       AT_SIGNATURE,
       &hKey))
    {
        ui->logBrowser->append("The signature key has been acquired.");
    }
    else
    {
        HandleError("Error during CryptGetUserKey for signkey.");
        return;
    }


    //-------------------------------------------------------------------
    // Export the public key. Here the public key is exported to a
    // PUBLICKEYBOLB so that the receiver of the signed hash can
    // verify the signature. This BLOB could be written to a file and
    // sent to another user.

    if(CryptExportKey(
       hKey,
       NULL,
       PUBLICKEYBLOB,
       0,
       NULL,
       &dwBlobLen))
    {
        ui->logBrowser->append("Size of the BLOB for the public key determined (" + QString::number(dwBlobLen) + ").");
    }
    else
    {
         HandleError("Error computing BLOB length.");
         return;
    }
    //-------------------------------------------------------------------
    // Allocate memory for the pbKeyBlob.

    if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
    {
        ui->logBrowser->append("Memory has been allocated for the BLOB.");
    }
    else
    {
        HandleError("Out of memory.");
        return;
    }
    //-------------------------------------------------------------------
    // Do the actual exporting into the key BLOB.

    if(CryptExportKey(
       hKey,
       NULL,
       PUBLICKEYBLOB,
       0,
       pbKeyBlob,
       &dwBlobLen))
    {
         ui->logBrowser->append("Contents have been written to the BLOB (pbKeyBlob.bin).");

         ofstream out("pbKeyBlob.bin", std::ofstream::binary);
         out.write(pbKeyBlob, dwBlobLen);
         out.close();
    }
    else
    {
        HandleError("Error during CryptExportKey.");
        return;
    }
    //-------------------------------------------------------------------
    // Create the hash object.

    if(CryptCreateHash(
       hProv,
       CALG_MD5,
       0,
       0,
       &hHash))
    {
         ui->logBrowser->append("Hash object created.");
    }
    else
    {
        HandleError("Error during CryptCreateHash.");
        return;
    }
    //-------------------------------------------------------------------
    // Compute the cryptographic hash of the buffer.

    if(CryptHashData(
       hHash,
       pbBuffer,
       dwBufferLen,
       0))
    {
         ui->logBrowser->append("The data buffer has been hashed.");
    }
    else
    {
         HandleError("Error during CryptHashData.");
         return;
    }
    //-------------------------------------------------------------------
    // Determine the size of the signature and allocate memory.

    dwSigLen= 0;
    if(CryptSignHash(
       hHash,
       AT_SIGNATURE,
       NULL,
       0,
       NULL,
       &dwSigLen))
    {
        ui->logBrowser->append("Signature length " + QString::number(dwSigLen) + " found.");
    }
    else
    {
         HandleError("Error during CryptSignHash.");
         return;
    }
    //-------------------------------------------------------------------
    // Allocate memory for the signature buffer.

    if(pbSignature = (BYTE *)malloc(dwSigLen))
    {
         ui->logBrowser->append("Memory allocated for the signature.");
    }
    else
    {
         HandleError("Out of memory.");
         return;
    }
    //-------------------------------------------------------------------
    // Sign the hash object.

    if(CryptSignHash(
       hHash,
       AT_SIGNATURE,
       NULL,
       0,
       pbSignature,
       &dwSigLen))
    {
         ui->logBrowser->append("pbSignature is the hash signature (pbSignature.bin).");

         ofstream out("pbSignature.bin", std::ofstream::binary);
         out.write(pbSignature, dwSigLen);
         out.close();
    }
    else
    {
         HandleError("Error during CryptSignHash.");
         return;
    }
    //-------------------------------------------------------------------
    // Destroy the hash object.

    if(hHash)
      CryptDestroyHash(hHash);

    ui->logBrowser->append("The hash object has been destroyed.");
    ui->logBrowser->append("<hr><font color = \"green\">The signing is completed successfully.");

    // Free memory to be used to store signature.

    if(pbSignature)
      free(pbSignature);

    //-------------------------------------------------------------------
    // Destroy the hash object.

    if(hHash)
      CryptDestroyHash(hHash);

    //-------------------------------------------------------------------
    // Release the provider handle.

    if(hProv)
       CryptReleaseContext(hProv, 0);
}


Функция верификации.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
void MainWindow::on_verifyButton_clicked()
{
    ui->logBrowser->clear();

    //-------------------------------------------------------------------
    // Declare and initialize variables.

    #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

    HCRYPTPROV hProv;
    BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed."; // будет считываться с файла
    DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
    HCRYPTHASH hHash;
    HCRYPTKEY hPubKey;
    BYTE *pbKeyBlob;
    BYTE *pbSignature; // будет считываться с файла
    DWORD dwSigLen;
    DWORD dwBlobLen;

    //-------------------------------------------------------------------
    // Acquire a cryptographic provider context handle.

    if(CryptAcquireContext(
       &hProv,
       L"test1", //container name
       NULL,
       PROV_RSA_FULL,   //provider type
       NULL)) // new container
    {
         ui->logBrowser->append("CSP context acquired.");
    }
    else
    {
         HandleError("Error during CryptAcquireContext.");
         return;
    }

    //-------------------------------------------------------------------
    // Export the public key. Here the public key is exported to a
    // PUBLICKEYBOLB so that the receiver of the signed hash can
    // verify the signature. This BLOB could be written to a file and
    // sent to another user.

    std::ifstream blobFile ("pbKeyBlob.bin", std::ifstream::binary);
    // get length of file:
    blobFile.seekg (0, blobFile.end);
    dwBlobLen = (unsigned long)blobFile.tellg();
    blobFile.seekg (0, blobFile.beg);

    char *buffer = new char [dwBlobLen];

    // read data as a block:
    blobFile.read (buffer,dwBlobLen);
    blobFile.close();

    ui->logBrowser->append("Size of the BLOB for the public key determined (" + QString::number(dwBlobLen) + ").");

    //-------------------------------------------------------------------
    // Allocate memory for the pbKeyBlob.

    if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
    {
        ui->logBrowser->append("Memory has been allocated for the BLOB.");
        this->charToByte(buffer, pbKeyBlob);
    }
    else
    {
        HandleError("Out of memory.");
        return;
    }


    //-------------------------------------------------------------------
    // Compute the cryptographic hash of the buffer.

    std::ifstream signFile ("pbSignature.bin", std::ifstream::binary);
    // get length of file:
    signFile.seekg (0, signFile.end);
    dwSigLen = (unsigned long)signFile.tellg();
    signFile.seekg (0, signFile.beg);

    buffer = new char [dwSigLen];

    // read data as a block:
    signFile.read (buffer, dwSigLen);
    signFile.close();

    ui->logBrowser->append("Signature length " + QString::number(dwSigLen) + " found.\n");

    //-------------------------------------------------------------------
    // Allocate memory for the signature buffer.

    if(pbSignature = (BYTE *)malloc(dwSigLen))
    {
         ui->logBrowser->append("Memory allocated for the signature.");
         this->charToByte(buffer, pbSignature);
    }
    else
    {
         HandleError("Out of memory.");
         return;
    }



    //-------------------------------------------------------------------
    // Get the public key of the user who created the digital signature
    // and import it into the CSP by using CryptImportKey. This returns
    // a handle to the public key in hPubKey.

    if(CryptImportKey(
       hProv,
       pbKeyBlob,
       dwBlobLen,
       0,
       0,
       &hPubKey))
    {
         ui->logBrowser->append("The key has been imported.");
    }
    else
    {
         HandleError("Public key import failed.");
         return;
    }
    //-------------------------------------------------------------------
    // Create a new hash object.

    if(CryptCreateHash(
       hProv,
       CALG_MD5,
       0,
       0,
       &hHash))
    {
         ui->logBrowser->append("The hash object has been recreated.");
    }
    else
    {
         HandleError("Error during CryptCreateHash.");
         return;
    }
    //-------------------------------------------------------------------
    // Compute the cryptographic hash of the buffer.

    if(CryptHashData(
       hHash,
       pbBuffer,
       dwBufferLen,
       0))
    {
         ui->logBrowser->append("The new hash has been created.");
    }
    else
    {
         HandleError("Error during CryptHashData.");
         return;
    }
    //-------------------------------------------------------------------
    // Validate the digital signature.

    if(CryptVerifySignature(
       hHash,
       pbSignature,
       dwSigLen,
       hPubKey,
       NULL,
       0))
    {
         ui->logBrowser->append("The signature has been verified.");
    }
    else
    {
         ui->logBrowser->append("<font color = \"red\">Signature not validated!</font>");
    }
    //-------------------------------------------------------------------
    // Free memory to be used to store signature.

    if(pbSignature)
      free(pbSignature);

    //-------------------------------------------------------------------
    // Destroy the hash object.

    if(hHash)
      CryptDestroyHash(hHash);

    //-------------------------------------------------------------------
    // Release the provider handle.

    if(hProv)
       CryptReleaseContext(hProv, 0);
}

...
Рейтинг: 0 / 0
Cryptoapi не импортируется public key
    #38454933
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fetterlessВ общем, есть функция подписи текста и верификации. Первая работает, а вот вторая нет...

IMHO. Почему ты думаешь, что первая функция работает?

Честно говоря, я всегда думал, что подпись имеет смысл только когда подписывающийся известен. Нафига ты при создании контента указываешь CRYPT_NEWKEYSET ?

Сгенери (или получи) контейнер для закрытых ключей с нормальным ключем и подписывай/проверяй по нормальному ключу/сертификату.

NOTE: Я пишу (в текущей момент) функцию для работы по ГОСТ, через КРИПТО-ПРО 3.6. Возможно в чистом Windows API все проще. В КриптоПро хранилище в реестре мне заставить работать не удалось, удалось создать контейнер ключей только на сменном носителе (флешке)
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Cryptoapi не импортируется public key
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]