【PHP8.x】openssl_public_encrypt関数の使い方

作成日: 更新日:

openssl_public_encrypt関数は、OpenSSL拡張機能の一部として、公開鍵暗号方式を使用してデータを暗号化する関数です。この関数は、与えられた平文のデータと公開鍵を受け取り、そのデータを暗号化して、対応する秘密鍵でのみ復号できる形式に変換します。公開鍵暗号方式は、データを暗号化するための公開鍵と、それを復号するための秘密鍵という対になる鍵を用いる方式であり、これにより高いセキュリティを実現します。

具体的には、インターネット上での通信において、共通鍵(対称鍵暗号方式で使用される鍵)を安全に交換する際や、少量の機密情報を保護したい場合などに利用されます。例えば、ウェブサイトとの安全な通信(SSL/TLS)の初期段階で、クライアントが生成した共通鍵をサーバーの公開鍵で暗号化し、安全にサーバーへ送るといった用途が挙げられます。

この関数を使用することで、第三者によるデータの盗聴や改ざんのリスクを低減し、情報の機密性を確保することが可能になります。関数は、暗号化したい元のデータ、暗号化されたデータが格納される変数を参照渡しで指定し、さらに暗号化に用いる公開鍵を引数として受け取ります。処理が成功した場合は true を、失敗した場合は false を返します。データのセキュリティを確保する上で非常に重要な役割を果たす関数の一つです。

基本的な使い方

構文(syntax)

<?php
$dataToEncrypt = "秘密の情報です。";
$encryptedData = '';
$publicKeyPem = '-----BEGIN PUBLIC KEY-----ここに実際の公開鍵の内容を貼り付けます-----END PUBLIC KEY-----';

$success = openssl_public_encrypt($dataToEncrypt, $encryptedData, $publicKeyPem, OPENSSL_PKCS1_PADDING);
?>

引数(parameters)

string $data, string &$encrypted_data, mixed $public_key, int $padding = OPENSSL_PKCS1_PADDING

  • string $data: 暗号化する元のデータ
  • string &$encrypted_data: 暗号化された結果を格納する変数(参照渡し)
  • mixed $public_key: 公開鍵(PEM形式の文字列、またはopenssl_pkey_get_public()で取得したリソース)
  • int $padding = OPENSSL_PKCS1_PADDING: パディング方式を指定する整数

戻り値(return)

bool

openssl_public_encrypt関数は、公開鍵暗号化の実行に成功したかどうかを示す真偽値 (bool) を返します。暗号化が成功した場合は true、失敗した場合は false を返します。

サンプルコード

PHP openssl_public_encryptで公開鍵暗号化する

<?php

/**
 * PHPのopenssl_public_encrypt関数を使用してデータを公開鍵で暗号化し、
 * その後、対応する秘密鍵で復号化するサンプルコードです。
 * システムエンジニアを目指す初心者にも分かりやすく、一連の処理を示します。
 */
