如何使用wprintf正确打印BCryptEncrypt加密生成的密文?
BCryptEncrypt密文的正确打印与保存方法
你当前用%hs打印密文的方式完全错误,原因很简单:BCryptEncrypt输出的密文是二进制数据,不是ASCII字符串。%hs会把传入的字节流当作ASCII字符解析,遇到值为0的字节就会截断输出,而且大部分二进制值对应不可打印的控制字符,最终只会输出乱码或不完整的内容。
正确的密文打印方式:转十六进制字符串
二进制密文无法直接用字符串格式符打印,最通用的做法是将每个字节转换为两位十六进制字符,转成可打印的宽字符串后再用wprintf输出。
可以添加一个辅助函数来完成二进制到十六进制的转换:
#include <wchar.h> // 将二进制数据转为十六进制宽字符串 BOOL BinaryToHexW(PBYTE pBinary, ULONG uBinarySize, PWSTR pHexStr, ULONG uHexStrSize) { if (pBinary == NULL || pHexStr == NULL || uHexStrSize < (uBinarySize * 2 + 1)) return FALSE; const WCHAR szHexChars[] = L"0123456789ABCDEF"; PWSTR pCurrent = pHexStr; for (ULONG i = 0; i < uBinarySize; i++) { // 高4位转十六进制 *pCurrent++ = szHexChars[(pBinary[i] >> 4) & 0x0F]; // 低4位转十六进制 *pCurrent++ = szHexChars[pBinary[i] & 0x0F]; } // 字符串结尾加终止符 *pCurrent = L'\0'; return TRUE; }
然后修改你代码中的打印部分:
wprintf(L"Plain text: %s \n", textToEncrypt); // 分配十六进制字符串缓冲区,长度是密文字节数*2 +1(终止符) PWSTR szCipherHex = (PWSTR)HeapAlloc(GetProcessHeap(), 0, (sizeCiphertext * 2 + 1) * sizeof(WCHAR)); if (szCipherHex != NULL) { if (BinaryToHexW(cipherText, sizeCiphertext, szCipherHex, (sizeCiphertext * 2 + 1))) { wprintf(L"Ciphertext (hex): %s \n", szCipherHex); } HeapFree(GetProcessHeap(), 0, szCipherHex); }
密文保存到记事本的方法
如果要让记事本能正常查看密文,同样需要将二进制密文转为十六进制字符串后再保存。直接保存原始二进制数据的话,记事本打开会显示乱码。
可以用fwprintf写入文件,示例:
FILE* pFile = _wfopen(L"ciphertext.txt", L"w"); if (pFile != NULL) { PWSTR szCipherHex = (PWSTR)HeapAlloc(GetProcessHeap(), 0, (sizeCiphertext * 2 + 1) * sizeof(WCHAR)); if (szCipherHex != NULL) { if (BinaryToHexW(cipherText, sizeCiphertext, szCipherHex, (sizeCiphertext * 2 + 1))) { fwprintf(pFile, L"%s\n", szCipherHex); } HeapFree(GetProcessHeap(), 0, szCipherHex); } fclose(pFile); }
额外注意事项
- 用完密文缓冲区后记得用
HeapFree释放内存,避免内存泄漏。 - 如果需要后续解密,要保存原始的二进制密文(不是十六进制字符串),此时用二进制模式写文件即可:
_wfopen(L"cipher.bin", L"wb"),写入时直接写cipherText的二进制数据。
内容的提问来源于stack exchange,提问作者Sergio Calderon
相关产品推荐
相关产品推荐

