公開鍵暗号を使用して、JavaScriptで暗号化し、PHPで復号化したいと思います。私はこれを達成できるライブラリを探していましたが、問題があります。
現在、 openpgpjs を探していますが、すべてのブラウザーでサポートが必要であり、テストページでさえ、サポートされているブラウザー(Google Chrome)としてリストされているもののみにエラーがあります。
最終目標に関するメモ:
TCP接続は既にSSLで保護されています。この保護層の主な目的は、意図的または意図しないWebサーバーのロギング、クラッシュダンプなどに対する防御です]
PHP側では、一時的な秘密鍵が生成されます(短時間で期限切れになります)。呼び出し側(Javascriptで)は、期限切れになると新しい公開鍵を要求します。秘密鍵の有効期限が切れる理由は、秘密鍵を保存しているサーバーが後で侵害された場合に、ログに記録された暗号化されたデータの復号化を防ぐためです。
サーバーが侵害されたシナリオ:誰かがデータベースサーバー以外のすべてのマシンのバックアップを取得します(ユーザーとパスワードを見つけても、ファイアウォールのためにデータベースにアクセスできません)。ログに記録されたデータを暗号化した秘密鍵はもはや存在しないため、攻撃者ができることは何もありません。
私はログインページに似たようなものを使用しました。 PHPで復号化できる公開鍵情報(N、e)を使用してログイン資格情報を暗号化します。
JSBN
の一部である次のファイルを使用します。
jsbn.js
-大きな整数で動作するrsa.js
-RSA暗号化のみ(jsbn.jsを使用)rng.js
-基本的なエントロピーコレクターprng4.js
-ARC4 RNGバックエンドデータを暗号化するには:
$pk = '-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----';
$kh = openssl_pkey_get_private($pk);
$details = openssl_pkey_get_details($kh);
function to_hex($data)
{
return strtoupper(bin2hex($data));
}
?>
<script>
var rsa = new RSAKey();
rsa.setPublic('<?php echo to_hex($details['rsa']['n']) ?>', '<?php echo to_hex($details['rsa']['e']) ?>');
// encrypt using RSA
var data = rsa.encrypt('hello world');
</script>
これは、送信されたデータをデコードする方法です。
$kh = openssl_pkey_get_private($pk);
$details = openssl_pkey_get_details($kh);
// convert data from hexadecimal notation
$data = pack('H*', $data);
if (openssl_private_decrypt($data, $r, $kh)) {
echo $r;
}
node-rsa を確認してください。
Node.jsモジュールです
このモジュールは、OpenSSLからRSA公開鍵ルーチンへのアクセスを提供します。サポートはRSAES-OAEPと公開キーによる暗号化、秘密キーによる復号化に限定されます。
たぶん、あなたはそれを移植してブラウザで実行することができます。
[〜#〜] update [〜#〜]
JavascriptのRSAクライアント側ライブラリ:(pidcryptは公式に廃止され、ウェブサイトドメインの有効期限が切れています-含まれるpidcryptと同じライブラリを含む@jackの回答を参照してください)。 https://www.pidder.com/pidcrypt/?page=rsa
PHPサーバー側コンポーネント: http://phpseclib.sourceforge.net/
幸運を!
RSAの実装には注意してください。実際、おそらくRSAはまったく使用すべきではありません。 ( 代わりにlibsodiumを使用してください! )
ライブラリ(たとえば、PHPのOpenSSL拡張機能を直接使用している場合、または最近まで _Zend\Crypt
_ )を使用している場合でも、まだ多くの問題が発生する可能性があります。特に:
このルートを進む前に、 JavaScript暗号化は有害と見なされます を何度か読みたいかもしれません。しかし、それは言った...
crypto_box_seal()
を公開鍵とともに使用して、クライアント側でメッセージを暗号化します。\Sodium\crypto_box_seal_open()
を公開鍵の対応する秘密鍵とともに使用して、メッセージを復号化します。しないでください 。楕円曲線暗号化は、サイドチャネルを使用せずに実装するのがより速く、簡単で、はるかに簡単です。ほとんどのライブラリは既にこれを行っています。 (Libsodium!)
レターへのこれらの推奨事項 に従ってください。あなたが暗号を役に立たなくするミス( SaltStackがしたように など)をStackOverflowに泣かないでください。
シンプルで簡単なRSA暗号化を提供することを目的とする1つのオプション(補完的なJavaScript実装は付属していませんので、お願いしません)は paragonie/easyrsa です。
しかし、実際には、公開鍵暗号の有効なユースケースが見つかった場合、代わりにlibsodiumが必要です。
pidCrypt (js)および phpseclib (php)のRSAの使用例。
この実例では秘密鍵を再利用しないでください。
pidCrypt暗号化
//From the pidCrypt example sandbox
function certParser(cert) {
var lines = cert.split('\n');
var read = false;
var b64 = false;
var end = false;
var flag = '';
var retObj = {
};
retObj.info = '';
retObj.salt = '';
retObj.iv;
retObj.b64 = '';
retObj.aes = false;
retObj.mode = '';
retObj.bits = 0;
for (var i = 0; i < lines.length; i++) {
flag = lines[i].substr(0, 9);
if (i == 1 && flag != 'Proc-Type' && flag.indexOf('M') == 0)//unencrypted cert?
b64 = true;
switch (flag) {
case '-----BEGI':
read = true;
break;
case 'Proc-Type':
if (read)retObj.info = lines[i];
break;
case 'DEK-Info:':
if (read) {
var tmp = lines[i].split(',');
var dek = tmp[0].split(': ');
var aes = dek[1].split('-');
retObj.aes = (aes[0] == 'AES') ? true : false;
retObj.mode = aes[2];
retObj.bits = parseInt(aes[1]);
retObj.salt = tmp[1].substr(0, 16);
retObj.iv = tmp[1];
}
break;
case '':
if (read)b64 = true;
break;
case '-----END ':
if (read) {
b64 = false;
read = false;
}
break;
default : if (read && b64)retObj.b64 += pidCryptUtil.stripLineFeeds(lines[i]);
}
}
return retObj;
}
var strCreditCardPublicKey="-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC\/tI7cw+gnUPK2LqWp50XboJ1i\njrLDn+4\/gPOe+pB5kz4VJX2KWwg9iYMG9UJ1M+AeN33qT7xt9ob2dxgtTh7Mug2S\nn1TLz4donuIzxCmW+SZdU1Y+WNDINds194hWsAVhMC1ClMQTfldUGzQnI5sXvZTF\nJWp\/9jheCNLDRIkAnQIDAQAB\n-----END PUBLIC KEY-----\n";
var objParams=certParser(strCreditCardPublicKey);
var binaryPrivateKey=pidCryptUtil.decodeBase64(objParams.b64);
var rsa=new pidCrypt.RSA();
var asn=pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(key));
var tree=asn.toHexTree();
rsa.setPublicKeyFromASN(tree);
var strHexSensitiveDataEncrypted=rsa.encrypt("4111111111111111");
var strBase64SensitiveDataEncrypted=pidCryptUtil.fragment(pidCryptUtil.encodeBase64(pidCryptUtil.convertFromHex(strHexSensitiveDataEncrypted)), 64))
console.log(strBase64SensitiveDataEncrypted);
。
phpseclib復号化
require_once("Crypt/RSA.php");
function decrypt($strBase64CipherText)
{
//CRYPT_RSA_MODE_INTERNAL is slow
//CRYPT_RSA_MODE_OPENSSL is fast, but requires openssl to be installed, configured and accessible.
define("CRYPT_RSA_MODE", CRYPT_RSA_MODE_INTERNAL);
$rsa=new Crypt_RSA();
//$strPrivateKey=file_get_contents("private.pem");
//This private key is for example purposes
//DO NOT REUSE
$strPrivateKey="-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDBNHK7R2CCYGqljipbPoj3Pwyz4cF4bL5rsm1t8S30gbEbMnKn
1gpzteoPlKp7qp0TnsgKab13Fo1d+Yy8u3m7JUd/sBrUa9knY6dpreZ9VTNul8Bs
p2LNnAXOIA5xwT10PU4uoWOo1v/wn8eMeBS7QsDFOzIm+dptHYorB3DOUQIDAQAB
AoGBAKgwGyxy702v10b1omO55YuupEU3Yq+NopqoQeCyUnoGKIHvgaYfiwu9sdsM
ZPiwxnqc/7Eo6Zlw1XGYWu61GTrOC8MqJKswJvzZ0LrO3oEb8IYRaPxvuRn3rrUz
K7WnPJyQ2FPL+/D81NK6SH1eHZjemb1jV9d8uGb7ifvha5j9AkEA+4/dZV+dZebL
dRKtyHLfbXaUhJcNmM+04hqN1DUhdLAfnFthoiSDw3i1EFixvPSiBfwuWC6h9mtL
CeKgySaOkwJBAMSdBhn3C8NHhsJA8ihQbsPa6DyeZN+oitiU33HfuggO3SVIBN/7
HmnuLibqdxpnDOtJT+9A+1D29TkNENlTWgsCQGjVIC8xtFcV4e2s1gz1ihSE2QmU
JU9sJ3YeGMK5TXLiPpobHsnCK8LW16WzQIZ879RMrkeDT21wcvnwno6U6c8CQQCl
dsiVvXUmyOE+Rc4F43r0VRwxN9QI7hy7nL5XZUN4WJoAMBX6Maos2Af7NEM78xHK
SY59+aAHSW6irr5JR351AkBA+o7OZzHIhvJfaZLUSwTPsRhkdE9mx44rEjXoJsaT
e8DYZKr84Cbm+OSmlApt/4d6M4YA581Os1eC8kopewpy
-----END RSA PRIVATE KEY-----
";
$strPrivateKey=preg_replace("/[ \t]/", "", $strPrivateKey);//this won't be necessary when loading from PEM
$rsa->loadKey($strPrivateKey);
$binaryCiphertext=base64_decode($strBase64CipherText);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$strBase64DecryptedData=$rsa->decrypt($binaryCiphertext);
return base64_decode($strBase64DecryptedData);
}
//The pidCrypt example implementation will output a base64 string of an encrypted base64 string which contains the original data, like this one:
$strBase64CipherText="JDlK7L/nGodDJodhCj4uMw0/LW329HhO2EvxNXNUuhe+C/PFcJBE7Gp5GWZ835fNekJDbotsUFpLvP187AFAcNEfP7VAH1xLhhlB2a9Uj/z4Hulr4E2EPs6XgvmLBS3MwiHALX2fES5hSKY/sfSUssRH10nBHHO9wBLHw5mRaeg=";
$binaryDecrypted=decrypt($strBase64CipherText);
//should output '4111111111111111'
var_export($binaryDecrypted);
これは、対称(秘密鍵)暗号化システムである Tiny Encryption Algorithm に基づいています。それにもかかわらず、軽量であるためにあなたの役に立つかもしれません。
これは次の場所にあります。 http://babelfish.nl/Projecten/JavascriptPhpEncryption