如果你想对一个字符串进行加密和解密**(只有当数据离开当前机器,并且发送方和接收方机器被允许解密来自对方的数据**时),你可以使用下面的例子。加密的数据将永远是动态的,所以对于给定的字符串,其结果将总是不同的。它在PHP7.2以上的机器上使用Sodium。**注意:**阅读代码中的注释。
类别
你可能需要在你的composer.json 文件中添加"ext-sodium": "*" 。也请阅读这里的相关函数的具体作用。
/**
* You have to use same "keys" and "nonce" to encrypt plain data and decrypt encrypted data.
* Use if the sender and receiver machines are allowed to decrypt the data coming from each other. A <-> B
*
* Use bin2hex() on encrypted data before sending.
* Use hex2bin() on encrypted data before decrypting.
*/
class Both
{
/**
* This is what sender computer A does.
*
* @param string $plainData This is what sender computer A will send to receiver computer B
* @param string $nonce
* @param string $aSecretKey This belongs to sender computer A where the message will be sent from
* @param string $bComputersPublicKey This belongs to receiver computer B where the message will be sent to
*
* @return string
*/
public function encryptA(string $plainData, string $nonce, string $aSecretKey, string $bComputersPublicKey): string
{
return $nonce.sodium_crypto_box($plainData, $nonce, $aSecretKey.$bComputersPublicKey);
}
/**
* This is what receiver computer B does.
*
* @param string $encryptedData This comes from the sender computer A
* @param string $nonce
* @param string $bSecretKey This belongs to receiver computer B where the message will be handled
* @param string $aComputersPublicKey This belongs to sender computer A where the message comes from
*
* @return string
*/
public function decryptB(string $encryptedData, string $nonce, string $bSecretKey, string $aComputersPublicKey): string
{
return sodium_crypto_box_open($encryptedData, $nonce, $bSecretKey.$aComputersPublicKey);
}
/**
* This is what sender computer B does.
*
* @param string $plainData This is what sender computer B will send to receiver computer A
* @param string $nonce
* @param string $bSecretKey This belongs to sender computer B where the message will be sent from
* @param string $aComputersPublicKey This belongs to receiver computer A where the message will be sent to
*
* @return string
*/
public function encryptB(string $plainData, string $nonce, string $bSecretKey, string $aComputersPublicKey): string
{
return $nonce.sodium_crypto_box($plainData, $nonce, $bSecretKey.$aComputersPublicKey);
}
/**
* This is what receiver computer A does.
*
* @param string $encryptedData This comes from the sender computer B
* @param string $nonce
* @param string $aSecretKey This belongs to receiver computer A where the message will be handled
* @param string $bComputersPublicKey This belongs to sender computer B where the message comes from
*
* @return string
*/
public function decryptA(string $encryptedData, string $nonce, string $aSecretKey, string $bComputersPublicKey): string
{
return sodium_crypto_box_open($encryptedData, $nonce, $aSecretKey.$bComputersPublicKey);
}
}
测试
class BothTest extends TestCase
{
private $aComputersKeyPair;
private $aComputersSecretKey;
private $aComputersPublicKey;
private $bComputersKeyPair;
private $bComputersSecretKey;
private $bComputersPublicKey;
protected function setUp()
{
$this->aComputersKeyPair = sodium_crypto_box_keypair();
$this->aComputersSecretKey = sodium_crypto_box_secretkey($this->aComputersKeyPair);
$this->aComputersPublicKey = sodium_crypto_box_publickey($this->aComputersKeyPair);
$this->bComputersKeyPair = sodium_crypto_box_keypair();
$this->bComputersSecretKey = sodium_crypto_box_secretkey($this->bComputersKeyPair);
$this->bComputersPublicKey = sodium_crypto_box_publickey($this->bComputersKeyPair);
}
public function testEncryptA(): void
{
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$dataToBeSent = (new Both())
->encryptA('inanzzz', $nonce, $this->aComputersSecretKey, $this->bComputersPublicKey);
$this->assertIsString($dataToBeSent);
}
public function testDecryptB(): void
{
// Sender
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$dataReceived = (new Both())
->encryptA('inanzzz', $nonce, $this->aComputersSecretKey, $this->bComputersPublicKey);
// Receiver
$nonce = mb_substr($dataReceived, 0, 24, '8bit');
$dataReceived = mb_substr($dataReceived, 24, null, '8bit');
$result = (new Both())
->decryptB($dataReceived, $nonce, $this->bComputersSecretKey, $this->aComputersPublicKey);
$this->assertSame('inanzzz', $result);
}
public function testEncryptB(): void
{
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$dataToBeSent = (new Both())
->encryptB('inanzzz', $nonce, $this->bComputersSecretKey, $this->aComputersPublicKey);
$this->assertIsString($dataToBeSent);
}
public function testDecryptA(): void
{
// Sender
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$dataReceived = (new Both())
->encryptB('inanzzz', $nonce, $this->bComputersSecretKey, $this->aComputersPublicKey);
// Receiver
$nonce = mb_substr($dataReceived, 0, 24, '8bit');
$dataReceived = mb_substr($dataReceived, 24, null, '8bit');
$result = (new Both())
->decryptA($dataReceived, $nonce, $this->aComputersSecretKey, $this->bComputersPublicKey);
$this->assertSame('inanzzz', $result);
}
}