function encryptAndDecryptDataWithOpenSsl(): void
{
    echo "--- OpenSSL 公開鍵暗号化と秘密鍵復号化の例 ---" . PHP_EOL . PHP_EOL;

    // 1. 鍵ペアの生成
    // openssl_pkey_new() を使用して、RSAタイプの秘密鍵と公開鍵のペアを生成します。
    // これはテスト目的であり、本番環境では鍵の適切な管理とより安全な設定が必要です。
    $config = [
        "private_key_bits" => 2048, // 鍵のビット数 (推奨: 2048ビット以上)
        "private_key_type" => OPENSSL_KEYTYPE_RSA, // RSA鍵タイプ
    ];
    $privateKeyResource = openssl_pkey_new($config);

    if ($privateKeyResource === false) {
        echo "エラー: 鍵ペアの生成に失敗しました。" . PHP_EOL . openssl_error_string() . PHP_EOL;
        return;
    }

    // 生成した秘密鍵をPEM形式の文字列として取得
    openssl_pkey_export($privateKeyResource, $privateKeyPem);

    // 生成した公開鍵をPEM形式の文字列として取得
    $publicKeyDetails = openssl_pkey_get_details($privateKeyResource);
    $publicKeyPem = $publicKeyDetails['key'];

    echo "--- 生成された鍵情報 ---" . PHP_EOL;
    echo "秘密鍵 (PEM形式):" . PHP_EOL . $privateKeyPem . PHP_EOL;
    echo "公開鍵 (PEM形式):" . PHP_EOL . $publicKeyPem . PHP_EOL;
    echo PHP_EOL;

    // 2. 暗号化する元のデータ
    $originalData = "This is a confidential message that needs to be secured using RSA encryption.";
    echo "元のデータ: " . $originalData . PHP_EOL;
    echo PHP_EOL;

    // 3. openssl_public_encrypt() を使って公開鍵でデータを暗号化
    // 公開鍵のPEM形式文字列から、OpenSSL関数が使用できるリソース形式に変換します。
    $publicKeyForEncryption = openssl_pkey_get_public($publicKeyPem);
    $encryptedData = ''; // 暗号化されたデータが格納される変数を初期化

    if ($publicKeyForEncryption === false) {
        echo "エラー: 公開鍵リソースの読み込みに失敗しました。" . PHP_EOL . openssl_error_string() . PHP_EOL;
        openssl_free_key($privateKeyResource);
        return;
    }

    // openssl_public_encrypt 関数を呼び出してデータを暗号化します。
    // 第1引数: 暗号化する元の文字列データ
    // 第2引数: 暗号化されたデータが格納される参照変数 ($encryptedDataに結果が代入される)
    // 第3引数: 公開鍵のリソース
    // 第4引数: パディング方式 (OPENSSL_PKCS1_PADDING は最も一般的なRSAパディング方式)
    $encryptionSuccess = openssl_public_encrypt(
        $originalData,
        $encryptedData,
        $publicKeyForEncryption,
        OPENSSL_PKCS1_PADDING
    );

    if ($encryptionSuccess) {
        echo "データの暗号化に成功しました。" . PHP_EOL;
        // 暗号化されたデータはバイナリ形式なので、表示や保存のためにBase64エンコードします。
        echo "暗号化されたデータ (Base64エンコード): " . base64_encode($encryptedData) . PHP_EOL;
        echo PHP_EOL;
    } else {
        echo "エラー: データの暗号化に失敗しました。" . PHP_EOL . openssl_error_string() . PHP_EOL;
        openssl_free_key($privateKeyResource);
        openssl_free_key($publicKeyForEncryption);
        return;
    }

    // 4. openssl_private_decrypt() を使って秘密鍵でデータを復号化 (動作確認のため)
    // 秘密鍵のPEM形式文字列から、OpenSSL関数が使用できるリソース形式に変換します。
    $privateKeyForDecryption = openssl_pkey_get_private($privateKeyPem);
    $decryptedData = ''; // 復号化されたデータが格納される変数を初期化

    if ($privateKeyForDecryption === false) {
        echo "エラー: 秘密鍵リソースの読み込みに失敗しました。" . PHP_EOL . openssl_error_string() . PHP_EOL;
        openssl_free_key($privateKeyResource);
        openssl_free_key($publicKeyForEncryption);
        return;
    }

    // openssl_private_decrypt 関数を呼び出してデータを復号化します。
    // 暗号化時と同じパディング方式を使用する必要があります。
    $decryptionSuccess = openssl_private_decrypt(
        $encryptedData,
        $decryptedData,
        $privateKeyForDecryption,
        OPENSSL_PKCS1_PADDING
    );

    if ($decryptionSuccess) {
        echo "データの復号化に成功しました。" . PHP_EOL;
        echo "復号化されたデータ: " . $decryptedData . PHP_EOL;
        echo PHP_EOL;

        // 元のデータと復号化されたデータが一致するか確認
        if ($originalData === $decryptedData) {
            echo "検証: 元のデータと復号化されたデータは一致します。" . PHP_EOL;
        } else {
            echo "検証エラー: 元のデータと復号化されたデータが一致しません。" . PHP_EOL;
        }
    } else {
        echo "エラー: データの復号化に失敗しました。" . PHP_EOL . openssl_error_string() . PHP_EOL;
    }

    // 使用した鍵リソースを解放します。
    // PHPはスクリプト終了時に自動的に解放しますが、明示的に行うこともできます。
    openssl_free_key($privateKeyResource);
    openssl_free_key($publicKeyForEncryption);
    openssl_free_key($privateKeyForDecryption);

    echo PHP_EOL . "--- 例の終了 ---" . PHP_EOL;
}

