在 Nodejs 中加密并在 PHP 中解密
Encrypt in Nodejs and Decrypt in PHP
我正在尝试解密 PHP 中最初在 NodeJS 中加密的字符串。
PHP:
openssl_decrypt($raw_id, "aes-128-cbc", "s7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m", 0, null)
这似乎总是returnfalse
。
Nodejs 中的加密:
function encrypt(text) {
var cipher = crypto.createCipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted;
}
function decrypt(text) {
var cipher = crypto.createDecipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var decrypted = cipher.update(text, 'hex', 'utf8')
decrypted += cipher.final('utf8');
return decrypted;
}
我基本上是想加密,例如Nodejs中的encrypt("Pizza")
,将它发送到PHP页面(3879f91a59e9a458db62f905b0a488a1
),然后从那里解密(openssl_decrypt: return Pizza
).
我知道这段代码不安全,因为我没有使用 IV,但我不确定如何添加。
您的方法不安全,也可能成为中间人攻击的受害者,您应该始终使用 IV 和 HMAC
您可以像这样 php 加密
$key = substr('encyptionsec123342',0,32)
function encrypt ($message, $method, $secret, &$hmac) {
$iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);
$encrypted = base64_encode($iv) . openssl_encrypt($message, $method, $secret, 0, $iv);
$hmac = hash_hmac('md5', $encrypted, $secret);
return $encrypted;
}
function decrypt ($encrypted, $method, $secret, $hmac) {
if (hash_hmac('md5', $encrypted, $secret) == $hmac) {
$iv = base64_decode(substr($encrypted, 0, 24));
return openssl_decrypt(substr($encrypted, 24), $method, $secret, 0, $iv);
}
}
function encryptWithTSValidation ($message, $method, $secret, &$hmac) {
date_default_timezone_set('UTC');
$message = substr(date('c'),0,19) . "$message";
return encrypt($message, $method, $secret, $hmac);
}
function decryptWithTSValidation ($encrypted, $method, $secret, $hmac, $intervalThreshold) {
$decrypted = decrypt($encrypted, $method, $secret, $hmac);
$now = new DateTime();
$msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
return substr($decrypted,19);
}
}
这是一种安全的 AES-256-CBC 方法,使用 HMAC 可以阻止中间人攻击。
Node.js
var secret = "encyptionsec123342";
secret = secret.substr(0, 32);
var method = 'AES-256-CBC';
var encrypt = function(message, method, secret, hmac) {
var iv = crypto.randomBytes(16).toString('hex').substr(0, 16);
var encryptor = crypto.createCipheriv(method, secret, iv);
var encrypted = new Buffer.alloc(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
hmac = crypto.createHmac('md5', secret).update(encrypted).digest('hex');
return encrypted;
};
var decrypt = function(encrypted, method, secret, hmac) {
if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac) {
var iv = new Buffer.from(encrypted.substr(0, 24), 'base64').toString();
var decryptor = crypto.createDecipheriv(method, secret, iv);
return decryptor.update(encrypted.substr(24), 'base64', 'utf8') + decryptor.final('utf8');
}
};
var encryptWithTSValidation = function(message, method, secret, hmac) {
var messageTS = new Date().toISOString().substr(0, 19) + message;
return encrypt(messageTS, method, secret, hmac);
}
var decryptWithTSValidation = function(encrypted, method, secret, hmac, intervalThreshold) {
var decrypted = decrypt(encrypted, method, secret, hmac);
var now = new Date();
var year = parseInt(decrypted.substr(0, 4)),
month = parseInt(decrypted.substr(5, 2)) - 1,
day = parseInt(decrypted.substr(8, 2)),
hour = parseInt(decrypted.substr(11, 2)),
minute = parseInt(decrypted.substr(14, 2)),
second = parseInt(decrypted.substr(17, 2));
var msgDate = new Date(Date.UTC(year, month, day, hour, minute, second))
if (Math.round((now - msgDate) / 1000) <= intervalThreshold) {
return decrypted.substr(19);
}
}
在php、
进行加密解密
$encrypted = encryptWithTSValidation($recipent, $method, $key, $hmac);
$decrypted = decryptWithTSValidation($encrypted,$method,$key, $hmac, 60*60*12)//this is 12 hours
要生成 hmac,可以使用简单的 md5 散列
$hmac = hash_hmac('md5', $recipent, $key);
并在 node.js
var decrypted = decryptWithTSValidation(encString, method, secret, hmac, 60 * 60);
var encrypted = decryptWithTSValidation(string, method, secret, hmac);
注意: nodejs 和php 中加密和解密时,请确保制作一个唯一的 32 位密钥,并且相同。还要妥善保管,切勿将其存储在数据库中。
代码参考:Encrypt string in PHP and decrypt in Node.js
我正在尝试解密 PHP 中最初在 NodeJS 中加密的字符串。
PHP:
openssl_decrypt($raw_id, "aes-128-cbc", "s7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m", 0, null)
这似乎总是returnfalse
。
Nodejs 中的加密:
function encrypt(text) {
var cipher = crypto.createCipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted;
}
function decrypt(text) {
var cipher = crypto.createDecipher('aes-128-cbc', 's7UbmJpfm56r6CAC6mz7KVZdRc3Fxc4m');
var decrypted = cipher.update(text, 'hex', 'utf8')
decrypted += cipher.final('utf8');
return decrypted;
}
我基本上是想加密,例如Nodejs中的encrypt("Pizza")
,将它发送到PHP页面(3879f91a59e9a458db62f905b0a488a1
),然后从那里解密(openssl_decrypt: return Pizza
).
我知道这段代码不安全,因为我没有使用 IV,但我不确定如何添加。
您的方法不安全,也可能成为中间人攻击的受害者,您应该始终使用 IV 和 HMAC
您可以像这样 php 加密
$key = substr('encyptionsec123342',0,32)
function encrypt ($message, $method, $secret, &$hmac) {
$iv = substr(bin2hex(openssl_random_pseudo_bytes(16)),0,16);
$encrypted = base64_encode($iv) . openssl_encrypt($message, $method, $secret, 0, $iv);
$hmac = hash_hmac('md5', $encrypted, $secret);
return $encrypted;
}
function decrypt ($encrypted, $method, $secret, $hmac) {
if (hash_hmac('md5', $encrypted, $secret) == $hmac) {
$iv = base64_decode(substr($encrypted, 0, 24));
return openssl_decrypt(substr($encrypted, 24), $method, $secret, 0, $iv);
}
}
function encryptWithTSValidation ($message, $method, $secret, &$hmac) {
date_default_timezone_set('UTC');
$message = substr(date('c'),0,19) . "$message";
return encrypt($message, $method, $secret, $hmac);
}
function decryptWithTSValidation ($encrypted, $method, $secret, $hmac, $intervalThreshold) {
$decrypted = decrypt($encrypted, $method, $secret, $hmac);
$now = new DateTime();
$msgDate = new DateTime(str_replace("T"," ",substr($decrypted,0,19)));
if (($now->getTimestamp() - $msgDate->getTimestamp()) <= $intervalThreshold) {
return substr($decrypted,19);
}
}
这是一种安全的 AES-256-CBC 方法,使用 HMAC 可以阻止中间人攻击。
Node.js
var secret = "encyptionsec123342";
secret = secret.substr(0, 32);
var method = 'AES-256-CBC';
var encrypt = function(message, method, secret, hmac) {
var iv = crypto.randomBytes(16).toString('hex').substr(0, 16);
var encryptor = crypto.createCipheriv(method, secret, iv);
var encrypted = new Buffer.alloc(iv).toString('base64') + encryptor.update(message, 'utf8', 'base64') + encryptor.final('base64');
hmac = crypto.createHmac('md5', secret).update(encrypted).digest('hex');
return encrypted;
};
var decrypt = function(encrypted, method, secret, hmac) {
if (crypto.createHmac('md5', secret).update(encrypted).digest('hex') == hmac) {
var iv = new Buffer.from(encrypted.substr(0, 24), 'base64').toString();
var decryptor = crypto.createDecipheriv(method, secret, iv);
return decryptor.update(encrypted.substr(24), 'base64', 'utf8') + decryptor.final('utf8');
}
};
var encryptWithTSValidation = function(message, method, secret, hmac) {
var messageTS = new Date().toISOString().substr(0, 19) + message;
return encrypt(messageTS, method, secret, hmac);
}
var decryptWithTSValidation = function(encrypted, method, secret, hmac, intervalThreshold) {
var decrypted = decrypt(encrypted, method, secret, hmac);
var now = new Date();
var year = parseInt(decrypted.substr(0, 4)),
month = parseInt(decrypted.substr(5, 2)) - 1,
day = parseInt(decrypted.substr(8, 2)),
hour = parseInt(decrypted.substr(11, 2)),
minute = parseInt(decrypted.substr(14, 2)),
second = parseInt(decrypted.substr(17, 2));
var msgDate = new Date(Date.UTC(year, month, day, hour, minute, second))
if (Math.round((now - msgDate) / 1000) <= intervalThreshold) {
return decrypted.substr(19);
}
}
在php、
进行加密解密$encrypted = encryptWithTSValidation($recipent, $method, $key, $hmac);
$decrypted = decryptWithTSValidation($encrypted,$method,$key, $hmac, 60*60*12)//this is 12 hours
要生成 hmac,可以使用简单的 md5 散列
$hmac = hash_hmac('md5', $recipent, $key);
并在 node.js
var decrypted = decryptWithTSValidation(encString, method, secret, hmac, 60 * 60);
var encrypted = decryptWithTSValidation(string, method, secret, hmac);
注意: nodejs 和php 中加密和解密时,请确保制作一个唯一的 32 位密钥,并且相同。还要妥善保管,切勿将其存储在数据库中。
代码参考:Encrypt string in PHP and decrypt in Node.js