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

作成日: 更新日:

openssl_private_decrypt関数は、PHPのOpenSSL拡張機能に属し、非対称暗号方式の原理に基づき、秘密鍵を使用して暗号化されたデータを復号する関数です。この関数は、公開鍵で暗号化されたデータを、対応する秘密鍵を使って元の平文に戻すことを目的としています。

具体的には、第一引数に復号したい暗号文、第二引数に復号後の平文を格納する変数を参照渡しで指定します。第三引数には、復号に使用する秘密鍵のリソースまたはPEM形式の秘密鍵文字列を渡します。そして、第四引数にはパディング方式を指定し、これはデータのセキュリティと整合性を保つ上で非常に重要です。

この関数は、復号処理が成功した場合はtrueを、失敗した場合はfalseを返します。復号に失敗した場合、具体的なエラー情報はopenssl_error_string()関数を用いて取得することができます。この関数は、セキュアな通信やデータの機密性を確保するために、特に公開鍵で暗号化されたメッセージの受信側で利用されることが多いです。秘密鍵は厳重に管理する必要があり、その取り扱いには十分な注意が求められます。

基本的な使い方

構文(syntax)

<?php
// 暗号化されたデータ(文字列)
$encryptedData = '...';

// プライベートキー(ファイルパス、PEM形式の文字列、またはOpenSSLAsymmetricKeyオブジェクト)
$privateKey = 'file:///path/to/private.key';

// 復号化されたデータが格納される変数(参照渡し)
$decryptedData = '';

// プライベートキーを使用してデータを復号化する
// 成功した場合は true、失敗した場合は false を返す
$success = openssl_private_decrypt(
    $encryptedData,
    $decryptedData,
    $privateKey,
    OPENSSL_PKCS1_PADDING // オプションのパディングモード、デフォルトは OPENSSL_PKCS1_PADDING
);

if ($success) {
    // $decryptedData に復号化されたデータが格納されています
    // 例: echo $decryptedData;
} else {
    // 復号化に失敗しました
    // 例: echo "復号化エラー: " . openssl_error_string();
}

引数(parameters)

string $data, string &$decrypted_data, mixed $private_key, int $padding = OPENSSL_PKCS1_PADDING

  • string $data: 復号化したい暗号化されたデータ
  • string &$decrypted_data: 復号化されたデータを格納する変数(参照渡し)
  • mixed $private_key: 復号化に使用する秘密鍵
  • int $padding = OPENSSL_PKCS1_PADDING: パディングの種類を指定する整数(デフォルトはPKCS1)

戻り値(return)

bool

openssl_private_decrypt 関数は、秘密鍵を使用してデータを復号化する処理が成功したかどうかを示す真偽値 (bool) を返します。成功した場合は true を、失敗した場合は false を返します。

サンプルコード

PHP: openssl_private_decryptで秘密鍵復号する

<?php

/**
 * OpenSSLを使用してRSA暗号化と復号化を実演する関数。
 * 公開鍵で暗号化し、秘密鍵で復号化する流れを示します。
 */