// サンプル関数の実行
encryptAndDecryptDataWithOpenSsl();

PHPのopenssl_public_encrypt関数は、指定されたデータを公開鍵で暗号化するために使用されます。この関数で暗号化されたデータは、対応する秘密鍵でのみ復号化可能となり、機密性の高い情報の保護に役立ちます。

引数には、暗号化する元の文字列$data、暗号化結果を格納する参照変数&$encrypted_data、公開鍵のリソース$public_key、およびパディング方式$padding(例: OPENSSL_PKCS1_PADDING)を指定します。関数は、処理の成功時にtrueを、失敗時にfalseを戻り値として返します。

サンプルコードでは、まずopenssl_pkey_newで秘密鍵と公開鍵のペアを生成します。次に、openssl_public_encryptを使って元のデータを生成した公開鍵で暗号化し、結果を$encrypted_dataに格納します。暗号化されたデータはバイナリ形式のため、通常はBase64エンコードして扱われます。さらに、暗号化が正しく行われたかを確認するため、openssl_private_decrypt関数で秘密鍵を使って復号化する一連の処理も示されており、公開鍵暗号化の基本動作を学ぶのに適しています。

このサンプルコードは公開鍵暗号化の基本を示していますが、本番環境では鍵ペアをセキュアに生成・管理し、秘密鍵は決して公開せず厳重に保管する必要があります。openssl_public_encryptで暗号化できるデータサイズには鍵長に応じた制限があるため、大きなデータは共通鍵暗号とのハイブリッド方式を検討してください。暗号化と復号化で同じパディング方式を指定することが不可欠です。関数が失敗した際は、openssl_error_string()で詳細なエラー情報を確認し、適切にエラー処理を行うことが重要です。

PHPでRSA公開鍵暗号化する

<?php

/**
 * 指定されたデータをRSA公開鍵で暗号化します。
 *
 * この関数は、一時的なRSA鍵ペアを生成し、その公開鍵を使用してデータを暗号化します。
 * 暗号化されたデータは、通常、対応する秘密鍵で復号されます。
 *
 * @param string $dataToEncrypt 暗号化する元の文字列データ。
 * @return string|false 暗号化されたデータ(Base64エンコード)、または処理失敗時にfalse。
 */
