WindowsプログラマのWebアプリへの挑戦日記。あとパンとか。

C++でバイト列をBase64や16進数表示へ変換

6月 27th, 2008 Posted in C++

バイト列をBase64や16進数表示へ変換

C++でバイト列をBase64変換するには、暗号化で使用するCrypt APIが使えます。Crypt APIにCryptBinaryToStringという関数があり、これを使うとBase64変換や16進数のASCII表示が簡単にできます。じつは、自前でBase64変換とか実装した後に気がついたんですけどね。

CryptBinaryToStringを使うには、Crypt32.libをリンクしてwincrypt.hをインクルードします。引数は次のとおりです。

第1引数:const BYTE*:変換元データ
第2引数:DWORD:変換元データのサイズ
第3引数:DWORD:変換形式のフラグ
第4引数:LPTSTR:変換後データ
第5引数:DWORD*:変換後データサイズ

CryptBinaryToStringの第3引数にフラグで変換形式を指定します。フラグは次のとおり。

  1. CRYPT_STRING_BASE64HEADER
  2. CRYPT_STRING_BASE64
  3. CRYPT_STRING_BINARY
  4. CRYPT_STRING_BASE64REQUESTHEADER
  5. CRYPT_STRING_HEX
  6. CRYPT_STRING_HEXASCII
  7. CRYPT_STRING_BASE64X509CRLHEADER
  8. CRYPT_STRING_HEXADDR
  9. CRYPT_STRING_HEXASCIIADDR

Base64文字列のみが欲しい場合は「CRYPT_STRING_BASE64」を指定します。「CRYPT_STRING_BASE64HEADER」や「CRYPT_STRING_BASE64REQUESTHEADER」を指定すると、前後に文字列が付いてきます。16進数で表示する場合は、「CRYPT_STRING_HEX」を指定します。16進数とASCII文字を表示する場合は、「CRYPT_STRING_HEXASCII」。16進数とASCII文字とアドレスを表示する場合は、「CRYPT_STRING_HEXASCIIADDR」。実際に試してみるとわかるのでフラグを変えていろいろやってみてください。

第4引数にNULLを指定すると第5引数に変換後のデータサイズが返ってくるので、メモリを確保してもう一度この関数を呼びます。

表示例

