我有一些问题,使工作的AES-256-CTR加密/解密在PHP,有一个以前加密的字符串与NodeJS加密。
下面是我的JS代码:
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = 'd6F3Efeq';
function encrypt(text){
var cipher = crypto.createCipher(algorithm,password)
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher(algorithm,password)
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}下面是我的PHP代码:
$text = "pereira";
echo bin2hex(openssl_encrypt($text, "aes-256-ctr", "d6F3Efeq",OPENSSL_RAW_DATA));JS版本在加密时返回以下内容:
148bc695286379PHP版本在我的加密测试中返回以下内容:
2f2ad5bb09fb56我是不是漏掉了什么?显然,我也不能在PHP中正确解密。
提前谢谢。
发布于 2018-01-29 19:20:00
我的问题终于有了答案,感谢@Alex K和@Artjom B。
正如我在评论中提到的,我必须获得与NodeJS createCipher兼容的PHP /descrypt,因为NodeJS应用程序是第三方应用程序。
因此,JS代码如下所示:
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = 'd6F3Efeq';
function encrypt(text){
var cipher = crypto.createCipher(algorithm,password)
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher(algorithm,password)
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}我写了一个小PHP类来实现这个加密/解密任务(基于@Artjon's solution):
class Crypto
{
const METHOD = 'aes-256-ctr';
public function encrypt($plaintext, $password, $salt='', $encode = false)
{
$keyAndIV = self::evpKDF($password, $salt);
$ciphertext = openssl_encrypt(
$plaintext,
self::METHOD,
$keyAndIV["key"],
OPENSSL_RAW_DATA,
$keyAndIV["iv"]
);
$ciphertext = bin2hex($ciphertext);
if ($encode)
{
$ciphertext = base64_encode($ciphertext);
}
return $ciphertext;
}
public function decrypt($ciphertext, $password, $salt='', $encoded = false)
{
if ( $encoded )
{
$ciphertext = base64_decode($ciphertext, true);
if ($ciphertext === false)
{
throw new Exception('Encryption failure');
}
}
$ciphertext = hex2bin($ciphertext);
$keyAndIV = self::evpKDF($password, $salt);
$plaintext = openssl_decrypt(
$ciphertext,
self::METHOD,
$keyAndIV["key"],
OPENSSL_RAW_DATA,
$keyAndIV["iv"]
);
return $plaintext;
}
public function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5")
{
$targetKeySize = $keySize + $ivSize;
$derivedBytes = "";
$numberOfDerivedWords = 0;
$block = NULL;
$hasher = hash_init($hashAlgorithm);
while ($numberOfDerivedWords < $targetKeySize)
{
if ($block != NULL)
{
hash_update($hasher, $block);
}
hash_update($hasher, $password);
hash_update($hasher, $salt);
$block = hash_final($hasher, TRUE);
$hasher = hash_init($hashAlgorithm);
// Iterations
for ($i = 1; $i < $iterations; $i++)
{
hash_update($hasher, $block);
$block = hash_final($hasher, TRUE);
$hasher = hash_init($hashAlgorithm);
}
$derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));
$numberOfDerivedWords += strlen($block)/4;
}
return array(
"key" => substr($derivedBytes, 0, $keySize * 4),
"iv" => substr($derivedBytes, $keySize * 4, $ivSize * 4)
);
}
}根据NodeJS文档,它从没有盐的密码派生IV,所以我使用一个空字符串作为盐。
我在CodeIgniter中使用这个PHP类如下所示:
$this->load->library("Crypto");
$plain_text = "pereira";
$password = "d6F3Efeq";
$enc_text = $this->crypto->encrypt($plain_text,$password);
$pla_text = $this->crypto->decrypt($enc_text,$password);
echo $enc_text."<br>";
echo $pla_text;这两个函数(NodeJS和PHP)对加密和解密函数返回相同的结果:
pereira = 148bc695286379致以问候。
发布于 2018-01-28 10:01:10
必须在两侧设置iv (初始化向量)。
节点JS代码:
var crypto = require('crypto'),
password = '1234567890abcdef1234567890abcdef',
iv = '1234567890abcdef',
text = "pereira";
function encrypt(iv, text, password){
var cipher = crypto.createCipheriv('aes-256-ctr', password, iv)
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
function decrypt(iv, text, password){
var decipher = crypto.createDecipheriv('aes-256-ctr', password, iv)
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}
console.log(encrypt(iv, text, password));和PHP代码:
$text = 'pereira';
$algorithm = 'aes-256-ctr';
$password = '1234567890abcdef1234567890abcdef'; //node js required 32 byte length key
$iv = '1234567890abcdef'; //must be 16 byte length
echo bin2hex(openssl_encrypt($text, $algorithm, $password, OPENSSL_RAW_DATA, $iv));https://stackoverflow.com/questions/48441285
复制相似问题