2015年7月23日星期四

Base64加解密

#include <windows.h>
#include <stdio.h>
#include <Dbghelp.h>

#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "Imagehlp.lib")

#include <Wincrypt.h>
#pragma comment(lib, "Crypt32.lib")

#pragma warning(disable:4995)
#pragma warning(disable:4996)

/*
目的:主要示例Base64的转换。
实现:解密Base64。

系统的接口:
CryptStringToBinary
CryptBinaryToString

微软的编码:
http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crypto/cyphers/base64/base64.c.htm
如果真想找到微软的东西,那就在sdk 6.0 Samples里面搜索Base64吧!

其实系统也有自带的命令的,用法如下:
CertUtil -encode InFile OutFile 将文件编码为 Base64
CertUtil -decode InFile OutFile 解码 Base64 编码的文件

made by corey
made at 2015.05.14
*/


void main()
{
    //DebugBreak();
    //__debugbreak();

    //摘自:http://zh.wikipedia.org/wiki/Base64
    LPCTSTR pszString = L"Man is distinguished, not only by his reason, "
        L"but by this singular passion from other animals, "
        L"which is a lust of the mind, that by a perseverance of delight in "
        L"the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";

    DWORD   cchString = lstrlen(pszString) * sizeof(wchar_t);
    DWORD   dwFlags   = CRYPT_STRING_BASE64;
 
    BOOL B = 0;

    LPTSTR pszString2 = 0;
    DWORD  pcchString = 0;
    B = CryptBinaryToString((BYTE *)pszString, cchString, dwFlags, pszString2, &pcchString);
    if (B == false)
    {
        return;
    }

    pcchString = pcchString * sizeof(wchar_t);
    pszString2 = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pcchString);
    if (pszString2 == NULL)
    {
        printf ("Failed to allocate on heap.\n");
        return;
    }

    //注意单字符和宽字符的编码是不一样的。
    B = CryptBinaryToString((BYTE *)pszString, cchString, dwFlags, pszString2, &pcchString);
    if (B == false)
    {
        HeapFree(GetProcessHeap(), 0, pszString2);
        return;
    }

    HeapFree(GetProcessHeap(), 0, pszString2);
    return;
}


--------------------------------------------------------------------------------------------------------------------------------


#include <windows.h>
#include <stdio.h>
#include <Dbghelp.h>

#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "Imagehlp.lib")

#include <Wincrypt.h>
#pragma comment(lib, "Crypt32.lib")

#pragma warning(disable:4995)
#pragma warning(disable:4996)

/*
目的:主要示例Base64的转换。
实现:解密Base64。

CryptStringToBinary
CryptBinaryToString

made by corey
made at 2015.05.14
*/


void main()
{
    //DebugBreak();
    //__debugbreak();

    //这个必须是相应的编码,如:Base64,否则下面的转换失败。
    //摘自:http://zh.wikipedia.org/wiki/Base64
    //LPCTSTR pszString = L"madebycorrey";
    LPCTSTR pszString = L"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
        L"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
        L"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
        L"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
        L"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";

    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    //第一步:把这个编码(Base64)转换为加密的二进制。

    DWORD   cchString = lstrlen(pszString);
    DWORD   dwFlags   = CRYPT_STRING_BASE64;
    BYTE  * pbBinary  = NULL;
    DWORD   pcbBinary = 0;
    DWORD   pdwSkip   = 0;
    DWORD   pdwFlags  = 0;

    BOOL B = CryptStringToBinary(
        pszString,

        //The number of characters of the formatted string to be converted, not including the terminating NULL character.
        //If this parameter is zero, pszString is considered to be a null-terminated string.      
        cchString,

        dwFlags,

        pbBinary,

        _Inout_ &pcbBinary,

        _Out_   & pdwSkip,
        _Out_   & pdwFlags
        );
    if (B == false)
    {
        int x = GetLastError();
        return;
    }

    pcbBinary = pcbBinary * sizeof(wchar_t);
    pbBinary = (BYTE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pcbBinary);
    if (pbBinary == NULL)
    {
        printf ("Failed to allocate on heap.\n");
        return;
    }

    B = CryptStringToBinary(pszString, cchString, dwFlags, pbBinary, &pcbBinary, &pdwSkip, &pdwFlags);
    if (B == false)
    {
        HeapFree(GetProcessHeap(), 0, pbBinary);
        return;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////
    //第二步:把上一步的内容这个转换为原文。

    LPTSTR pszString2 = 0;
    DWORD  pcchString = 0;
    B = CryptBinaryToString(pbBinary, pcbBinary, dwFlags,
        _Out_opt_       pszString2,
        _Inout_         &pcchString
        );
    if (B == false)
    {
        HeapFree(GetProcessHeap(), 0, pbBinary);
        return;
    }

    pcchString = pcchString * sizeof(wchar_t);
    pszString2 = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pcchString);
    if (pszString2 == NULL)
    {
        HeapFree(GetProcessHeap(), 0, pbBinary);
        printf ("Failed to allocate on heap.\n");
        return;
    }

    B = CryptBinaryToString(pbBinary, pcbBinary, dwFlags,
        _Out_opt_       pszString2,
        _Inout_         &pcchString
        );//这里把空格给去掉了,多个回车换行。如果有-,后面的都截取了。总是多个回车换行。
    if (B == false)
    {
        HeapFree(GetProcessHeap(), 0, pbBinary);
        HeapFree(GetProcessHeap(), 0, pszString2);
        return;
    }

    HeapFree(GetProcessHeap(), 0, pbBinary);
    HeapFree(GetProcessHeap(), 0, pszString2);
    return;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////
}