function encryptDataWithPublicKey(string $dataToEncrypt): string|false
{
    // 1. RSA鍵ペアの生成
    // openssl_pkey_new() は、公開鍵と秘密鍵のペアを生成します。
    // ここでは2048ビットのRSA鍵を生成します。
    $res = openssl_pkey_new([
        'private_key_bits' => 2048,
        'private_key_type' => OPENSSL_KEYTYPE_RSA,
    ]);

    if ($res === false) {
        // 鍵生成に失敗した場合のエラー処理
        error_log("鍵ペアの生成に失敗しました: " . openssl_error_string());
        return false;
    }

    // 2. 生成された鍵ペアから公開鍵の詳細を取得
    // openssl_pkey_get_details() は、鍵の詳細情報を含む配列を返します。
    // 'key' エントリに PEM 形式の公開鍵が含まれています。
    $details = openssl_pkey_get_details($res);
    if ($details === false || !isset($details['key'])) {
        // 公開鍵の取得に失敗した場合のエラー処理
        error_log("公開鍵の取得に失敗しました。");
        openssl_pkey_free($res); // 鍵リソースを解放
        return false;
    }
    $publicKey = $details['key'];

    // 暗号化されたデータを格納するための変数
    $encryptedData = '';

    // 3. openssl_public_encrypt 関数を使用してデータを公開鍵で暗号化
    // 第1引数: 暗号化する元のデータ ($dataToEncrypt)
    // 第2引数: 暗号化されたデータが格納される参照変数 ($encryptedData)
    // 第3引数: 使用する公開鍵 ($publicKey)
    // 第4引数: パディングモード (OPENSSL_PKCS1_PADDING はRSA標準のパディング方式)
    $success = openssl_public_encrypt(
        $dataToEncrypt,
        $encryptedData,
        $publicKey,
        OPENSSL_PKCS1_PADDING
    );

    // 鍵リソースを解放 (メモリリークを防ぐため)
    openssl_pkey_free($res);

    if ($success) {
        // 暗号化されたデータはバイナリ形式のため、表示や転送のためにBase64エンコードします。
        return base64_encode($encryptedData);
    } else {
        // 暗号化に失敗した場合のエラー処理
        error_log("データの公開鍵暗号化に失敗しました: " . openssl_error_string());
        return false;
    }
}

// --- サンプルコードの実行 ---

// 暗号化したい元のデータ
$originalMessage = "This is a secret message that needs to be protected.";
echo "元のデータ: " . $originalMessage . "\n\n";

// 関数を呼び出してデータを暗号化
$encryptedResult = encryptDataWithPublicKey($originalMessage);

if ($encryptedResult !== false) {
    echo "--- 暗号化成功 ---\n";
    echo "暗号化されたデータ (Base64エンコード): " . $encryptedResult . "\n";
    echo "\n注意: このサンプルでは復号を行っていませんが、通常は対応する秘密鍵で復号します。\n";
} else {
    echo "--- 暗号化失敗 ---\n";
    echo "データの暗号化に失敗しました。エラーログを確認してください。\n";
}

?>

PHPのopenssl_public_encrypt関数は、RSA公開鍵暗号化の仕組みを利用してデータを安全に暗号化するために使用されます。この関数は、公開鍵で暗号化されたデータを、対応する秘密鍵でのみ復号できるという特性を持っています。具体的な機能として、第1引数に指定された元のデータ($data)を、第3引数で渡された公開鍵($public_key)を用いて暗号化します。暗号化された結果のデータは、第2引数の参照変数(&$encrypted_data)に格納されます。第4引数($padding)には、暗号化の際のパディング方式を指定し、通常はOPENSSL_PKCS1_PADDINGを選びます。処理が成功した場合はtrueを、失敗した場合はfalseを返します。

提供されたサンプルコードでは、openssl_pkey_new関数で一時的なRSA鍵ペアを生成し、その中からopenssl_pkey_get_detailsで公開鍵を取り出しています。そして、この公開鍵と元のメッセージをopenssl_public_encryptに渡して暗号化を実行しています。暗号化されたデータはバイナリ形式のため、通常はbase64_encodeでBase64エンコードしてから扱います。また、鍵リソースは処理後にopenssl_pkey_freeで解放し、エラー発生時にはopenssl_error_stringで原因を確認するよう実装されています。

このサンプルコードは一時的なRSA鍵ペアを生成して公開鍵暗号化を行っていますが、実際のアプリケーションでは鍵ペアは事前に生成し、秘密鍵は厳重に管理する必要があります。暗号化されたデータはバイナリ形式のため、データベース保存やネットワーク転送時にはBase64エンコードが必須です。openssl_public_encryptで直接暗号化できるデータ長には鍵長に応じた制限がありますので、大きなデータを扱う場合は共通鍵暗号と組み合わせるハイブリッド暗号方式の検討が必要です。常にエラーチェックを行い、使用後はopenssl_pkey_freeで鍵リソースを解放するようにしてください。復号には、この公開鍵に対応する秘密鍵が必要となります。

【PHP8.x】openssl_public_encrypt関数の使い方 | いっしー@Webエンジニア