バイナリアン御用達(?) CryptBinaryToString

CryptBinaryToString というAPIを使うと、バイナリ列を文字列に変換できる。

BOOL WINAPI CryptBinaryToString(
  __in       const BYTE *pbBinary,  // バイナリ列
  __in       DWORD cbBinary,        // バイナリ列のサイズ
  __in       DWORD dwFlags,         // 変換書式のフラグ
  __out_opt  LPTSTR pszString,      // 変換後の文字列を受け取るバッファ
  __inout    DWORD *pcchString      // 変換後の文字列を受け取るバッファの配列要素数
);

使い方は、はじめに CryptBinaryToString にバイナリ列とそのサイズを渡して、変換した文字列を格納するために必要なバッファサイズを取得する。その後、要求されたサイズのバッファを確保して、そのバッファとともに再度バイナリ列を渡すと、バイナリ列を文字列に変換することができる。


変換の書式はフラグで指定することができ、BASE64や、16進数と文字列の併記などが可能。以下に、指定可能なフラグそれぞれを指定しての変換結果を示す。「**** フラグ定数名 ****」以下に変換結果を出力している。

**** CRYPT_STRING_BASE64HEADER ****
-----BEGIN CERTIFICATE-----
W2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9hYTM3OTg4
NyUyOFZTLjg1JTI5LmFzcHg6dGl0bGU9Q3J5cHRCaW5hcnlUb1N0cmluZ10ggsaC
ooKkQVBJgvCOZ4KkgsaBQYNvg0ODaYOKl/GC8JW2jpqX8YLJlc+Kt4LFgquC6YFC
DQqCzYK2gt+CyYFBQ3J5cHRCaW5hcnlUb1N0cmluZyCCyYNvg0ODaYOKl/GCxoK7
gsyDVINDg1mC8JNugrWCxIFBlc+Kt4K1gr2Vto6al/GC8IpplFuCt4Lpgr2C34LJ
lUuXdoLIg2+DYoN0g0CDVINDg1mC8I7mk76Ct4LpgUKCu4LMjOOBQZd2i4GCs4Lq
gr2DVINDg1mCzINvg2KDdINAgvCKbZXbgrWCxIFBgruCzINvg2KDdINAgsaCxoLg
gsmNxJN4g2+DQ4Npg4qX8YLwk26Ct4LGgUGDb4NDg2mDipfxgvCVto6al/GCyZXP
ireCt4LpgrGCxoKqgsWCq4LpgUI=
-----END CERTIFICATE-----

**** CRYPT_STRING_BASE64 ****
W2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9hYTM3OTg4
NyUyOFZTLjg1JTI5LmFzcHg6dGl0bGU9Q3J5cHRCaW5hcnlUb1N0cmluZ10ggsaC
ooKkQVBJgvCOZ4KkgsaBQYNvg0ODaYOKl/GC8JW2jpqX8YLJlc+Kt4LFgquC6YFC
DQqCzYK2gt+CyYFBQ3J5cHRCaW5hcnlUb1N0cmluZyCCyYNvg0ODaYOKl/GCxoK7
gsyDVINDg1mC8JNugrWCxIFBlc+Kt4K1gr2Vto6al/GC8IpplFuCt4Lpgr2C34LJ
lUuXdoLIg2+DYoN0g0CDVINDg1mC8I7mk76Ct4LpgUKCu4LMjOOBQZd2i4GCs4Lq
gr2DVINDg1mCzINvg2KDdINAgvCKbZXbgrWCxIFBgruCzINvg2KDdINAgsaCxoLg
gsmNxJN4g2+DQ4Npg4qX8YLwk26Ct4LGgUGDb4NDg2mDipfxgvCVto6al/GCyZXP
ireCt4LpgrGCxoKqgsWCq4LpgUI=

