我的目标是使用CryptoAPI获取CryptoAPI中生成的签名和编码证书的一些字节,并将它们转换为B64。问题是,正在修复证书标题,但输出不是B64!
我的输出:
----- BEGIN CERTIFICATE ----- MIIDfjCCAmagAwIBAgIBAjANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xEDAOBgNVBAoMB0FVVE9TT0wxDzANBgNVBAsMBkNNREVQVDEUMBIGA1UEAwwLbmFtZWRwaXBlQ0EwHhcNMTgwMTI2MTk0NDQ2WhcNMTkwMTI2MTk0NDQ2WjBlMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xDDAKBgNVBAoMA0RpczEmMCQGA1UEAwwdU1ZSLkNNMDA0MDlEOTg4RTk1LjE1MTY5OTQ5OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD28NOZkuJbUsU0COQFrJgMgzGaj / afj6lYKZyTr5oXtenSmTAXN0WJE7Wd7DCfKqPpbnui4mb62Tgn3NCyMyEHY5jzFUWaUIchlmVzkamQzkmE3g99Fhj3EZP9zAEQE7qs7p5aKcgzIHuMRDB16Ap7 / GcFLTUBXcval17yOyU + J9csiywTRA54IK8nvtXzYVvgDSKXOh02VEU9RIjE4C069PKGg04lwZNHm8KvuPJn70PXQQnDaoSkbyvh46lKGhJUsNzNsV0Dpk1owrV9jCCUhpOKdA61Ye8P1oFgLkyu8VV4FjJL7 / t7AwaV7AgV7fVtOQ1fZ1HU4VheDD + Q23snAgMBAAGjNjA0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA4GA1UdDwEB / wQEAwIFoDANBgNVHQoEBjAEAwIGQDANBgkqhkiG9w0BAQsFAAOCAQEAShaqwVJvEjg9n4Tw24hBvl5pXpRGlUjgOQHDsk9sf8WWlDQWZzdRbaw9Y2QBEPuBbxbnF / voiUwYIhWrIYZziZDmx4mHuM1tt7Dyo79pAaJ6KrYkEz OoLP9VCuC1qHsux9cwYb1WiJmJtIZi22aFvAXDCQ3cDr6ej + PbgrXOL + oaS3b95F2ds6zWhDjyFwBLldkAXB4P / GiiOnS3X85DVxWLzY + y88hoKqBYJq5vaAIdLHlqA6jZJYuR2VUjVixggLclAeGUYO9ljLcyS9aer0DFJvdCMKJyUfcN6t6s / tDsKO7nrJrPNIVxbXfg8KzVnWG3Px9KTF9u9bt2G3kJNg == ----- END CERTIFICATE -----
如果我在此处粘贴上述文字并尝试解码,则会失败...它不是B64: https://www.base64decode.org/
如果我转到https://www.base64encode.org/并粘贴上面的内容,该工具会将其转换为B64,我可以通过我需要进行的内部API调用提交它,OpenSSL对此感到满意。我需要在代码示例中使用最后两个函数调用来执行此操作,但它不起作用。没有错误被抛出。
代码:
std::string sCertificate;
HCRYPTPROV hCaProv = NULL;
PCRYPT_KEY_PROV_INFO pKeyInfo_CA = NULL;
CERT_INFO serverCertInfo;
CRYPT_ALGORITHM_IDENTIFIER signAlgo;
DWORD cbEncodedCert_SERVER = 0;
LPBYTE pbEncodedCert_SERVER = NULL;
DWORD dwB64CertificateLength;
LPSTR lpstrServerCertificate = NULL;
//...
//do a million things to process a CSR and make a certificate ready to be signed
//use CryptSignAndEncodeCertificate to figure out how much space to allocate for the certificate
if (!CryptSignAndEncodeCertificate(
hCaProv,
pKeyInfo_CA->dwKeySpec,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_CERT_TO_BE_SIGNED,
(void*)&serverCertInfo,
&signAlgo,
NULL,
NULL,
&cbEncodedCert_SERVER
))
{
LocalFree(pbEnhancedUsage);
LocalFree(pbUsage);
LocalFree(pbEncodedBasicConstraints);
CertFreeCertificateContext(pCACertContext);
CryptReleaseContext(hCaProv, 0);
CertCloseStore(hStoreRoot, 0);
throw std::runtime_error("Unable to sign and encode certificate");
}
//allocate space for the certificate
pbEncodedCert_SERVER = (LPBYTE)LocalAlloc(0, cbEncodedCert_SERVER);
//use CryptSignAndEncodeCertificate to sign and encode the new certificate
if (!CryptSignAndEncodeCertificate(
hCaProv,
pKeyInfo_CA->dwKeySpec,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_CERT_TO_BE_SIGNED,
(void*)&serverCertInfo,
&signAlgo,
NULL,
pbEncodedCert_SERVER,
&cbEncodedCert_SERVER
))
{
LocalFree(pbEnhancedUsage);
LocalFree(pbUsage);
LocalFree(pbEncodedBasicConstraints);
CertFreeCertificateContext(pCACertContext);
LocalFree(pbEncodedCert_SERVER);
CryptReleaseContext(hCaProv, 0);
CertCloseStore(hStoreRoot, 0);
throw std::runtime_error("Unable to sign and encode certificate");
}
//free up a bunch of memory we don't need anymore
CertFreeCertificateContext(pCACertContext);
CryptReleaseContext(hCaProv, 0);
CertCloseStore(hStoreRoot, 0);
LocalFree(pbEnhancedUsage);
LocalFree(pbUsage);
LocalFree(pbEncodedBasicConstraints);
//convert to B64 (call #1 to get length)
if (!CryptBinaryToStringA(
pbEncodedCert_SERVER,
cbEncodedCert_SERVER,
CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCRLF,
NULL,
&dwB64CertificateLength
))
{
LocalFree(pbEncodedCert_SERVER);
throw std::runtime_error("Could not get size of B64 string for server certificate");
}
//allocate space based on call #1
lpstrServerCertificate = (LPSTR)LocalAlloc(0, dwB64CertificateLength);
//convert to B64 (call #2 to encode)
if (!CryptBinaryToStringA(
pbEncodedCert_SERVER,
cbEncodedCert_SERVER,
CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCRLF,
lpstrServerCertificate,
&dwB64CertificateLength
))
{
LocalFree(pbEncodedCert_SERVER);
LocalFree(lpstrServerCertificate);
throw std::runtime_error("Could not make B64 string of server certificate");
}
//put the certificate text into a std::string to pass it out of the function and be done
sCertificate = lpstrServerCertificate;
//free resources
LocalFree(pbEncodedCert_SERVER);
LocalFree(lpstrServerCertificate);
连连呢?我觉得我可能在这里犯了一个简单的错误,但我不知道是什么。
答案 0 :(得分:0)
我认为CryptBinaryToString实际上会在第一次传递时将结果转换为B64 ...由于某种原因需要另一次传递。似乎愚蠢的是必须调用相同的功能4次才能完成这项工作但显然是必要的。我添加了这段代码并在sCertificate上调用了上面的代码,现在我在B64中有一些可行的东西。去搞清楚。希望另一个人从中得到一些东西。
bool UTIL::EncodeB64(
std::string sToEncode, //data to encode in B64 [IN]
std::string & sEncoded //encoded data [OUT]
)
{
sEncoded = "";
LPSTR lpstrEncoded = NULL;
DWORD dwB64Length;
std::vector<BYTE> vcharBytes(sToEncode.begin(), sToEncode.end());
//convert to B64 (call #1 to get length)
if (!CryptBinaryToStringA(
&vcharBytes[0],
vcharBytes.size(),
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
NULL,
&dwB64Length
))
{
//crashed and burned
return false;
}
//allocate space based on call #1
lpstrEncoded = (LPSTR)LocalAlloc(0, dwB64Length);
//convert to B64 (call #2 to encode)
if (!CryptBinaryToStringA(
&vcharBytes[0],
vcharBytes.size(),
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
lpstrEncoded,
&dwB64Length
))
{
//crashed and burned
LocalFree(lpstrEncoded);
return false;
}
//set result that we are going to pass out
sEncoded = lpstrEncoded;
//free memory
LocalFree(lpstrEncoded);
//success
return true;
}
添加到调用代码:
std::string sB64Pass1Certificate = lpstrServerCertificate;
LocalFree(pbEncodedCert_SERVER);
LocalFree(lpstrServerCertificate);
if (!EncodeB64(
sB64Pass1Certificate,
sCertificate
))
{
throw std::runtime_error("Could not make B64 string of server certificate (second pass)");
}