PHP加密数据需要在React Native中解密

标签 php react-native encryption cryptojs zero-padding

我正在使用以下代码片段在 PHP 中对 CBC 256 模式进行 AES 加密。

$iv_real = "ahc/2u6F0Yvww12fyQiZWA==";
$decoded_iv = base64_decode($iv_real);
$plaintext_shared_secret = "9b8a3e600073de05e5d095b5d909043e50f5047ffcd0048c01c65ca690b7b4e981e51b59641d4ffd5a140c27f25a761ab0f99e601b59c5ae3427c751bfae9331";
echo "Shared secret: {$plaintext_shared_secret}\r\n";
$aes_key = hash("sha256", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d0a390bbb5a9a0b1b3a4feb1a0a0b1e6e2b6e1b2b5b4e4e1e1e6e6b2e2b3e4e5e5b4e8e2e3e3e7e2e2e2e7e2e3b2e0e2e8e7b4e9e2e0" rel="noreferrer noopener nofollow">[email protected]</a>"); 
$encrypted_shared_secret = openssl_encrypt(
    $plaintext_shared_secret, 
    "aes-256-cbc", 
    $aes_key,
    OPENSSL_ZERO_PADDING,
    $decoded_iv //Binary data
);
//Base64 encoded, encryped shared secret
echo "\r\nEncrypted, base64_encoded, shared secret\r\n";
var_dump($encrypted_shared_secret);

我得到的加密响应与我在 React Native 中得到的加密响应相差甚远。我需要在 ReactNative 中解密相同的数据。我已经尝试过了

  1. React-native-simple-crypto
  2. react-native-crypto-js

但它们似乎都无法正常工作并提供解密数据,甚至无法像我使用 PHP 那样获得加密数据。

任何 React 模块中都不支持 Padding。

我选择了 ReactNative Framework,想象它是最先进的框架,但我已经浪费了很多天来解决这个问题,所以不知道如何解决这个问题。

以下是 react 代码

async DecryptSharedSecret() {
//    var plaintext_secret = "9b8a3e600073de05e5d095b5d909043e50f5047ffcd0048c01c65ca690b7b4e981e51b59641d4ffd5a140c27f25a761ab0f99e601b59c5ae3427c751bfae9331";
var strIV = 'ahc/2u6F0Yvww12fyQiZWA==';
var iv_bin = Base64.Decode(strIV, strIV.length);
// Decoded value IV is in Binary when converted to Hex its 6a173fdaee85d18bf0c35d9fc9089958

var shared_secret =
  'n4gIdzwY5UsOpzGtslpRlyNjLwLla7sJWfGkfH0GHadPFjtsOxNGJgqRe9WnjYkbNjCgwvvAvQtYV1kFHTpCIS4zDJa3h/2ADHrDgC7ym3HUyMeVIWgFKRCZYeVKz8SEHmullNxWG6dCjsWEbK6yqVmpNfwJSeh0XHHDFe0/Sak=';
var shared_secret_bin = Base64.Decode(shared_secret, shared_secret.length);
// Decoded Value shared_secret is in Binary when converted to HEx for printing, Value is
// '9f8808773c18e54b0ea731adb25a519723632f02e56bbb0959f1a47c7d061da74f163b6c3b1346260a917bd5a78d891b3630a0c2fbc0bd0b585759051d3a42212e330c96b787fd800c7ac3802ef29b71d4c8c79521680529109961e54acfc4841e6ba594dc561ba7428ec5846caeb2a959a935fc0949e8745c71c315ed3f49a9'

var strKey = '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="88fbc8e3edf1f8e9ebfca6e9f8f8e9bebaeeb9eaedecbcb9b9bebeeabaebbcbdbdecb0babbbbbfbabababfbabbeab8bab0bfecb1bab8" rel="noreferrer noopener nofollow">[email protected]</a>';
var keysha256 = await RNSimpleCrypto.SHA.sha256(strKey);
console.log('Key SHA 256 ===== >> ', keysha256);
// var key =
// '074bf4849734a4c3a653fc213f2734d23f5dc63ce9d6244f386276097f032ad7';

let bytes = CryptoJS.AES.decrypt(
  shared_secret_bin,
  CryptoJS.enc.Hex.parse(keysha256),
  {
    iv: iv_bin,
    mode: CryptoJS.mode.CBC,
  },
);
var decrypted = bytes.toString(CryptoJS.enc.Utf8);
console.log('Decrypted Data ', decrypted);

} }

