OpenSSL Crypto
認証ライブラリ
OpenSSL Crypto
概要
OpenSSLは、TLS/SSLプロトコルと汎用暗号化ライブラリを提供するオープンソースのツールキットです。
詳細
OpenSSLは、世界で最も広く使用されている暗号化ライブラリの一つであり、TLS(Transport Layer Security)およびSSL(Secure Sockets Layer)プロトコルの実装を提供しています。Apache License 2.0の下でライセンスされ、C言語で書かれたオープンソースプロジェクトです。対称暗号化(AES、DES、3DES)、非対称暗号化(RSA、ECC、DSA)、ハッシュ関数(SHA、MD5)、メッセージ認証コード(HMAC)、デジタル署名、X.509証明書の処理など、包括的な暗号化機能を提供します。ネットワーク通信のセキュリティ、ファイルの暗号化、デジタル証明書の管理、PKI(Public Key Infrastructure)の構築など、幅広いセキュリティ要件に対応できます。多くのプログラミング言語でバインディングが提供されており、クロスプラットフォーム対応で様々なオペレーティングシステムで動作します。
メリット・デメリット
メリット
- 業界標準: 世界中で広く採用されている暗号化ライブラリ
- 包括的機能: 対称・非対称暗号化、ハッシュ、デジタル署名など全対応
- プロトコル対応: TLS/SSL、DTLS、QUICなどのセキュリティプロトコル実装
- 多言語対応: 様々なプログラミング言語でのバインディング提供
- クロスプラットフォーム: Linux、Windows、macOS、組み込みシステム対応
- 高性能: 最適化されたアルゴリズム実装
- 豊富なアルゴリズム: 古典的から最新まで幅広い暗号化アルゴリズム
デメリット
- 複雑性: 多機能ゆえのAPI複雑さ
- セキュリティ更新: 定期的な脆弱性対応とアップデートが必要
- メモリ管理: C言語ベースのため慎重なメモリ管理が必要
- ドキュメント: 一部の機能で詳細ドキュメントが不足
- ビルド複雑さ: プラットフォーム固有のビルド設定が複雑
- デバッグ難易度: 暗号化関連の問題のデバッグが困難
主要リンク
書き方の例
基本的なAES暗号化・復号化
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
// AES-256-CBC暗号化
int encrypt_aes(unsigned char *plaintext, int plaintext_len,
unsigned char *key, unsigned char *iv,
unsigned char *ciphertext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
int len, ciphertext_len;
// 暗号化初期化
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
// 暗号化実行
EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
ciphertext_len = len;
// 最終ブロック処理
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
// AES-256-CBC復号化
int decrypt_aes(unsigned char *ciphertext, int ciphertext_len,
unsigned char *key, unsigned char *iv,
unsigned char *plaintext) {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
int len, plaintext_len;
// 復号化初期化
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
// 復号化実行
EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
plaintext_len = len;
// 最終ブロック処理
EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
RSA鍵ペア生成とデジタル署名
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
// RSA鍵ペア生成
EVP_PKEY* generate_rsa_keypair(int key_length) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY *pkey = NULL;
// 鍵生成初期化
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_length);
// 鍵ペア生成
EVP_PKEY_keygen(ctx, &pkey);
EVP_PKEY_CTX_free(ctx);
return pkey;
}
// デジタル署名作成
int sign_data(unsigned char *data, size_t data_len,
EVP_PKEY *private_key, unsigned char **signature,
size_t *signature_len) {
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
// 署名初期化
EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, private_key);
// データ更新
EVP_DigestSignUpdate(ctx, data, data_len);
// 署名長取得
EVP_DigestSignFinal(ctx, NULL, signature_len);
// 署名作成
*signature = OPENSSL_malloc(*signature_len);
int ret = EVP_DigestSignFinal(ctx, *signature, signature_len);
EVP_MD_CTX_free(ctx);
return ret;
}
SHA-256ハッシュ計算
#include <openssl/sha.h>
#include <openssl/evp.h>
// SHA-256ハッシュ計算
int calculate_sha256(unsigned char *data, size_t data_len,
unsigned char *hash) {
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned int hash_len;
// ハッシュ初期化
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
// データ更新
EVP_DigestUpdate(ctx, data, data_len);
// ハッシュ最終化
EVP_DigestFinal_ex(ctx, hash, &hash_len);
EVP_MD_CTX_free(ctx);
return hash_len;
}
// HMAC-SHA256計算
int calculate_hmac_sha256(unsigned char *data, size_t data_len,
unsigned char *key, size_t key_len,
unsigned char *hmac) {
unsigned int hmac_len;
HMAC(EVP_sha256(), key, key_len, data, data_len, hmac, &hmac_len);
return hmac_len;
}
X.509証明書の処理
#include <openssl/x509.h>
#include <openssl/x509v3.h>
// 証明書読み込み
X509* load_certificate(const char *cert_file) {
FILE *fp = fopen(cert_file, "r");
if (!fp) return NULL;
X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);
fclose(fp);
return cert;
}
// 証明書情報表示
void print_certificate_info(X509 *cert) {
// サブジェクト取得
X509_NAME *subject = X509_get_subject_name(cert);
char *subject_str = X509_NAME_oneline(subject, NULL, 0);
printf("Subject: %s\n", subject_str);
OPENSSL_free(subject_str);
// 発行者取得
X509_NAME *issuer = X509_get_issuer_name(cert);
char *issuer_str = X509_NAME_oneline(issuer, NULL, 0);
printf("Issuer: %s\n", issuer_str);
OPENSSL_free(issuer_str);
// 有効期限確認
ASN1_TIME *not_before = X509_get_notBefore(cert);
ASN1_TIME *not_after = X509_get_notAfter(cert);
printf("Valid from: ");
ASN1_TIME_print(stdout, not_before);
printf(" to ");
ASN1_TIME_print(stdout, not_after);
printf("\n");
}
TLS/SSLクライアント接続
#include <openssl/ssl.h>
#include <openssl/err.h>
// SSL/TLS初期化
void init_openssl() {
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
}
// SSL接続作成
SSL* create_ssl_connection(const char *hostname, int port) {
// SSL コンテキスト作成
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
if (!ctx) return NULL;
// 証明書検証設定
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_default_verify_paths(ctx);
// ソケット作成(省略)
int sock = create_socket(hostname, port);
// SSL構造体作成
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
// TLSハンドシェイク
if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
SSL_free(ssl);
SSL_CTX_free(ctx);
return NULL;
}
return ssl;
}
ランダム数生成
#include <openssl/rand.h>
// 暗号学的乱数生成
int generate_random_bytes(unsigned char *buffer, int length) {
return RAND_bytes(buffer, length);
}
// パスワード生成例
void generate_password(char *password, int length) {
const char charset[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789!@#$%^&*";
unsigned char random_bytes[length];
if (RAND_bytes(random_bytes, length) == 1) {
for (int i = 0; i < length; i++) {
password[i] = charset[random_bytes[i] % (sizeof(charset) - 1)];
}
password[length] = '\0';
}
}