**** CRYPT_STRING_BINARY ****
[http://msdn.microsoft.com/en-us/library/aa379887%28VS.85%29.aspx:title=CryptBinaryToString] というAPIを使うと、バイナリ列を文字列に変換できる。
はじめに、CryptBinaryToString にバイナリ列とそのサイズを渡して、変換した文字列を格納するために必要なバッファサイズを取得する。その後、要求されたサイズのバッファを確保して、そのバッファとともに再度バイナリ列を渡すと、バイナリ列を文字列に変換することができる。g1mCレS・

**** CRYPT_STRING_BASE64REQUESTHEADER ****
-----BEGIN NEW CERTIFICATE REQUEST-----
W2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9hYTM3OTg4
NyUyOFZTLjg1JTI5LmFzcHg6dGl0bGU9Q3J5cHRCaW5hcnlUb1N0cmluZ10ggsaC
ooKkQVBJgvCOZ4KkgsaBQYNvg0ODaYOKl/GC8JW2jpqX8YLJlc+Kt4LFgquC6YFC
DQqCzYK2gt+CyYFBQ3J5cHRCaW5hcnlUb1N0cmluZyCCyYNvg0ODaYOKl/GCxoK7
gsyDVINDg1mC8JNugrWCxIFBlc+Kt4K1gr2Vto6al/GC8IpplFuCt4Lpgr2C34LJ
lUuXdoLIg2+DYoN0g0CDVINDg1mC8I7mk76Ct4LpgUKCu4LMjOOBQZd2i4GCs4Lq
gr2DVINDg1mCzINvg2KDdINAgvCKbZXbgrWCxIFBgruCzINvg2KDdINAgsaCxoLg
gsmNxJN4g2+DQ4Npg4qX8YLwk26Ct4LGgUGDb4NDg2mDipfxgvCVto6al/GCyZXP
ireCt4LpgrGCxoKqgsWCq4LpgUI=
-----END NEW CERTIFICATE REQUEST-----

**** CRYPT_STRING_HEX ****
5b 68 74 74 70 3a 2f 2f  6d 73 64 6e 2e 6d 69 63
72 6f 73 6f 66 74 2e 63  6f 6d 2f 65 6e 2d 75 73
2f 6c 69 62 72 61 72 79  2f 61 61 33 37 39 38 38
37 25 32 38 56 53 2e 38  35 25 32 39 2e 61 73 70
78 3a 74 69 74 6c 65 3d  43 72 79 70 74 42 69 6e
61 72 79 54 6f 53 74 72  69 6e 67 5d 20 82 c6 82
a2 82 a4 41 50 49 82 f0  8e 67 82 a4 82 c6 81 41
83 6f 83 43 83 69 83 8a  97 f1 82 f0 95 b6 8e 9a
97 f1 82 c9 95 cf 8a b7  82 c5 82 ab 82 e9 81 42
0d 0a 82 cd 82 b6 82 df  82 c9 81 41 43 72 79 70
74 42 69 6e 61 72 79 54  6f 53 74 72 69 6e 67 20
82 c9 83 6f 83 43 83 69  83 8a 97 f1 82 c6 82 bb
82 cc 83 54 83 43 83 59  82 f0 93 6e 82 b5 82 c4
81 41 95 cf 8a b7 82 b5  82 bd 95 b6 8e 9a 97 f1
82 f0 8a 69 94 5b 82 b7  82 e9 82 bd 82 df 82 c9
95 4b 97 76 82 c8 83 6f  83 62 83 74 83 40 83 54
83 43 83 59 82 f0 8e e6  93 be 82 b7 82 e9 81 42
82 bb 82 cc 8c e3 81 41  97 76 8b 81 82 b3 82 ea
82 bd 83 54 83 43 83 59  82 cc 83 6f 83 62 83 74
83 40 82 f0 8a 6d 95 db  82 b5 82 c4 81 41 82 bb
82 cc 83 6f 83 62 83 74  83 40 82 c6 82 c6 82 e0
82 c9 8d c4 93 78 83 6f  83 43 83 69 83 8a 97 f1
82 f0 93 6e 82 b7 82 c6  81 41 83 6f 83 43 83 69
83 8a 97 f1 82 f0 95 b6  8e 9a 97 f1 82 c9 95 cf
8a b7 82 b7 82 e9 82 b1  82 c6 82 aa 82 c5 82 ab
82 e9 81 42

**** CRYPT_STRING_HEXASCII ****
5b 68 74 74 70 3a 2f 2f  6d 73 64 6e 2e 6d 69 63   [http://msdn.mic
72 6f 73 6f 66 74 2e 63  6f 6d 2f 65 6e 2d 75 73   rosoft.com/en-us
2f 6c 69 62 72 61 72 79  2f 61 61 33 37 39 38 38   /library/aa37988
37 25 32 38 56 53 2e 38  35 25 32 39 2e 61 73 70   7%28VS.85%29.asp
78 3a 74 69 74 6c 65 3d  43 72 79 70 74 42 69 6e   x:title=CryptBin
61 72 79 54 6f 53 74 72  69 6e 67 5d 20 82 c6 82   aryToString] ...
a2 82 a4 41 50 49 82 f0  8e 67 82 a4 82 c6 81 41   ...API...g.....A
83 6f 83 43 83 69 83 8a  97 f1 82 f0 95 b6 8e 9a   .o.C.i..........
97 f1 82 c9 95 cf 8a b7  82 c5 82 ab 82 e9 81 42   ...............B
0d 0a 82 cd 82 b6 82 df  82 c9 81 41 43 72 79 70   ...........ACryp
74 42 69 6e 61 72 79 54  6f 53 74 72 69 6e 67 20   tBinaryToString
82 c9 83 6f 83 43 83 69  83 8a 97 f1 82 c6 82 bb   ...o.C.i........
82 cc 83 54 83 43 83 59  82 f0 93 6e 82 b5 82 c4   ...T.C.Y...n....
81 41 95 cf 8a b7 82 b5  82 bd 95 b6 8e 9a 97 f1   .A..............
82 f0 8a 69 94 5b 82 b7  82 e9 82 bd 82 df 82 c9   ...i.[..........
95 4b 97 76 82 c8 83 6f  83 62 83 74 83 40 83 54   .K.v...o.b.t.@.T
83 43 83 59 82 f0 8e e6  93 be 82 b7 82 e9 81 42   .C.Y...........B
82 bb 82 cc 8c e3 81 41  97 76 8b 81 82 b3 82 ea   .......A.v......
82 bd 83 54 83 43 83 59  82 cc 83 6f 83 62 83 74   ...T.C.Y...o.b.t
83 40 82 f0 8a 6d 95 db  82 b5 82 c4 81 41 82 bb   .@...m.......A..
82 cc 83 6f 83 62 83 74  83 40 82 c6 82 c6 82 e0   ...o.b.t.@......
82 c9 8d c4 93 78 83 6f  83 43 83 69 83 8a 97 f1   .....x.o.C.i....
82 f0 93 6e 82 b7 82 c6  81 41 83 6f 83 43 83 69   ...n.....A.o.C.i
83 8a 97 f1 82 f0 95 b6  8e 9a 97 f1 82 c9 95 cf   ................
8a b7 82 b7 82 e9 82 b1  82 c6 82 aa 82 c5 82 ab   ................
82 e9 81 42                                        ...B

**** CRYPT_STRING_BASE64X509CRLHEADER ****
-----BEGIN X509 CRL-----
W2h0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9hYTM3OTg4
NyUyOFZTLjg1JTI5LmFzcHg6dGl0bGU9Q3J5cHRCaW5hcnlUb1N0cmluZ10ggsaC
ooKkQVBJgvCOZ4KkgsaBQYNvg0ODaYOKl/GC8JW2jpqX8YLJlc+Kt4LFgquC6YFC
DQqCzYK2gt+CyYFBQ3J5cHRCaW5hcnlUb1N0cmluZyCCyYNvg0ODaYOKl/GCxoK7
gsyDVINDg1mC8JNugrWCxIFBlc+Kt4K1gr2Vto6al/GC8IpplFuCt4Lpgr2C34LJ
lUuXdoLIg2+DYoN0g0CDVINDg1mC8I7mk76Ct4LpgUKCu4LMjOOBQZd2i4GCs4Lq
gr2DVINDg1mCzINvg2KDdINAgvCKbZXbgrWCxIFBgruCzINvg2KDdINAgsaCxoLg
gsmNxJN4g2+DQ4Npg4qX8YLwk26Ct4LGgUGDb4NDg2mDipfxgvCVto6al/GCyZXP
ireCt4LpgrGCxoKqgsWCq4LpgUI=
-----END X509 CRL-----

**** CRYPT_STRING_HEXADDR ****
0000    5b 68 74 74 70 3a 2f 2f  6d 73 64 6e 2e 6d 69 63
0010    72 6f 73 6f 66 74 2e 63  6f 6d 2f 65 6e 2d 75 73
0020    2f 6c 69 62 72 61 72 79  2f 61 61 33 37 39 38 38
0030    37 25 32 38 56 53 2e 38  35 25 32 39 2e 61 73 70
0040    78 3a 74 69 74 6c 65 3d  43 72 79 70 74 42 69 6e
0050    61 72 79 54 6f 53 74 72  69 6e 67 5d 20 82 c6 82
0060    a2 82 a4 41 50 49 82 f0  8e 67 82 a4 82 c6 81 41
0070    83 6f 83 43 83 69 83 8a  97 f1 82 f0 95 b6 8e 9a
0080    97 f1 82 c9 95 cf 8a b7  82 c5 82 ab 82 e9 81 42
0090    0d 0a 82 cd 82 b6 82 df  82 c9 81 41 43 72 79 70
00a0    74 42 69 6e 61 72 79 54  6f 53 74 72 69 6e 67 20
00b0    82 c9 83 6f 83 43 83 69  83 8a 97 f1 82 c6 82 bb
00c0    82 cc 83 54 83 43 83 59  82 f0 93 6e 82 b5 82 c4
00d0    81 41 95 cf 8a b7 82 b5  82 bd 95 b6 8e 9a 97 f1
00e0    82 f0 8a 69 94 5b 82 b7  82 e9 82 bd 82 df 82 c9
00f0    95 4b 97 76 82 c8 83 6f  83 62 83 74 83 40 83 54
0100    83 43 83 59 82 f0 8e e6  93 be 82 b7 82 e9 81 42
0110    82 bb 82 cc 8c e3 81 41  97 76 8b 81 82 b3 82 ea
0120    82 bd 83 54 83 43 83 59  82 cc 83 6f 83 62 83 74
0130    83 40 82 f0 8a 6d 95 db  82 b5 82 c4 81 41 82 bb
0140    82 cc 83 6f 83 62 83 74  83 40 82 c6 82 c6 82 e0
0150    82 c9 8d c4 93 78 83 6f  83 43 83 69 83 8a 97 f1
0160    82 f0 93 6e 82 b7 82 c6  81 41 83 6f 83 43 83 69
0170    83 8a 97 f1 82 f0 95 b6  8e 9a 97 f1 82 c9 95 cf
0180    8a b7 82 b7 82 e9 82 b1  82 c6 82 aa 82 c5 82 ab
0190    82 e9 81 42

**** CRYPT_STRING_HEXASCIIADDR ****
0000    5b 68 74 74 70 3a 2f 2f  6d 73 64 6e 2e 6d 69 63   [http://msdn.mic
0010    72 6f 73 6f 66 74 2e 63  6f 6d 2f 65 6e 2d 75 73   rosoft.com/en-us
0020    2f 6c 69 62 72 61 72 79  2f 61 61 33 37 39 38 38   /library/aa37988
0030    37 25 32 38 56 53 2e 38  35 25 32 39 2e 61 73 70   7%28VS.85%29.asp
0040    78 3a 74 69 74 6c 65 3d  43 72 79 70 74 42 69 6e   x:title=CryptBin
0050    61 72 79 54 6f 53 74 72  69 6e 67 5d 20 82 c6 82   aryToString] ...
0060    a2 82 a4 41 50 49 82 f0  8e 67 82 a4 82 c6 81 41   ...API...g.....A
0070    83 6f 83 43 83 69 83 8a  97 f1 82 f0 95 b6 8e 9a   .o.C.i..........
0080    97 f1 82 c9 95 cf 8a b7  82 c5 82 ab 82 e9 81 42   ...............B
0090    0d 0a 82 cd 82 b6 82 df  82 c9 81 41 43 72 79 70   ...........ACryp
00a0    74 42 69 6e 61 72 79 54  6f 53 74 72 69 6e 67 20   tBinaryToString
00b0    82 c9 83 6f 83 43 83 69  83 8a 97 f1 82 c6 82 bb   ...o.C.i........
00c0    82 cc 83 54 83 43 83 59  82 f0 93 6e 82 b5 82 c4   ...T.C.Y...n....
00d0    81 41 95 cf 8a b7 82 b5  82 bd 95 b6 8e 9a 97 f1   .A..............
00e0    82 f0 8a 69 94 5b 82 b7  82 e9 82 bd 82 df 82 c9   ...i.[..........
00f0    95 4b 97 76 82 c8 83 6f  83 62 83 74 83 40 83 54   .K.v...o.b.t.@.T
0100    83 43 83 59 82 f0 8e e6  93 be 82 b7 82 e9 81 42   .C.Y...........B
0110    82 bb 82 cc 8c e3 81 41  97 76 8b 81 82 b3 82 ea   .......A.v......
0120    82 bd 83 54 83 43 83 59  82 cc 83 6f 83 62 83 74   ...T.C.Y...o.b.t
0130    83 40 82 f0 8a 6d 95 db  82 b5 82 c4 81 41 82 bb   .@...m.......A..
0140    82 cc 83 6f 83 62 83 74  83 40 82 c6 82 c6 82 e0   ...o.b.t.@......
0150    82 c9 8d c4 93 78 83 6f  83 43 83 69 83 8a 97 f1   .....x.o.C.i....
0160    82 f0 93 6e 82 b7 82 c6  81 41 83 6f 83 43 83 69   ...n.....A.o.C.i
0170    83 8a 97 f1 82 f0 95 b6  8e 9a 97 f1 82 c9 95 cf   ................
0180    8a b7 82 b7 82 e9 82 b1  82 c6 82 aa 82 c5 82 ab   ................
0190    82 e9 81 42                                        ...B

**** CRYPT_STRING_HEXRAW ****
5b687474703a2f2f6d73646e2e6d6963726f736f66742e636f6d2f656e2d75732f6c6962726172792f616133373938383725323856532e38352532392e617370783a7469746c653d437279707442696e617279546f537472696e675d2082c682a282a441504982f08e6782a482c68141836f83438369838a97f182f095b68e9a97f182c995cf8ab782c582ab82e981420d0a82cd82b682df82c98141437279707442696e617279546f537472696e672082c9836f83438369838a97f182c682bb82cc83548343835982f0936e82b582c4814195cf8ab782b582bd95b68e9a97f182f08a69945b82b782e982bd82df82c9954b977682c8836f83628374834083548343835982f08ee693be82b782e9814282bb82cc8ce3814197768b8182b382ea82bd83548343835982cc836f83628374834082f08a6d95db82b582c4814182bb82cc836f83628374834082c682c682e082c98dc49378836f83438369838a97f182f0936e82b782c68141836f83438369838a97f182f095b68e9a97f182c995cf8ab782b782e982b182c682aa82c582ab82e98142

**** CRYPT_STRING_STRICT ****

最後のCRYPT_STRING_STRICTは要求された書式のバイナリ列を対象として渡していないため、動作していない。


変換したもともとのバイナリ列は、この記事のSJISテキストデータの一部分で次のとおり。

[http://msdn.microsoft.com/en-us/library/aa379887%28VS.85%29.aspx:title=CryptBinaryToString] というAPIを使うと、バイナリ列を文字列に変換できる。
はじめに、CryptBinaryToString にバイナリ列とそのサイズを渡して、変換した文字列を格納するために必要なバッファサイズを取得する。その後、要求されたサイズのバッファを確保して、そのバッファとともに再度バイナリ列を渡すと、バイナリ列を文字列に変換することができる。


上記の CRYPT_STRING_HEXASCII や CRYPT_STRING_HEXASCIIADDR を指定したときの変換結果から判るように、16進数と文字列の併記の場合はASCII表現しかできないため、マルチバイト文字が正しく出力できない。
が、それでもCRYPT_STRING_HEXASCIIADDRは簡易的な確認プログラムを作成するときなどに役立ちそうだ。


なお、変換に利用したサンプルプログラムは以下のとおり。

#include <windows.h>
#include <tchar.h>

#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")

#include <iostream>

BOOL DumpBinary(
    const BYTE* Binary,
    DWORD BinarySize,
    DWORD Flags)
{
    DWORD RequireSize = 0;
    if (!CryptBinaryToString(Binary, BinarySize, Flags, NULL, &RequireSize))
        return FALSE;

    TCHAR* StringBuffer = (TCHAR*)malloc(RequireSize * sizeof(TCHAR));
    if (!StringBuffer)
        return FALSE;
    
    BOOL Result = CryptBinaryToString(Binary, BinarySize, Flags, StringBuffer, &RequireSize);
    if (Result)
        _tprintf(_T("%s\n"), StringBuffer);

    free(StringBuffer);
    return Result;
}


int _tmain(int argc, TCHAR* argv[]) {

    if (argc != 2)
    {
        std::cerr 
            << "usage:\n"
            << "    >this.exe filename\n";
        return 1;
    }

    HANDLE File = NULL;
    HANDLE FileMap = NULL;
    BYTE* View = NULL;

    File = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (File == INVALID_HANDLE_VALUE)
        goto End;

    LARGE_INTEGER FileSize;
    if (!GetFileSizeEx(File, &FileSize) || FileSize.QuadPart == 0 || FileSize.HighPart != 0)
        goto End;

    FileMap = CreateFileMapping(File, NULL, PAGE_READONLY, 0, 0, NULL);
    if (!FileMap)
        goto End;

    View = (BYTE*)MapViewOfFile(FileMap, FILE_MAP_READ, 0, 0, 0);
    if (!View)
        goto End;

    std::cout << "**** CRYPT_STRING_BASE64HEADER ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_BASE64HEADER);
    std::cout << "**** CRYPT_STRING_BASE64 ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_BASE64);
    std::cout << "**** CRYPT_STRING_BINARY ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_BINARY);
    std::cout << "**** CRYPT_STRING_BASE64REQUESTHEADER ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_BASE64REQUESTHEADER);
    std::cout << "**** CRYPT_STRING_HEX ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_HEX);
    std::cout << "**** CRYPT_STRING_HEXASCII ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_HEXASCII);
    std::cout << "**** CRYPT_STRING_BASE64X509CRLHEADER ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_BASE64X509CRLHEADER);
    std::cout << "**** CRYPT_STRING_HEXADDR ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_HEXADDR);
    std::cout << "**** CRYPT_STRING_HEXASCIIADDR ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_HEXASCIIADDR);
    std::cout << "**** CRYPT_STRING_HEXRAW ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_HEXRAW);
    std::cout << "**** CRYPT_STRING_STRICT ****\n";
    DumpBinary(View, FileSize.LowPart, CRYPT_STRING_STRICT);
    
End:
    UnmapViewOfFile(View);
    CloseHandle(FileMap);
    CloseHandle(File);

return 0; }

ちなみに CryptStringToBinary というAPIもあり、こちらは文字列をバイナリ列に変換できる。