OpenSSL ライブラリを利用したプログラム開発の問題解決
こんなエラーが出る.
1>------ ビルド開始: プロジェクト: keyPairOut, 構成: Debug Win32 ------ 1>コンパイルしています... 1>main.cpp 1>c:\software\develop\openssl\include\openssl\x509.h(207) : error C2143: 構文エラー : ')' が '定数' の前にありません。 1>c:\software\develop\openssl\include\openssl\x509.h(207) : error C2143: 構文エラー : ';' が '定数' の前にありません。 1>c:\software\develop\openssl\include\openssl\x509.h(207) : error C2040: 'LPCSTR' : 'STACK' は 'const CHAR *' と間接操作のレベルが異なります。 1>c:\software\develop\openssl\include\openssl\x509.h(207) : error C2059: 構文エラー : ')' 1>c:\software\develop\openssl\include\openssl\x509.h(929) : error C2226: 構文エラー : 'LPCSTR' 型指定子の前あるいは内部で構文エラーが発生しました。 1>c:\software\develop\openssl\include\openssl\x509.h(929) : error C2065: 'a' : 定義されていない識別子です。 1>c:\software\develop\openssl\include\openssl\x509.h(929) : error C2062: 型 'unsigned char' は不要です。 1>c:\software\develop\openssl\include\openssl\x509.h(929) : error C2226: 構文エラー : 'LPCSTR' 型指定子の前あるいは内部で構文エラーが発生しました。 1>ビルドログは "file://c:\Documents and Settings\hoge\My Documents\Visual Studio 2008\Projects\keyPairOut\Debug\BuildLog.htm" に保存されました。 1>keyPairOut - エラー 8、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
環境は,
- Windows XP SP3
- VC++ 2009 Express Edition
- Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions の Win32 OpenSSL v0.9.8k
- Windows SDK 6.0A か何か
WinCrypt.h のインクルードガード,__WINCRYPT_H__ を定義したらコンパイルが通った.
ひらめき
- いろいろやっている中,「wincrypt x509.h X509_NAME」で Google 検索した
- http://sourcejam.com/jp/openssl-0.9.8b/include_2openssl_2x509_8h-source.html に到達した
- 第107行以下数行を見て衝撃が走った
- Windows SDK の WinCrypt.h を確認し,X509_NAME の定義を発見した
- 試しに __WINCRYPT_H__ を定義してビルドし,通ることを確認した
私が書いていたコードは RSA 暗号のキーペアを生成・ファイル出力するもの.エントリ後部で全文を掲載している.
その他
この問題は OpenSSL 使用トラブル - BiBoLoG の件と同一で,その時から5週間経過している.
別件で numeric_limits
今までこの問題が放置されていたのは 1.0.0 Beta 3 を独自ビルドしたものを利用していたため.別件で MSVC が致命的なエラーを云々が発生した.いろいろ検索し,http://osdir.com/ml/encryption.openssl.user/2002-05/msg00105.html から
に関連するらしいと理解した.この問題を回避するためにビルド済みライブラリを利用すればいいじゃーんと思い立ち,今回,5週前のトラブルと再会した.MD 版を自分でビルドできればいいんだろうが,方法が分からないしなあ.5週前のトラブルを今日1日で解決できたのはうれしい.
main.cpp
#include <stdio.h> #include <string.h> #define __WINCRYPT_H__ #include <openssl/rsa.h> #include <openssl/engine.h> #include <openssl/pem.h> #pragma comment(lib, "libeay32md.lib") #pragma comment(lib, "libssl32md.lib") // http://www.fireproject.jp/feature/c-language/openssl/rsa.html // キーペアの作成 static void printError(char *msg, unsigned long err); int main(int argc, char *argv[]) { int size = 2048; unsigned long exponent = 65537; FILE *privateKeyFile; FILE *publicKeyFile; if(argc != 3) { fprintf(stderr, "Usage : %s privateKeyFile publicKeyFile\n", argv[0]); exit(-1); } else { fopen_s(&privateKeyFile, argv[1], "w"); if (privateKeyFile == NULL) { perror("failed to fopen"); exit(-1); } fopen_s(&publicKeyFile, argv[2], "w"); if (publicKeyFile == NULL) { perror("failed to fopen"); exit(-1); } } // キーペアの作成 RSA *rsaKey = RSA_generate_key(size, exponent, NULL, NULL); if (rsaKey == NULL) { printError("failed to RSA_generate_key", ERR_get_error()); exit(-1); } if(RSA_print_fp(stdout, rsaKey, 0) != 1) { printError("failed to RSA_print_fp", ERR_get_error()); exit(-1); } // 公開鍵をPEM形式で書き出し if(PEM_write_RSAPublicKey(publicKeyFile, rsaKey) != 1) { printError("failed to PEM_write_RSAPublicKey", ERR_get_error()); exit(-1); } // 秘密鍵をPEM形式で書き出し if(PEM_write_RSAPrivateKey(privateKeyFile, rsaKey, NULL, NULL, 0, NULL, NULL) != 1) { printError("failed to PEM_write_RSAPrivateKey", ERR_get_error()); exit(-1); } // 領域の開放 RSA_free(rsaKey); fclose(privateKeyFile); fclose(publicKeyFile); return 0; } static void printError(char *msg, unsigned long err) { char *errmsg = ERR_error_string(err, NULL); fprintf(stderr, "%s(%s)\n", msg, errmsg); }