有没有一种方法可以在PHP中使用无随机随机随机数的钠加密



我正在对新库"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());
}
}

它工作正常,没有问题。但是…..:-(总有一个"但是"。

例如,如果我使用此方法加密电子邮件地址,并将其作为用户登录凭据存储在数据库中,则这些凭据是对其凭据的唯一加密。下次用户输入他的凭据并对其进行加密时,由于$key和$nonce的随机生成,我可能会在DB中找到他。

如果我生成自己的密钥,而不是随机密钥:(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

此消息显示为:"nonce大小应为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中使用钠吗?欢迎任何意见。

我知道这个消息很旧,可能已经解决了,但我想这可能会有所帮助。

NONCE是24个字符长。->这几乎就是答案。但是,如果您试图使nonce不随机,包括密钥,那么输出将不再是单个数据的一系列无休止的随机字符。这很容易被说成是一对一。无论如何,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=');

并且它将返回到纯文本:CCD_ 2。

无论你做什么,只要你不更改密钥和随机数,加密永远不会改变。这就像一对一加密。只要确保没有人知道密钥和nonce,因为一切都会变得无用。不要忘记NONCE应该是24个字符长,不能多,不能少;并且KEY应该是32个字符长,而不是更多,也不是更少。

无论随机数和密钥每次都是随机的,也可以使用常规的钠随机加密(用于保存电子邮件、用户名等(。但这不是问题所在。无论如何,我建议不要让它成为静态的,因为它的设计不是一个。

好吧,我希望你已经解决了这个问题,我希望这在某种程度上有所帮助(即使我真的认为,它没有(。

@Tesmurd101上只有一条评论。在钠中StaticDecrypt the following line

$decrypted = sodium_crypto_secretbox_open($data,$this->nonce,$this->key);

应该是

$decrypted = sodium_crypto_secretbox_open($decrypt,$this->nonce,$this->key);

最新更新