dwgebler/encryption

使用libsodium提供的简单API,为PHP提供对称和非对称加密、解密、数字签名和信息认证的封装。

1.1.0 2022-12-11 19:32 UTC

This package is auto-updated.

Last update: 2024-09-19 22:06:14 UTC


README

Build Status!

封装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提出一个问题。