Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Error 0x80070002 from CryptUIWizDigitalSign

12 views
Skip to first unread message

leinzing...@googlemail.com

unread,
Apr 10, 2019, 7:47:35 AM4/10/19
to
I try to sign a file remotly on a server but i get the error code 0x80070002 from CryptUIWizDigitalSign and i cant find any documentation about error codes. Can some one help me with this? Do you knwo which error this is and what it means? Any alternative? Im using a hardware token. Here is the code:

#include "stdafx.h"
#include "windows.h"
#include "cryptuiapi.h"
#include "iostream"
#include "string"
#include "Wincrypt.h"
#pragma comment (lib, "cryptui.lib")

const std::wstring ETOKEN_BASE_CRYPT_PROV_NAME = L"eToken Base Cryptographic Provider";

std::string utf16_to_utf8(const std::wstring& str)
{
if (str.empty())
{
return "";
}

auto utf8len = ::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), NULL, 0, NULL, NULL);
if (utf8len == 0)
{
return "";
}

std::string utf8Str;
utf8Str.resize(utf8len);
::WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), &utf8Str[0], utf8Str.size(), NULL, NULL);

return utf8Str;
}

struct CryptProvHandle
{
HCRYPTPROV Handle = NULL;
CryptProvHandle(HCRYPTPROV handle = NULL) : Handle(handle) {}
~CryptProvHandle() { if (Handle) ::CryptReleaseContext(Handle, 0); }
};

HCRYPTPROV token_logon(const std::wstring& containerName, const std::string& tokenPin)
{
CryptProvHandle cryptProv;
if (!::CryptAcquireContext(&cryptProv.Handle, containerName.c_str(), ETOKEN_BASE_CRYPT_PROV_NAME.c_str(), PROV_RSA_FULL, CRYPT_SILENT))
{
std::wcerr << L"CryptAcquireContext failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
return NULL;
}
std::wcerr << L"CryptAcquireContext succeeded" << L"\n";
if (!::CryptSetProvParam(cryptProv.Handle, PP_SIGNATURE_PIN, reinterpret_cast<const BYTE*>(tokenPin.c_str()), 0))
{
std::wcerr << L"CryptSetProvParam failed, error " << std::hex << std::showbase << ::GetLastError() << L"\n";
return NULL;
}
std::wcerr << L"CryptSetProvParam succeeded" << L"\n";
auto result = cryptProv.Handle;
cryptProv.Handle = NULL;
return result;
}

int wmain(int argc, wchar_t** argv)
{
if (argc < 6)
{
std::wcerr << L"usage: signExe.exe <certificate file path> <private key container name> <token PIN> <timestamp URL> <path to file to sign>\n";
return 1;
}

const std::wstring certFile = argv[1];
const std::wstring containerName = argv[2];
const std::wstring tokenPin = argv[3];
const std::wstring timestampUrl = argv[4];
const std::wstring fileToSign = argv[5];

CryptProvHandle cryptProv = token_logon(containerName, utf16_to_utf8(tokenPin));
if (!cryptProv.Handle)
{
return 1;
}

CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO extInfo = {};
extInfo.dwSize = sizeof(extInfo);
extInfo.pszHashAlg = szOID_NIST_sha256; // Use SHA256 instead of default SHA1

CRYPT_KEY_PROV_INFO keyProvInfo = {};
keyProvInfo.pwszContainerName = const_cast<wchar_t*>(containerName.c_str());
keyProvInfo.pwszProvName = const_cast<wchar_t*>(ETOKEN_BASE_CRYPT_PROV_NAME.c_str());
keyProvInfo.dwProvType = PROV_RSA_FULL;

CRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO pvkInfo = {};
pvkInfo.dwSize = sizeof(pvkInfo);
pvkInfo.pwszSigningCertFileName = const_cast<wchar_t*>(certFile.c_str());
pvkInfo.dwPvkChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK_PROV;
pvkInfo.pPvkProvInfo = &keyProvInfo;

CRYPTUI_WIZ_DIGITAL_SIGN_INFO signInfo = {};
signInfo.dwSize = sizeof(signInfo);
signInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE;
signInfo.pwszFileName = fileToSign.c_str();
signInfo.dwSigningCertChoice = CRYPTUI_WIZ_DIGITAL_SIGN_PVK;
signInfo.pSigningCertPvkInfo = &pvkInfo;
signInfo.pwszTimestampURL = timestampUrl.c_str();
signInfo.pSignExtInfo = &extInfo;
//
if (!::CryptUIWizDigitalSign(CRYPTUI_WIZ_NO_UI, NULL, NULL, &signInfo, NULL))
{
std::wcerr << "CryptUIWizDigitalSign failed, error: " << std::hex << std::showbase << ::GetLastError() << L"\n";
std::wcerr << "Letzter Fehler: " << ::GetLastError() << L"\n";
//Es wird ein Fehler ausgegeben ... aber trotzdem signiert. Hier wird genau dieser FEhler geprüft
//und dann trotzdem 0 zurückgegeben.
if (std::to_string(::GetLastError()).compare("2148086027") == 0) {
std::wcerr << "2148086027: Timestamp URL nicht abfragbar" << L"\n";
return 1;
}
if (std::to_string(::GetLastError()).compare("2148073494") == 0) {
std::wcerr << "2148073494: Containerbezeichnung falsch" << L"\n";
return 1;
}
return 1;
}

std::wcout << L"Successfully signed " << fileToSign << L"\n";
return 0;
}
0 new messages