web-dev-qa-db-ja.com

公開鍵/秘密鍵を使用してPHPのデータを暗号化する方法は?

自分のサイトから送信されたときにユーザーエージェントに他のサイトに渡してもらいたいデータの小さな文字列(1kb未満)があります。他のサイトが私が文字列Iを作成したサイトであることを確認するために、2つのオプションがあります。

  1. サーバーは確認のために私にpingを返します(Paypal、openidなど)。
  2. メッセージを送信したことを証明するために公開鍵/秘密鍵を使用します(PGP、DKIMなど)。

HMACをセットアップしたくないのは、サイトごとにカスタムキーを使用する必要があるため、面倒です。

これらの2つの選択肢のうち、#2は帯域幅を節約するため、より良い選択肢のように思われます。

では、PHPを使用して公開鍵/秘密鍵の暗号化を設定するにはどうすればよいですか?欠点はありますか?

14
Xeoncross

OpenSSLを使用してS/MIMEパブリック/プライベートキーペアを作成し、OpenSSLコマンドを使用して暗号化と復号化を行います。 opensslはほとんどのLinuxオペレーティングシステムに含まれていますが、PGPには含まれていないため、これはPGPを使用するよりも優れていると思います。 OpenSSLも標準ベースであり、コマンドを停止すると、一般的に操作が簡単になります。

私は「純粋なPHP」ソリューションに対して推奨しました(純粋なPHPとは、PHPを使用して既存のライブラリまたは別の実行可能ファイルを呼び出すのではなく、PHPで暗号化を行うことを意味します)。 PHPで一括暗号化を実行したい。遅すぎる。OpenSSLを使用したい。パフォーマンスが高く、セキュリティが十分に理解されているからです。

これが魔法です。

X.509キーを作成するには:

$subj="/C=US/ST=California/L=Remote/O=Country Govt./OU=My Dept/CN=Mr. Agent/[email protected]"
openssl req -x509 -newkey rsa:1024 -keyout mycert.key -out mycert.pem -nodes -subj $subj

これにより、秘密鍵がmycert.keyに、公開鍵がmycert.pemに配置されます。秘密鍵はパスワードで保護されていません。

ここで、S/MIMEを使用してメッセージに署名するには:

openssl smime -sign -signer mycert.pem -inkey mycert.key <input >output

S/MIMEでメッセージを暗号化するには:

openssl smime -encrypt -recip yourcert.pem <input >output

S/MIMEでメッセージを復号化するには:

openssl smime -decrypt -inkey mycert.key -certfile mycert.pem <input >output

C言語バインディングからOpenSSLを使用するデモもいくつかありますが、PHPからは使用できません。

11
vy32

PHP OpenSSL関数を使用して秘密鍵と公開鍵のペアを作成する:

// Configuration settings for the key
$config = array(
    "digest_alg" => "sha512",
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
);

// Create the private and public key
$res = openssl_pkey_new($config);

// Extract the private key into $private_key
openssl_pkey_export($res, $private_key);

// Extract the public key into $public_key
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"];

次に、次のような秘密鍵と公開鍵を使用して暗号化および復号化できます。

// Something to encrypt
$text = 'This is the text to encrypt';

echo "This is the original text: $text\n\n";

// Encrypt using the public key
openssl_public_encrypt($text, $encrypted, $public_key);

$encrypted_hex = bin2hex($encrypted);
echo "This is the encrypted text: $encrypted_hex\n\n";

// Decrypt the data using the private key
openssl_private_decrypt($encrypted, $decrypted, $private_key);

echo "This is the decrypted text: $decrypted\n\n";
18
Eborbob

ルール1:自分で実装するのではなく、ライブラリを使用します。

どのライブラリ? これが私の推奨するPHP公開鍵暗号ライブラリ

  1. Halite 、libsodiumに依存します(ただし、セキュリティに加えて、シンプルさと使いやすさを強調しています)。
  2. libsodium 、PECLから
  3. EasyRSA 、最も安全なモードでRSAを使用して安全な公開鍵暗号化と公開鍵署名を実装します(PKCS1v1.5ではありません!)
  4. phpseclib 、EasyRSAが便乗します。

一般に、セキュリティが目標である場合は、libsodiumが必要になります。 Haliteを使用するかどうかは好みの問題です。

3

PGPは良いオプションです-それは適切かつ完全に実装されています(つまり、PGPのセキュリティミスの余地はほとんどありません)。 this SO question は、GnuPGとのインターフェースに役立つと思います。問題は、他のサイトがあなたの署名を検証するかどうか、そしてどのように検証するかです。どちらかに従う必要があります。検証メカニズムの要件、またはそれらのサイトが検証に使用する独自のモジュールを提供します。

また、OAuthまたはOpenIDを使用して、これらの他のサイトのユーザーを識別することもできますが、私はこれらのテクノロジーの専門家ではありません。

PHPおよびPythonでopenSSLを使用した暗号化と復号化の例を記述しました

http://glynrob.com/php/hashing-and-public-key-encryption/

利用可能なGithubソースコード。

これを機能させるには、復号化の場所で秘密鍵を使用できる必要があることを忘れないでください。

1
GlynRob