我正在对新库“ Libsodium”进行一些实验。基于https://www.zimuel.it/slides/zendcon2018/sodium#/21幻灯片。在此幻灯片中,显示了有关使用钠进行加密和解密的示例。
$msg = 'This is a super secret message!';
// Generating an encryption key and a nonce
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES); // 256 bit
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // 24 bytes
// Encrypt
$ciphertext = sodium_crypto_secretbox($msg, $nonce, $key);
// Decrypt
$plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
echo $plaintext === $msg ? 'Success' : 'Error';
我在这样的PHP类方法中使用了此方法:
public function sodium_encrypt($p_sPlaintext)
{
try{
if(!empty($p_sPlaintext) && is_string($p_sPlaintext)){
// Generating an encryption key and a nonce
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES); // 256 bit
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // 24 bytes
// Encrypt Note: the encryption is always authenticated, you need to store also nonce + ciphertext
$eCiphertext = sodium_crypto_secretbox($p_sPlaintext, $nonce, $key);
$eCryptotext = $nonce.$eCiphertext;
if(!empty($eCiphertext)){
return($eCiphertext);
} else{
throw new Exception('clse004'); // Error trigger
}
} else{
throw new Exception('clse005'); // Error trigger
}
} catch (Exception $e){
echo("<br>Errormessage, code: ".$e->getMessage());
}
}
它的工作原理应该是应该的,那里没有问题。但是..... :-)总是有一个'but'。
例如,如果我使用此方法来加密电子邮件地址,并在用户登录凭据时将其存储在数据库中,则它们是其凭据的唯一加密。下次用户输入其凭据并进行加密时,由于$ key和$ nonce的随机生成,我最终在数据库中找到了他。
如果我生成自己的密钥,而不是随机密钥:(https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx)
$key = "4D6251655468576D597133743677397A24432646294A404E635266556A586E32"; // 256 bit hex
然后我收到消息:“密钥大小应为SODIUM_CRYPTO_SECRETBOX_KEYBYTES字节”。
使用键:
$key = "E)H@McQfTjWnZr4u7w!z%C*F-JaNdRgU"; // 256 bit non hex
那个问题也解决了。
然后,由于随机随机数,$密文仍然是随机的。用非随机随机数替换随机化器,例如:(https://www.random.org/bytes/)
$nonce = "d80ac8385bb52cef7920ded5bda4de50697efc95ea53d81b" ; // 24 bytes hex
显示此消息:“立即大小应该为SODIUM_CRYPTO_SECRETBOX_NONCEBYTES字节”。
与:相同
$nonce = "249206220193104991548714284109130186236311295118249161302345616 " ; // 24 bytes decimal
$nonce = "056073032127157034374115050245203151150054323272014260311360377272100266" ; // 24 bytes octal
目前,我当前的方法看起来像:
public function sodium_encrypt($p_sPlaintext)
{
try{
if(!empty($p_sPlaintext) && is_string($p_sPlaintext)){
// Generating an encryption key and a nonce
$key = "E)H@McQfTjWnZr4u7w!z%C*F-JaNdRgU"; // 256 bit
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); // 24 bytes
// Encrypt Note: the encryption is always authenticated, you need to store also nonce + ciphertext
$eCiphertext = sodium_crypto_secretbox($p_sPlaintext, $nonce, $key);
//$eCryptoText = $nonce.$eCiphertext;
echo $eCiphertext;
if(!empty($eCiphertext)){
return($eCiphertext);
} else{
throw new Exception('clse004'); // Error trigger
}
exit();
} else{
throw new Exception('clse005'); // Error trigger
}
} catch (Exception $e){
echo("<br>Errormessage, code: ".$e->getMessage());
}
}
我看过https://download.libsodium.org/doc/secret-key_cryptography,但找不到找到一种可在此加密实例中使用的非随机(秘密)方法的解决方案。有人有想法吗?是否有更多的人在PHP中使用Sodium?欢迎任何输入。
我知道此消息很旧并且可能已解决,但是我想这可能会有所帮助。
NONCE为24个字符长。 ->这几乎就是答案。但是,如果您尝试使随机数(包括密钥)不是随机的,则输出将不再为单个数据提供一系列无尽的随机字符。容易说成[[one to one。无论如何,KEY是32个字符。让我们尝试这个例子。
<?php
class justEncrypt {
private $key = 'vDIa5JdknBqfrKOu8d7UpddnBMCH1vza'; //32 characters
private $nonce = 'Ra5LeH7ntW2rvkz3dmqI5Stx'; //24 characters
public function sodiumStaticEncrypt(string $data) {
$encrypted = base64_encode(
sodium_crypto_secretbox(
$data,
$this->nonce,
$this->key
)
);
return $encrypted;
}
}
测试脚本:
<?php $site = new justEncrypt; // I feel like I should not have done this echo $site->sodiumStaticEncrypt("It's better late than never!");
将具有5Was2l9V0RgsgEm5csEbXnCaIxLkWwWiOxnHBgrej9+Ipyqn4ehn8VImFa8=
的输出,仅是因为您不希望它变得随机,对吧?检索数据相对容易。只需添加此代码:
public function sodiumStaticDecrypt(string $data) { // decode the base64 on $data first $decrypt = base64_decode($data); $decrypted = sodium_crypto_secretbox_open($data,$this->nonce,$this->key); return $decrypted; }
因此:
<?php echo $site->sodiumStaticDecrypt('5Was2l9V0RgsgEm5csEbXnCaIxLkWwWiOxnHBgrej9+Ipyqn4ehn8VImFa8=');
它将返回为纯文本:应该是24个字符长,不要多,不能少;和KEY应该为32个字符长,不能超过,不能少于。无论随机数和密钥每次都是随机的,也可以使用常规的钠随机加密(用于保存电子邮件,用户名等)。但这不是问题。无论如何,我建议不要将其设置为静态,因为它的设计目的不是一个。It's better late than never!
。无论您做什么,只要不更改密钥和随机数,加密就永远不会改变。就像一对一加密。只要确保没有人知道密钥和随机数,因为一切都会变得毫无用处。不要忘记
NONCE
好吧,我希望您已经解决了这个问题,希望对您有所帮助(即使我确实认为,也没有。)>