OpenSSL Crypto

暗号化ライブラリOpenSSLTLSSSL暗号化ハッシュ証明書C/C++

認証ライブラリ

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';
    }
}