function demonstrateOpensslPrivateDecrypt(): void
{
    // --- 1. RSA鍵ペアの生成 ---
    // 実際のアプリケーションでは、鍵ペアは一度生成され、安全に保管されます。
    // この例では、デモンストレーションのために実行時に生成します。
    $config = [
        'private_key_bits' => 2048, // 鍵の強さ:2048ビットが一般的です
        'private_key_type' => OPENSSL_KEYTYPE_RSA, // RSAアルゴリズムを使用します
    ];

    // 新しい秘密鍵リソースを生成します
    $privateKeyResource = openssl_pkey_new($config);

    if (false === $privateKeyResource) {
        echo 'エラー: 秘密鍵リソースの生成に失敗しました。OpenSSLエラー: ' . openssl_error_string() . PHP_EOL;
        return;
    }

    // 秘密鍵を文字列形式でエクスポートします
    openssl_pkey_export($privateKeyResource, $privateKeyString);

    // 秘密鍵リソースから公開鍵の詳細を取得します
    $publicKeyDetails = openssl_pkey_get_details($privateKeyResource);

    if (false === $publicKeyDetails) {
        echo 'エラー: 公開鍵の詳細取得に失敗しました。OpenSSLエラー: ' . openssl_error_string() . PHP_EOL;
        return;
    }

    $publicKeyString = $publicKeyDetails['key'];

    echo "--- RSA鍵ペア生成完了 ---" . PHP_EOL;
    echo "秘密鍵 (先頭100文字): " . substr($privateKeyString, 0, 100) . "..." . PHP_EOL;
    echo "公開鍵 (先頭100文字): " . substr($publicKeyString, 0, 100) . "..." . PHP_EOL . PHP_EOL;

    // --- 2. 暗号化するデータの準備 ---
    $originalData = 'これは、RSAを使用して暗号化および復号化される秘密のメッセージです。';
    echo "元のデータ: " . $originalData . PHP_EOL . PHP_EOL;

    // --- 3. 公開鍵を使用した暗号化 ---
    // openssl_public_encrypt() を使用してデータを暗号化します。
    // openssl_private_decrypt() のデフォルトと互換性のある OPENSSL_PKCS1_PADDING を使用します。
    $encryptedData = '';
    if (!openssl_public_encrypt($originalData, $encryptedData, $publicKeyString, OPENSSL_PKCS1_PADDING)) {
        echo 'エラー: 暗号化に失敗しました。OpenSSLエラー: ' . openssl_error_string() . PHP_EOL;
        return;
    }

    echo "暗号化されたデータ (表示のためにBase64エンコード): " . base64_encode($encryptedData) . PHP_EOL . PHP_EOL;

    // --- 4. 秘密鍵を使用した復号化 (openssl_private_decrypt) ---
    // openssl_private_decrypt() は、公開鍵で暗号化されたデータを秘密鍵を使用して復号化します。
    // デフォルトのパディングは OPENSSL_PKCS1_PADDING であり、暗号化ステップと一致します。
    $decryptedData = '';
    if (openssl_private_decrypt($encryptedData, $decryptedData, $privateKeyString, OPENSSL_PKCS1_PADDING)) {
        echo "復号化に成功しました!" . PHP_EOL;
        echo "復号化されたデータ: " . $decryptedData . PHP_EOL . PHP_EOL;
    } else {
        echo 'エラー: 復号化に失敗しました。OpenSSLエラー: ' . openssl_error_string() . PHP_EOL;
        return;
    }

    // --- 5. 検証 ---
    if ($originalData === $decryptedData) {
        echo "検証: 元のデータと復号化されたデータは一致します。(成功)" . PHP_EOL;
    } else {
        echo "検証: 元のデータと復号化されたデータは一致しません。(失敗)" . PHP_EOL;
    }

    // 鍵リソースを解放します
    openssl_pkey_free($privateKeyResource);
}

// デモンストレーション関数を実行します
demonstrateOpensslPrivateDecrypt();

?>

PHPのopenssl_private_decrypt関数は、RSA暗号方式において、公開鍵で暗号化されたデータを対応する秘密鍵を使って復号化する際に使用されます。この関数は、安全に送信された暗号化メッセージを元の平文に戻す重要な役割を果たします。

サンプルコードでは、まずRSA鍵ペア(公開鍵と秘密鍵)が生成され、その後、特定のデータが公開鍵によって暗号化されます。この暗号化されたデータがopenssl_private_decrypt関数の第一引数$dataとして渡されます。第二引数&$decrypted_dataは、復号化されたデータが格納される変数であり、参照渡しで結果を受け取ります。第三引数$private_keyには、復号化に使用する秘密鍵を指定します。第四引数$paddingはパディング方式を定義し、暗号化時と一致するOPENSSL_PKCS1_PADDINGをデフォルトで使用します。

この関数は、復号化が成功した場合はtrueを、失敗した場合はfalseを戻り値として返します。これにより、公開鍵でロックされた情報を、対応する秘密鍵を持つ正規のユーザーだけが解読できるようになります。

本サンプルコードの注意点として、秘密鍵はシステムのセキュリティを左右する非常に重要な情報であり、厳重に管理し、決して外部に漏らさないでください。実際のシステムでは鍵は安全な場所に保管され、コード内で毎回生成するべきではありません。また、暗号化(openssl_public_encrypt)と復号化(openssl_private_decrypt)では、必ず同じパディング方式(例: OPENSSL_PKCS1_PADDING)を指定する必要があります。openssl_private_decrypt関数は、公開鍵で暗号化されたデータを秘密鍵で復号する用途で使われます。関数の戻り値がfalseの場合、復号に失敗しているため、必ずエラーチェックを行い、openssl_error_string()で詳細を確認する習慣をつけましょう。データの機密性を保つ上でこれらの点は非常に重要です。

openssl_private_decryptで復号する

<?php

/**
 * Demonstrates the use of openssl_private_decrypt for RSA decryption.
 *
 * This function generates a public/private key pair, encrypts a given message
 * using the public key, and then decrypts it using the private key.
 * It also includes error checking, which is crucial for diagnosing issues
 * commonly associated with 'openssl_private_decrypt not working'.
 *
 * @param string $originalMessage The message to be encrypted and then decrypted.
 * @return void
 */
