ZTMSブログ

自作フリーソフトやプログラミング雑記

 >  Win32 >  [OpenSSL] 自己署名サーバ証明書をC言語で作る

[OpenSSL] 自己署名サーバ証明書をC言語で作る

証 明 書
HTTPS通信で使うSSLサーバ証明書(自己署名)を、OpenSSLを使ってプログラム(C言語)で自動生成したい。ググったらコマンドライン(opensslコマンド)のやり方はすぐ見つかったけど、プログラムコード例はあまり見つからなかったのでメモ。

環境:WinXP Home SP3 / VC2008 Express / OpenSSL 1.0.0j / C言語

参考サイト
http://stackoverflow.com/questions/16364522/how-do-i-create-a-self-signed-certificate-in-openssl-programatically-i-e-not
http://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl

あとOpenSSLのソースコードも参考に
https://github.com/luvit/openssl/blob/master/openssl/apps/genrsa.c
https://github.com/openssl/openssl/blob/master/apps/x509.c
https://github.com/openssl/openssl/blob/master/apps/apps.c
http://docs.huihoo.com/doxygen/openssl/1.0.1c/selfsign_8c_source.html

エラーチェックなし必要な関数のみコードはこんな感じ。
void SSLSelfCertificateCreate( void )
{
ASN1_INTEGER* serial = ASN1_INTEGER_new();
EVP_PKEY* pkey = EVP_PKEY_new();
BIGNUM* exp = BN_new();
BIGNUM* big = BN_new();
X509* x509 = X509_new();
RSA* rsa = RSA_new();
X509_NAME* name = NULL;

BN_set_word( exp, RSA_F4 );
RSA_generate_key_ex( rsa, 2048, exp, NULL ); // 鍵長2048bit
#define SERIAL_RAND_BITS 64
BN_pseudo_rand( big, SERIAL_RAND_BITS, 0, 0 );
BN_to_ASN1_INTEGER( big, serial );
X509_set_serialNumber( x509, serial );
EVP_PKEY_assign_RSA( pkey, rsa );
rsa = NULL;
X509_set_version( x509, 2 ); // 2 -> x509v3
X509_gmtime_adj( X509_get_notBefore(x509), 0 );
X509_gmtime_adj( X509_get_notAfter(x509), 60*60*24*365 ); // 有効期間365日
X509_set_pubkey( x509, pkey );
name = X509_get_subject_name( x509 );
X509_NAME_add_entry_by_txt(name,"C",MBSTRING_ASC,"JP",-1,-1,0); // Country
X509_NAME_add_entry_by_txt(name,"CN",MBSTRING_ASC,"OreOre",-1,-1,0); // Common Name
X509_set_issuer_name( x509, name );
X509_sign( x509, pkey, EVP_sha1() );
// x509 が証明書、pkey が秘密鍵
// ファイルに保存したり、HTTPS通信に使ったり

ASN1_INTEGER_free( serial );
EVP_PKEY_free( pkey );
X509_free( x509 );
RSA_free( rsa );
BN_free( exp );
BN_free( big );
}

ファイルに保存するには、PEM_write_XX 関数を使う。
FILE* fp = fopen( "ssl.crt", "wb" );
PEM_write_X509( fp, x509 );
fclose( fp );

fp = fopen( "ssl.key", "wb" );
PEM_write_PrivateKey( fp, pkey, NULL,NULL,0,NULL,NULL );
fclose( fp );

保存したファイルから読み込むには PEM_read_XX 関数を使う。
X509* x509;
EVP_PKEY* pkey;
FILE* fp;

fp = fopen( "ssl.crt", "rb" );
x509 = PEM_read_X509( fp, NULL,NULL,NULL );
fclose( fp );

fp = fopen( "ssl.key", "rb" );
pkey = PEM_read_PrivateKey( fp, NULL,NULL,NULL );
fclose( fp );

HTTPSのサーバ証明書とかに使うには例えば以下のように割り当てる。
SSL_CTX* ctx = SSL_CTX_new( SSLv23_method() );
SSL_CTX_use_certificate( ctx, x509 );
SSL_CTX_use_PrivateKey( ctx, pkey );

もっとも簡素なTCP/SSLサーバは以下のような感じ。
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"libeay32.lib")
#pragma comment(lib,"ssleay32.lib")

#include <winsock2.h>
#include <ws2tcpip.h>
#include <openssl/ssl.h>

int main( void )
{
WSADATA wsaData;
ADDRINFOA hint;
ADDRINFOA* adr;
SOCKET server;
SOCKADDR_STORAGE addr;
int addrlen = sizeof(addr);
SOCKET client;
SSL_CTX* ctx;
SSL* ssl;

WSAStartup( MAKEWORD(2,2), &wsaData );
SSL_library_init();

memset( &hint, 0, sizeof(hint) );
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
hint.ai_flags = AI_PASSIVE;

#define HOST "localhost"
#define PORT "10080"
GetAddrInfoA( HOST, PORT, &hint, &adr );
server = socket( adr->ai_family, adr->ai_socktype, adr->ai_protocol );
bind( server, adr->ai_addr, (int)adr->ai_addrlen );
#define BACKLOG 128
listen( server, BACKLOG );
client = accept( server, (SOCKADDR*)&addr, &addrlen );

ctx = SSL_CTX_new( SSLv23_method() );
ssl = SSL_new( ctx );
#define SSL_CRT "ssl.crt"
#define SSL_KEY "ssl.key"
SSL_use_certificate_file( ssl, SSL_CRT, SSL_FILETYPE_PEM );
SSL_use_PrivateKey_file( ssl, SSL_KEY, SSL_FILETYPE_PEM );
SSL_set_fd( ssl, client );
SSL_accept( ssl );
#define DATA "Hello, OpenSSL!\r\n"
SSL_write( ssl, DATA, strlen(DATA) );
SSL_shutdown( ssl );
SSL_free( ssl );
SSL_CTX_free( ctx );

shutdown( client, SD_BOTH );
closesocket( client );
shutdown( server, SD_BOTH );
closesocket( server );
FreeAddrInfoA( adr );
WSACleanup();
return 0;
}

TCP/SSLサーバの動作確認にはコマンド openssl s_client が便利。
>openssl.exe s_client -connect localhost:10080
http://mtny.mobi/tE * by Alice Lowe
This is a message to the [OpenSSL] 自己署名サーバ証明書をC言語で作る - ZTMSブログ webmaster. Your website is missing out on at least 300 visitors per day. Our traffic system will dramatically increase your traffic to your website: http://ralive.de/201z - We offer 500 free targeted visitors during our free trial period and we offer up to 30,000 targeted visitors per month. Hope this helps :) Unsubscribe here: http://2url.de/1alt

コメント






管理者にだけ表示を許可する

http://mtny.mobi/tE

This is a message to the [OpenSSL] 自己署名サーバ証明書をC言語で作る - ZTMSブログ webmaster. Your website is missing out on at least 300 visitors per day. Our traffic system will dramatically increase your traffic to your website: http://ralive.de/201z - We offer 500 free targeted visitors during our free trial period and we offer up to 30,000 targeted visitors per month. Hope this helps :) Unsubscribe here: http://2url.de/1alt
2018-12-12 * Alice Lowe [ 編集 ]