最佳答案

您的 PHP 代码的结果是:

n4gIdzwY5UsOpzGtslpRlyNjLwLla7sJWfGkfH0GHadPFjtsOxNGJgqRe9WnjYkbNjCgwvvAvQtYV1kFHTpCIS4zDJa3h/2ADHrDgC7ym3HUyMeVIWgFKRCZYeVKz8SEHmullNxWG6dCjsWEbK6yqVmpNfwJSeh0XHHDFe0/Sak=

以下 CryptoJS 代码给出相同的结果:

// IV
var iv_real = "ahc/2u6F0Yvww12fyQiZWA==";
var decoded_iv = CryptoJS.enc.Base64.parse(iv_real);

// Key
var hash = CryptoJS.SHA256("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0a794a616f737a6b697e246b7a7a6b3c386c3b686f6e3e3b3b3c3c6838693e3f3f6e323839393d3838383d3839683a38323d6e33383a" rel="noreferrer noopener nofollow">[email protected]</a>");
var hashHex32 = hash.toString(CryptoJS.enc.Hex).substring(0,32);
var aes_key = CryptoJS.enc.Utf8.parse(hashHex32);

// Plaintext
var plaintext_shared_secret = "9b8a3e600073de05e5d095b5d909043e50f5047ffcd0048c01c65ca690b7b4e981e51b59641d4ffd5a140c27f25a761ab0f99e601b59c5ae3427c751bfae9331";

var encrypted = CryptoJS.AES.encrypt(
    plaintext_shared_secret, 
    aes_key, 
    {
        iv: decoded_iv,
        padding: CryptoJS.pad.NoPadding 
    });

console.log(encrypted.toString().replace(/(.{56})/g,'$1\n'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

在 PHP 代码中,SHA256 哈希值以十六进制编码返回,因此由 64 个字符或 64 个字节组成。 openssl_encrypt 仅使用 AES-256 的前 32 个字节,因此在 CryptoJS 代码中, key 必须相应缩短。将哈希值作为二进制数据返回会更有意义,因此它的长度为 32 个字节。此外,如果十六进制编码数据在一种环境中为大写而在另一种环境中为小写,则使用十六进制编码数据可能会导致跨平台问题。
另一点是,填充在 PHP 代码中被禁用(因为 OPENSSL_ZERO_PADDING 标志),因此它也必须在 CryptoJS 代码中禁用。这意味着只有长度为 block 大小(AES 为 16 字节)整数倍的明文才能加密,对于发布的明文(长度为 128 字节)也是如此。
由于明文在 PHP 代码中似乎是十六进制编码的,因此一种优化是在加密之前对明文进行十六进制解码,这将使数据量减半。
请注意,静态 IV 是不安全的。相反,每次加密都应该使用随机生成的 IV。

关于PHP加密数据需要在React Native中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65063473/

相关文章:

python - 通过 'passphrase' 进行一次填充

php - 检查文件的最后一行下面是否有东西

php - 如何复制基于 PHP 的网站?

php - 如何限制 Laravel 4 中每个用户帐户的同时 session 数

javascript - Realm 在 React Native 和 Node.JS 中查找单个对象,例如 MongoDB findOne

c# - 从密码字符串派生加密 key 和 IV 时,可以使用密码的 SHA1 散列作为盐吗?

PHP 将 MCRYPT_ENCRYPT 转换为 OPENSSL_ENCRYPT(SOAP header )

reactjs - 没有可用的位置提供程序, react native 中的权限被拒绝

android - react native 检查平板电脑或屏幕是否以英寸为单位

node.js - 如何在nodejs中加密和解密字符串/对象