function decryptWithOpensslPrivateDecrypt(string $originalMessage): void
{
    echo "Original Message: " . $originalMessage . PHP_EOL;

    // 1. Generate a new private and public key pair
    $privateKeyResource = openssl_pkey_new([
        "digest_alg" => "sha512",
        "private_key_bits" => 2048,
        "private_key_type" => OPENSSL_KEYTYPE_RSA,
    ]);

    if ($privateKeyResource === false) {
        echo "Error: Failed to generate private key." . PHP_EOL;
        // Output any OpenSSL errors for debugging
        while ($error = openssl_error_string()) {
            echo "OpenSSL Error: " . $error . PHP_EOL;
        }
        return;
    }

    // Export the private key to a string
    openssl_pkey_export($privateKeyResource, $privateKeyContent);

    // Extract the public key details and get the public key string
    $publicKeyDetails = openssl_pkey_get_details($privateKeyResource);
    $publicKeyContent = $publicKeyDetails['key'];

    echo "\n--- Key Pair Generated ---" . PHP_EOL;
    // For brevity, keys are not printed in full.
    // echo "Private Key (first 100 chars): " . substr($privateKeyContent, 0, 100) . "..." . PHP_EOL;
    // echo "Public Key (first 100 chars): " . substr($publicKeyContent, 0, 100) . "..." . PHP_EOL;

    // 2. Encrypt the original message using the public key
    $encryptedData = '';
    $encryptionSuccess = openssl_public_encrypt($originalMessage, $encryptedData, $publicKeyContent);

    if ($encryptionSuccess === false) {
        echo "\nError: Public key encryption failed." . PHP_EOL;
        while ($error = openssl_error_string()) {
            echo "OpenSSL Error: " . $error . PHP_EOL;
        }
        openssl_pkey_free($privateKeyResource); // Free the key resource
        return;
    }

    echo "\n--- Encryption ---" . PHP_EOL;
    // Display encrypted data in base64 format as it's binary
    echo "Encrypted Data (base64): " . base64_encode($encryptedData) . PHP_EOL;

    // 3. Decrypt the data using the private key
    $decryptedData = '';
    // The $padding parameter defaults to OPENSSL_PKCS1_PADDING, matching encryption.
    $decryptionSuccess = openssl_private_decrypt($encryptedData, $decryptedData, $privateKeyContent);

    echo "\n--- Decryption ---" . PHP_EOL;
    if ($decryptionSuccess === true) {
        echo "Decryption Successful!" . PHP_EOL;
        echo "Decrypted Message: " . $decryptedData . PHP_EOL;

        // Verify if the decrypted message matches the original
        if ($originalMessage === $decryptedData) {
            echo "Verification: Original and decrypted messages match." . PHP_EOL;
        } else {
            echo "Verification: WARNING! Original and decrypted messages DO NOT match." . PHP_EOL;
        }
    } else {
        // This block is essential for debugging "not working" issues
        echo "Error: Private key decryption failed." . PHP_EOL;
        while ($error = openssl_error_string()) {
            echo "OpenSSL Error: " . $error . PHP_EOL;
        }
    }

    // Free the key resource when no longer needed
    openssl_pkey_free($privateKeyResource);
}

// --- Example Usage ---
// This example demonstrates a full cycle of encryption and decryption.
// Ensure the OpenSSL extension is enabled in your PHP configuration.
decryptWithOpensslPrivateDecrypt("Hello, System Engineers! This is a secret message to be secured.");

PHPのopenssl_private_decrypt関数は、RSA暗号方式において、公開鍵で暗号化されたデータを秘密鍵を用いて安全に復号するために使用されます。この関数は、主にopenssl_public_encryptで作成された暗号文を元の平文に戻す際に利用されます。

引数$dataには復号したい暗号化されたデータ(バイナリ形式)を指定します。&$decrypted_dataは、復号に成功した場合に元のデータが格納される変数で、参照渡しのため事前に定義しておく必要があります。$private_keyには復号に使用する秘密鍵のリソースまたは文字列を渡します。$paddingはパディング方式を指定するオプションですが、通常はデフォルトのOPENSSL_PKCS1_PADDINGを使用します。

関数は処理が成功するとtrueを、失敗した場合はfalseを返します。サンプルコードでは、鍵の生成から公開鍵での暗号化、そしてopenssl_private_decryptによる秘密鍵での復号までの一連のプロセスを具体的に示しています。特に、復号がうまくいかない("not working")といった問題が発生した際には、openssl_error_string()関数を用いて具体的なエラーメッセージを確認し、原因を特定することが非常に重要ですし、これは安全なシステム開発において不可欠な要素となります。

openssl_private_decrypt関数は、公開鍵で暗号化されたデータを秘密鍵で復号するために使用します。このサンプルコードでは、鍵の生成から暗号化、復号までの一連の流れを理解できます。特に重要な注意点は、暗号化時と復号時でパディングモードを必ず一致させることです。通常はデフォルトのOPENSSL_PKCS1_PADDINGを使いますが、異なるパディングを使用すると復号に失敗します。復号がうまくいかない場合は、openssl_error_string()関数でOpenSSLのエラーメッセージを確認し、原因を特定することが重要です。また、この関数を利用するにはPHPのOpenSSL拡張が有効になっている必要があります。秘密鍵はシステム上で厳重に管理し、外部への漏洩がないように運用してください。暗号化されたデータはバイナリ形式のため、表示や通信時にはBase64エンコードなどを利用すると良いでしょう。

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