dwgebler / encryption
使用libsodium提供的简单API,为PHP提供对称和非对称加密、解密、数字签名和信息认证的封装。
Requires
- php: >=7.2.0
- ext-mbstring: *
- ext-sodium: *
Requires (Dev)
- phpunit/phpunit: ^8.0
- squizlabs/php_codesniffer: ^3.6
This package is auto-updated.
Last update: 2024-09-19 22:06:14 UTC
README
封装Sodium库的加密API,提供对称和非对称加密、解密、数字签名和信息认证的简单对象接口。
Encryption
类可以生成密钥和密钥对,加密和解密数据,签名和验证数据,以及生成和验证数字签名。
加密消息以base64编码返回,而密钥和密钥以十六进制字符串返回。
这些到和从二进制数据的转换使用了sodium_*
时间安全的函数。
所有底层加密都使用Sodium库完成。
此库需要PHP 7.2或更高版本,并安装了libsodium
(这包含在PHP 7.2或更高版本中,所以你可能已经安装了它)。
安装
通过Composer安装
composer require dwgebler/encryption
用法
为了快速入门,请参阅包含的demo.php
文件。
创建Encryption类的实例。
<?php use Gebler\Encryption\Encryption; $crypt = new Encryption();
对称加密
使用密码
使用encryptWithPassword()
函数使用密码加密消息。使用sodium_crypto_pwhash()
从密码中确定性地派生一个安全密钥。返回的加密数据将以base64编码,并包括用于派生密钥的随机生成的盐。
相应的decryptWithPassword()
函数将使用相同的密码解密消息。
<?php $encrypted = $crypt->encryptWithPassword('This is a secret message', 'SecurePassword'); $decrypted = $crypt->decryptWithPassword($encrypted, 'SecurePassword');
使用密钥
使用encryptWithSecret(string $message, string $key, bool $hexEncoded = true)
函数使用密钥加密消息。此函数期望加密的消息或数据是一个字符串,密钥是一个十六进制字符串。如果您的密钥不是十六进制编码的,可以将false
作为第三个参数传递,表示密钥未编码。
您可以使用generateSecret()
生成密钥,或者使用预先生成的密钥。
或者,您可以将一个空字符串或null的引用传递以生成密钥。
$mySecret = null; $data = "Hello world! This is a secret message."; $result = $crypt->encryptWithSecret($data, $mySecret); // $mySecret has now been populated with a new secret key // Alternatively, generate a new key. $mySecret = $crypt->generateEncryptionSecret(); $result = $crypt->encryptWithSecret($data, $mySecret); // Alternatively, create a key and encode it as hex. // Keys should be 32 bytes long - shorter keys are forced to this length by a deterministic hash, // but this is not recommended. Longer keys will throw an InvalidArgumentException. $mySecret = bin2hex("my_super_secret_key"); // ...or use random_bytes() to generate a random key. $mySecret = bin2hex(random_bytes(32)); $result = $crypt->encryptWithSecret($data, $mySecret); // Or, pass in a raw binary key by setting the `hex` parameter to false. $mySecret = random_bytes(32); $result = $crypt->encryptWithSecret($data, $mySecret, false); // $result is now base64 encoded, e.g. echo $result; // wgYwuB/by9bz+CvHj1EtylicXnRH6hl9hLALsUUPUHaZeO3sEj4hgi8+pKBZGZIG6ueRKw3xpvrG8dRWU9OCn3aMtlwLz8aapUX/oK3L
要解密您的消息,请使用decryptWithSecret()
函数。
$mySecret = "my_super_secret_key"; $message = "This is a test message."; $encrypted = $crypt->encryptWithSecret($message, $mySecret, false); echo $encrypted, PHP_EOL; $decrypted = $crypt->decryptWithSecret($encrypted, $mySecret, false); echo $decrypted, PHP_EOL;
非对称加密
为了执行认证的非对称加密(即消息既被加密,发送者也可以被验证),您需要为发送者生成一对公钥和私钥。您还需要接收者的公钥。
// Generate a new random keypair. $keypair = $crypt->generateEncryptionKeypair(); // Or provide a password to generate a deterministic keypair. $keypair = $crypt->generateEncryptionKeypair("my_super_secret_password"); // Or use a pre-existing keypair. // Once you have a keypair, you can export the public key as a hexadecimal string, // for storage or transmission. $publicKey = $keypair['publicKey']; // The keypair also includes the private key. $privateKey = $keypair['privateKey']; // The full keypair is also provided. This is a string containing both the private and public key. $fullKeypair = $keypair['keypair'];
以Alice向Bob发送消息为例。
$aliceKeypair = $crypt->generateEncryptionKeypair("alice_secret"); // In the real-world, Bob has provided Alice with his public key, but for demo purposes // we'll generate a keypair for him too. $bobKeypair = $crypt->generateEncryptionKeypair("bob_secret"); // Alice encrypts a message for Bob, using his public key and her private key. $message = "Hello Bob! This is a secret message from Alice."; $encrypted = $crypt->encryptWithKey($message, $bobKeypair['publicKey'], $aliceKeypair['privateKey']); // Alice can now transmit $encrypted to Bob. It will look something like this: // hMvdJf2L78ZWcF38WRXJ16q3xXnlsWWfOsbJISPVwJhBtdcWbZ8SquS3oyJD1k6H/lAs+VHXPpDNfYLWO3wMLl+FB8rYUyCe+IZzti3dFL0YljeJ3QreGlrv echo $encrypted, PHP_EOL; // Bob decrypts the message using his private key and the public key of Alice. $decrypted = $crypt->decryptWithKey($encrypted, $bobKeypair['privateKey'], $aliceKeypair['publicKey']); // Hello Bob! This is a secret message from Alice. echo $decrypted, PHP_EOL;
您也可以使用这个库来执行匿名的非对称加密,只使用接收者的公钥。在这种情况下,不需要发送者的私钥,尽管只有接收者(持有相应私钥的人)可以解码消息,但他们无法识别或验证发送者。这类似于openssl_public_encrypt
。
$bobKeypair = $crypt->generateEncryptionKeypair("bob_secret"); // Alice encrypts a message for Bob, using his public key. $message = "Hello Bob! This is a secret message from an unknown sender."; $encrypted = $crypt->encryptWithKey($message, $bobKeypair['publicKey']); // Alice can now transmit $encrypted to Bob. echo $encrypted, PHP_EOL; // Bob decrypts the message using his full keypair. $decrypted = $crypt->decryptWithKey($encrypted, $bobKeypair['keypair']); // Hello Bob! This is a secret message from an unknown sender. echo $decrypted, PHP_EOL;
数字签名
非对称加密对于保护消息很有用,但它也用于验证消息的发送者。
数字签名是一种验证消息发送者以及消息本身的方法,确保它在传输过程中没有被篡改或更改。
// Generate a new random keypair. // Like generateEncryptionKeypair, you can also optionally provide a password to generate a deterministic keypair. $aliceSigningKeypair = $crypt->generateSigningKeypair(); // Alice signs a message for Bob, using her private key. $message = "This is a message signed by Alice."; $signedMessage = $crypt->getSignedMessage($message, $aliceSigningKeypair['privateKey']); // Alice can now transmit $signedMessage to Bob. It will look something like this: // JaI6p6jb5qQ041DiK1Yqbk8u1r/wVAovzy57ELfwrWfhqLCUU9jTzBLH6K6v1VF/8vOxaOZe2r8ch/GUKmfgC1RoaXMgaXMgYSBtZXNzYWdlIHNpZ25lZCBieSBBbGljZS4= // Note: The message itself is NOT encrypted and can be viewed by anyone, by decoding the base64-encoded signed message. echo $signedMessage, PHP_EOL; // Bob can now use Alice's public key to verify the signature and obtain the message part. // If the message has been tampered with, the signature will be invalid and the message will be rejected. $verifiedMessage = $crypt->verifySignedMessage($signedMessage, $aliceSigningKeypair['publicKey']); // This is a message signed by Alice. echo $verifiedMessage, PHP_EOL;
我们还可以为消息生成签名,而不将其附加到消息本身。
$aliceSigningKeypair = $crypt->generateSigningKeypair(); // Alice signs a message for Bob, using her private key. $message = "This is a message signed by Alice."; $signature = $crypt->getMessageSignature($message, $aliceSigningKeypair['privateKey']); // Alice can now transmit the message and signature separately to Bob. // Bob can now use Alice's public key to verify the signature. // If the message has been tampered with, the signature will be invalid and the message will be rejected. $messageAuthenticated = $crypt->verifyMessageSignature($message, $signature, $aliceSigningKeypair['publicKey']); if ($messageAuthenticated === true) { echo "The message has not been tampered with.", PHP_EOL; }
消息认证
我们可以使用共享密钥来生成消息认证码(MAC)并使用它来签名和验证消息,而不是使用非对称密钥。
$message = "This is a message signed anonymously with a secret key."; // We can generate a secure, random 32 byte key, which is returned as a hexadecimal string. $secret = $crypt->generateSigningSecret(); // Or, as long as the key is 32 bytes (256 bits), you can use any other string. $secret = hash("sha256", "my secret key"); // Like with the symmetric encryption functions, you can pass an optional third parameter // to signWithSecret to specify that the secret key is NOT a hexadecimal string. $secret = hash("sha256", "my secret key", true); $signature = $crypt->signWithSecret($message, $secret, false); // Or omit this parameter if the secret is a hexadecimal string. $secret = $crypt->generateSigningSecret(); $signature = $crypt->signWithSecret($message, $secret); // The message can now be either transmitted to someone else who also has the shared secret, // or later verified on the same system, e.g. after being retrieved from a database. $messageAuthenticated = $crypt->verifyWithSecret($signature, $message, $secret); if ($messageAuthenticated === true) { echo "The message has not been tampered with.", PHP_EOL; } // Similarly, pass false as the third parameter if the secret is NOT a hexadecimal string. $secret = hash("sha256", "my secret key", true); $signature = $crypt->signWithSecret($message, $secret, false); $messageAuthenticated = $crypt->verifyWithSecret($signature, $message, $secret, false); if ($messageAuthenticated === true) { echo "The message has not been tampered with.", PHP_EOL; }
许可证
本软件遵循MIT许可证发布。
错误、问题、评论
如果您遇到任何问题或有任何疑问,请通过GitHub提出一个问题。