CRYPT_STRING_HEXASCIIADDRを指定するとバイト列は次のような文字列へ変換されます。

  1. 0000    81 29 fd 28 07 38 c6 a1  c8 fe a6 fd ce 5a 79 eb   .).(.8.......Zy.
  2. 0010    bb 8c 3c 75 be 6c 8b 72  d1 14 d3 5e 4d 70 73 2b   ..<u.l.r...^Mps+
  3. 0020    25 5b f0 87 88 bd ec 1e  3b 06 e0 88 6d 23 60 bf   %[......;...m#`.
  4. 0030    a4 9f af 57 aa b9 ca 06                            ...W....

CRYPT_STRING_BASE64を指定するとバイト列は次のような文字列へ変換されます。

  1. gSn9KAc4xqHI/qb9zlp567uMPHW+bIty0RTTXk1wcyslW/CHiL3sHjsG4IhtI2C/pJ+vV6q5ygY=

Base64文字列や16進数表示をバイト列に変換

Base64文字列や16進数表示からバイト列に変換する場合は、CryptStringToBinaryを使います。第5引数まではCryptBinaryToStringと同じです。第3引数にはCryptBinaryToStringのフラグに加えて、次のフラグが指定できます。

  1. CRYPT_STRING_BASE64_ANY
  2. CRYPT_STRING_ANY
  3. CRYPT_STRING_HEX_ANY

第6引数:DWORD*:文字列で実際にBase64文字列や16進数文字列が始まるまでの文字数を返します。NULLも指定できます。
第7引数:DWORD*:実際に変換に使われた形式のフラグが返ります。NULLも指定できます。

第7引数の使い道としては、変換しようとしている文字列が、次のうちどれで変換されたものかわからない場合に、

  1. CRYPT_STRING_HEXADDR
  2. CRYPT_STRING_HEXASCIIADDR
  3. CRYPT_STRING_HEX
  4. CRYPT_STRING_HEXRAW
  5. CRYPT_STRING_HEXASCII

第3引数にCRYPT_STRING_HEX_ANYをしていすると、正しい変換形式が自動で選択されて、第7引数に選択された変換形式が返ってくるという仕組みです。

詳しくは、CryptStringToBinary Function (Windows)を熟読してください。

実装例

では、例として次の4つの変換についてC++のコードを載せておきます。

  • バイト列を16進数のASCII表示に変換する
    1. DWORD dwDst = 0;
    2. LPTSTR pstrDst = NULL;
    3. if( CryptBinaryToString( bSrc, nLen, CRYPT_STRING_HEXASCIIADDR, NULL, &dwDst ) ){
    4.        pstrDst = new TCHAR[ dwDst + 1 ];
    5.        if( CryptBinaryToString( bSrc, nLen, CRYPT_STRING_HEXASCIIADDR, pstrDst, &dwDst ) ){
    6.                //pstrDst:バイト列の16進数表示文字列
    7.        }
    8. }
    9. delete pstrDst;
  • 16進数のASCII表示をバイト列に変換する

    1. DWORD dwDst = 0;
    2. BYTE* pbDist = NULL;
    3. if( CryptStringToBinary( bSrc, nLen, CRYPT_STRING_HEXASCIIADDR, NULL, &dwDst, NULL, NULL ) ){
    4.        pbDist = new BYTE[ dwDst ];
    5.        if( CryptStringToBinary( bSrc, nLen, CRYPT_STRING_HEXASCIIADDR, pbDist, &dwDst, NULL, NULL ) ){
    6.                //pbDist:バイト列
    7.        }
    8. }
    9. delete pbDist;
  • バイト列をBase64文字列に変換する
    1. DWORD dwDst = 0;
    2. LPTSTR pstrDst = NULL;
    3. if( CryptBinaryToString( bSrc, nLen, CRYPT_STRING_BASE64, NULL, &dwDst ) ){
    4.        pstrDst = new TCHAR[ dwDst + 1 ];
    5.        if( CryptBinaryToString( bSrc, nLen, CRYPT_STRING_BASE64, pstrDst, &dwDst ) ){
    6.                //pstrDst:Base64文字列
    7.        }
    8. }
    9. delete pstrDst;
  • Base64文字列をバイト列に変換する
    1. DWORD dwDst = 0;
    2. BYTE* pbDist = NULL;
    3. if( CryptStringToBinary( bSrc, nLen, CRYPT_STRING_BASE64, NULL, &dwDst, NULL, NULL ) ){
    4.        pbDist = new BYTE[ dwDst ];
    5.        if( CryptStringToBinary( bSrc, nLen, CRYPT_STRING_BASE64, pbDist, &dwDst, NULL, NULL ) ){
    6.                //pbDist:バイト列
    7.        }
    8. }
    9. delete pbDist;
こちらもオススメ!

Trackback URL

  1. 2 Responses to “C++でバイト列をBase64や16進数表示へ変換”

  2. By sora on 6月 28, 2008

    どもども。
    んー、なんだか c++ が遠い昔のことのよう、、
    やっぱ c++ 良いですねー。

    ところで、Base64 ってどんなとき使います?

  3. By ヨスケ on 6月 28, 2008

    どうも。
    やっぱり型がはっきりしてると安心しますね。
    ワタクシの場合。

    Base64はe-mailなんかで添付ファイルを送るときなんかに使うんでしょうけど、実際に使ったのはアプリで覚えとくユーザIDとかを暗号化してBase64にして保存とかやったような気がします。あんまり意味ないですけどね。

Post a Comment