does anyone know why this code is not working?
#include "stdafx.h"
#include <windows.h>
#include <WinCrypt.h>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t *bin = TEXT("ProductID:1233===>55555");
BYTE out2[1000];
DWORD olen;
olen = 1000;
if (CryptStringToBinary(bin, 0, 1, out2, &olen, 0, 0) == 0)
{
wprintf(TEXT("Failure\n"));
}
else
{
//wprintf(TEXT("rn%s\n"),out2);
wprintf(TEXT("Success\n"));
}
system("pause");
return 0;
}
Thank you very much in advance!
Tom
asked Jul 4, 2010 at 17:53
Tom JonesTom Jones
31 silver badge3 bronze badges
1
Because you specified a length (parameter 2) of 0?
Edit: Just to clarify our eventual solution in the comments below, the code in the original question (since edited) contained two errors:
- It was calling
CryptBinaryToString
instead ofCryptStringToBinary
. Since it’s invalid to pass a 0 in the second parameter toCryptBinaryToString
, the function was failing. - It was passing 1 in the third parameter (dwFlags), which is interpreted as
CRYPT_STRING_BASE64
. Since the string to encrypt wasn’t in base 64 (it contained invalid characters such as ‘:’), the function was failing. In general, passing a raw value instead of using an existing definition (e.g.,CRYPT_STRING_BASE64
) is not a good idea.
answered Jul 4, 2010 at 17:58
Emerick RogulEmerick Rogul
6,7063 gold badges32 silver badges39 bronze badges
8
- Remove From My Forums
-
Question
-
I have a binary string which i want to convert to base64 string using CryptBinaryToString(). the function works and returns a base64 string but filled with ‘null’/’invalid’ bytes somewhere at the middle and end of string.
//pData contains the binary string and it is the pointer to 'BYTE array' (LPBYTE). //pdwDataSize is the number of bytes in pData. dwBase64Size = 0; //Get the length of buffer to be allocated. CryptBinaryToStringA(pData, pdwDataSize,CRYPT_STRING_BASE64 , NULL, &dwBase64Size); //Allocate buffer LPSTR pBase64 = (LPSTR)malloc(dwBase64Size); CryptBinaryToStringA(pData, pdwDataSize, CRYPT_STRING_BASE64 , pBase64, &dwBase64Size); The result pBase64 contains the base64 string but with 'null' or invalid characters.
Answers
-
I developed a simple function BinaryToBase64 which takes as input a pointer to binary data and its size in bytes, and returns a CString instance containing the base64 string.
(AtlThrow is used to signal errors.)
This function is a simple wrapper to CryptBinaryToString function (using CRYPT_STRING_BASE64 flag).Considering that the CRYPT_STRING_NOCRLF flag is not supported on Windows Server 2003 and Windows XP, I developed a simple function to remove CR/LF pairs from strings.
You can copy and paste the following compilable C++ code in an empty Win32 project created with Visual Studio 2008:
////////////////////////////////////////////////////////////////////////// // // TestBase64.cpp // // by Giovanni Dicanio <giovanni DOT dicanio AT gmail.com> // // 2009, October 25th // ////////////////////////////////////////////////////////////////////////// //======================================================================== // INCLUDES //======================================================================== #define WIN32_LEAN_AND_MEAN #define STRICT #include <Windows.h> // Win32 Platform SDK #include <WinCrypt.h> // CryptBinaryString function #include <atlbase.h> // ATL library #include <atlstr.h> // CString class from ATL #pragma comment(lib, "Crypt32.lib") //======================================================================== // FUNCTION IMPLEMENTATIONS //======================================================================== //------------------------------------------------------------------------ // Converts binary data to a Base64 string. //------------------------------------------------------------------------ CString BinaryToBase64( __in const BYTE * pbBinary, __in DWORD cbBinary ) { // Check input pointer ATLASSERT( pbBinary != NULL ); if ( pbBinary == NULL ) AtlThrow( E_POINTER ); // Check input size ATLASSERT( cbBinary != 0 ); if ( cbBinary == 0 ) AtlThrow( E_INVALIDARG ); // Request size of Base64 string DWORD cchBase64; if ( ! CryptBinaryToString( pbBinary, cbBinary, CRYPT_STRING_BASE64, NULL, &cchBase64 ) ) { AtlThrowLastWin32(); } // Allocate a string with required size CString strBase64; LPTSTR pszBase64 = strBase64.GetBuffer( cchBase64 ); ATLASSERT( pszBase64 != NULL ); // Convert binary data to Base64 if ( ! CryptBinaryToString( pbBinary, cbBinary, CRYPT_STRING_BASE64, pszBase64, &cchBase64 ) ) { AtlThrowLastWin32(); } // Release CString buffer strBase64.ReleaseBuffer(); // Return the converted string return strBase64; } //------------------------------------------------------------------------ // Given an input string, removes the return/line feed (CR/LF) pairs // from it. // If the input string is NULL, just returns an empty string. //------------------------------------------------------------------------ CString StripNewLines( __in LPCTSTR pszSource ) { // Check input string pointer: // returns empty string if input is NULL or empty. if ( ( pszSource == NULL ) || ( *pszSource == 0 ) ) return TEXT(""); // String without CR/LF pairs CString strResult; // Pointer to characters in input string const TCHAR * pchSource = pszSource; // Scan input string while ( *pchSource ) { // Copy character to destination string if it is not a CR/LF (0x0D/0x0A) pair if ( *pchSource != 0x0D ) { strResult.AppendChar( *pchSource ); // Move to next character ++pchSource; } else { // We should have a LF (0x0A) following it ATLASSERT( *(pchSource + 1) == 0x0A ); // Skip CR/LF pchSource++; pchSource++; } } // Return string without CR/LF pairs return strResult; } //------------------------------------------------------------------------ // A simple test for BinaryToBase64 function. //------------------------------------------------------------------------ void Test() { // Message copied from Wikipedia entry about Base64: // http://en.wikipedia.org/wiki/Base64 // char szMessage[] = "Man is distinguished, not only by his reason, " \ "but by this singular passion from other animals, which is a " \ "lust of the mind, that by a perseverance of delight in the " \ "continued and indefatigable generation of knowledge, exceeds " \ "the short vehemence of any carnal pleasure."; // // Convert text to base64 // CString strBase64 = BinaryToBase64( reinterpret_cast<BYTE *>(szMessage), sizeof(szMessage) - 1 // -1 to exclude terminating \0 ); // // Show base64 string // MessageBox( NULL, CA2T(szMessage), TEXT("Original String:"), MB_OK ); // MessageBox(NULL, strBase64, TEXT("Base64 String:"), MB_OK); MessageBox( NULL, StripNewLines(strBase64), TEXT("Base64 String:"), MB_OK ); } //------------------------------------------------------------------------ // Win32 App Entry-point. //------------------------------------------------------------------------ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // Run the test Test(); return 0; } //////////////////////////////////////////////////////////////////////////
HTH,
Giovanni-
Marked as answer by
Sunday, October 25, 2009 11:42 AM
-
Edited by
Giovanni Dicanio
Sunday, October 25, 2009 4:36 PM
Renamed local variable in ‘StripNewLines’ function from ‘pcchSource’ to ‘pchSource’.
-
Marked as answer by
Я пытаюсь вывести исходную форму base64 импортированного открытого ключа RSA, используя функции Windows CryptoAPI. Используя CryptBinaryToString с флагом CRYPT_STRING_BASE64HEADER, выходной заголовок будет читать «BEGIN CERTIFICATE» вместо ожидаемого «BEGIN PUBLIC KEY».
Не станет ли это проблематичным, если я экспортирую вывод и повторно импортирую его с разными заголовками? Если так, что я делаю не так?
Вот как был импортирован открытый ключ.
Открытый ключ хранится в файле pubkey.pem в следующем формате PEM:
-----BEGIN PUBLIC KEY-----
[REDACTED]
-----END PUBLIC KEY-----
Файл читается в буфер с помощью CreateFile/ReadFile. PEM преобразован в двоичный файл с использованием CryptStringToBinaryA. Двоичный файл декодируется в X509_PUBLIC_KEY_INFO с использованием CryptDecodeObjectEx. Структура PubKeyInfo декодируется в RSA_CSP_PUBLICKEYBLOB (та же функция, что и выше).
Эта часть прекрасно работает (можно импортировать ключ и шифровать данные с помощью CryptImportKey, CryptEncrypt и т.д.).
Вот код, который я собрал, чтобы попытаться вернуть необработанный блоб обратно в формат PEM base64. Я удалил большинство проверок на ошибки, чтобы избежать головной боли.
pbTmp и cbTmp — это временный буфер для хранения вывода и размера соответственно. pBinaryKey — это необработанный двоичный объект с открытым ключом (импортированный ранее). pBuffer — это выходной буфер (предполагается, что он имеет правильный размер). ulDataLen — это размер выходного буфера.
CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pBinaryKey, 0, NULL, NULL, &cbTmp)
pbTmp = malloc(cbTmp);
CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, pBinaryKey, 0, NULL, pbTmp, &cbTmp)
CryptBinaryToStringA(pbTmp, cbTmp, CRYPT_STRING_BASE64HEADER, NULL, &ulDataLen)
CryptBinaryToStringA(pbTmp, cbTmp, CRYPT_STRING_BASE64HEADER, pBuffer, &ulDataLen)
Получающийся буфер заканчивается этим:
-----BEGIN CERTIFICATE-----
[REDACTED; DIFFERENT FROM ORIGINAL PUBLIC KEY]
-----END CERTIFICATE-----
- Remove From My Forums
-
Question
-
Code Snippet
Private Sub ConvertBase64() ‘fileName As String)
Dim byteBuffer() As Byte
Dim outputLength As Long
Dim strBase64 As String
Dim inputStream As Object
Dim fileName As String
Dim result As LongfileName = «c:\test.txt»
Set inputStream = CreateObject(«ADODB.Stream»)
inputStream.Type = 1 ‘adTypeBinary
inputStream.Open
inputStream.LoadFromFile fileName
ReDim byteBuffer(inputStream.Size)
byteBuffer = inputStream.Read(-1) ‘adReadAllresult = CryptBinaryToString(byteBuffer(0), _
UBound(byteBuffer) + 1, _
CRYPT_STRING_BASE64, _
vbNullString, _
outputLength)strBase64 = Space$(outputLength)
If CryptBinaryToString(byteBuffer(0), _
UBound(byteBuffer) + 1, _
CRYPT_STRING_BASE64, _
strBase64, _
outputLength) <> 0 Then
MsgBox strBase64
Else
MsgBox «Error » & CStr(Err.LastDllError)
End If
End SubOn the marked string I’ve got:
outputLength = 0
result = 0
Err.LastDllError = 234 (0x000000EA)my text file content: «abc»
Why
CryptBinaryToString returns outputLength = 0 ?