React使用OpenSSL本机加密数据

watbbzwu  于 2023-03-13  发布在  React
关注(0)|答案(1)|浏览(136)

下面是我的PHP代码:

$input_data = array("request_type" => "bill_status",
    "custno" => array(0 => "35677890GH"),
    "key" => "billstatusapiauth", "source" => "CustomerDashboard");
$create_json = json_encode($input_data, true);
$base_enc = base64_encode($create_json);
$create_encrypted = openssl_encrypt($base_enc, "aes-256-cbc", "billstatusapiauth", OPENSSL_RAW_DATA, "billrepository");
$create_encoded = base64_encode($create_encrypted);
$send_data = array("enc" => $create_encoded);

我想实现的加密一样,在上面的React原生,所以我用AES加密。
下面是我的React原生代码

var value = session?.businessInfo?.number;
dataArray.push(value);
const confidentialParams = {
    request_type: 'bill_status',
    custno: dataArray,
    key: 'billstatusapiauth',
    source: 'CustomerDashboard',
};

// To encode an object (This produces a string)
var encode = JSON.stringify(confidentialParams);
   
//convert encoded value into base64
const encodedbase64 = base64.encode(encode);
    
var ciphertext = CryptoES.AES.encrypt(
    JSON.stringify(encodedbase64),
    'billstatusapiauth',
).toString();

const newBase64 = base64.encode(ciphertext);

我已经按照所有的步骤已经写在PHP代码,但我仍然没有得到API的响应。我该如何在React Native中实现这一点?
编辑:
我正在使用从“crypto-es”导入CryptoES;以加密和解密数据。

hgtggwj0

hgtggwj01#

正如评论中已经提到的,存在以下问题:

  • 对于AES-256,必须使用32字节的密钥。发布的密钥billstatusapiauth较短,因此对于AES-256无效。PHP * 隐式 * 将值为0x 00的密钥填充到32字节。在JavaScript端,必须 * 显式 * 将值为0x 00的密钥扩展到32字节。
  • 对于AES,必须使用16字节的IV。发布的IV billrepository较短,因此对AES无效。PHP隐式地用0x 00值将IV填充到16字节(同时显示相应的警告)。在JavaScript端,IV必须显式地用0x 00值扩展到16字节。
  • 在CryptoES代码中,密钥和IV必须作为WordArray传递(如果密钥作为字符串传递,则CryptoES应用密钥派生函数)。

下面的代码显示了一个可能的CryptoES实现。由于我没有找到提供CryptoES的CDN,我将在下面的代码中使用来自 * www.example.com * 的CryptoJScdnjs.cloudflare.com(CryptoES是一个与ES6和TypeScript兼容的CryptoJS端口)。在我的本地环境中,CryptoES给出了相同的结果:

var CryptoES = CryptoJS; // for this test environment here

const confidentialParams = {
    request_type: 'bill_status',
    custno: ['35677890GH'],
    key: 'billstatusapiauth',
    source: 'CustomerDashboard',
};

var plaintext = JSON.stringify(confidentialParams);
var plaintextB64 = CryptoES.enc.Utf8.parse(plaintext).toString(CryptoES.enc.Base64);

var key = CryptoES.enc.Utf8.parse('billstatusapiauth'.padEnd(32, '\0'));
var iv = CryptoES.enc.Utf8.parse('billrepository'.padEnd(16, '\0'));

var ciphertext = CryptoES.AES.encrypt(plaintextB64, key, {iv: iv});

var ciphertextB64 = ciphertext.toString();
var ciphertextJson = {enc:ciphertextB64};
console.log(ciphertextJson); // {enc: "FRu6qofJyIn6zda1PzOTxXl7AQ65U+AKHIzaVAJ9mOFxNJBBmB/VaGGr4c3m2RiSkEGfgbl3HiVV6/H81UqH7ecnYC9ZqyQFKpTyyhxzkWUKYJ71eliicKh/Y1RCd2mT1wYgG1PCwtPp8opM8j7VMQOWSxJY5B42BHAmfRRd/GIWEdyXLyruAFapmZWLq47UKM8l4Z80cyrQ6oY1YEXU5Q=="}
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

在PHP端,print_r($send_data)返回所使用的数据:

Array
(
    [enc] => FRu6qofJyIn6zda1PzOTxXl7AQ65U+AKHIzaVAJ9mOFxNJBBmB/VaGGr4c3m2RiSkEGfgbl3HiVV6/H81UqH7ecnYC9ZqyQFKpTyyhxzkWUKYJ71eliicKh/Y1RCd2mT1wYgG1PCwtPp8opM8j7VMQOWSxJY5B42BHAmfRRd/GIWEdyXLyruAFapmZWLq47UKM8l4Z80cyrQ6oY1YEXU5Q==
)

即相同的密文!
安全性:
使用的密钥和IV都是漏洞,两者不仅过短,而且是字符串,相反,两者都应该是所需长度的随机字节序列。
如果确实要将字符串(而不是随机字节序列)用作密钥材料,则必须应用密钥导出函数(至少PBKDF 2)。
此外,密钥/IV对不能重复使用,这一点很重要。因此,对于固定密钥,通常为 * 每次 * 加密生成随机IV(IV不是秘密的,通常与密文连接,以便在解密期间可用)。

相关问题