我在python中成功加密資料并將url安全資料發送到PHP。當我嘗試使用openssl_decryptPHP 方法解密資料時,它回傳false. 我已經閱讀了 2 天,知道正在尋找解決方案,但沒有一個解決方案可以解決我的問題 [本論壇上有 2 個類似的問題,但它們沒有幫助,Q1,Q2 ]。
加密使用 python3.8 和包PyCryptodome:
from Crypto.Cipher import AES
import base64
import hashlib
import os
import secrets
BLOCK = 16
PADDING = '~'
iv = secrets.token_urlsafe(16)
secretKey = secrets.token_urlsafe(32) # 32 bytes is used as AES 256 expects 256 bits
encoding = 'latin-1'
s = 'very secret data' # secret to be encrypted
k = hashlib.sha256(secretKey.encode(encoding)).hexdigest()[:32].encode(encoding) # key hashed and encoded
pad = s (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
cipher = AES.new(key=k, mode=AES.MODE_CBC, IV=hashlib.sha256(iv.encode(encoding)).hexdigest()[:16].encode(encoding)) # cipher object
encrypted_secret = base64.urlsafe_b64encode(cipher.encrypt(pad.encode(encoding)))
print("Key: ", secretKey, "\n", "IV:",iv, "\n", "Encrypted:", encrypted_secret.decode(encoding))
Outputs[0]:
Key: cdLTCHW95FjHF6ESu2Rkm-90AUbzDBv71HrdshsEx3k
IV: b16ezD5O05EDNovsqLExUg
Encrypted: RJqA3-n6d7hmKgj7biiwUKD0SjRjm__4f42P06R-qO8=
*我對加密的秘密結果進行解碼,因為它是作為 json 編碼物件發送的,而 json 的編碼器在其中抱怨位元組物件。
在 PHP 中解密是更少的代碼(對于測驗,我復制了密鑰和 iv,但 iv 每次都是新創建的,并且密鑰存盤在不同的服務器上):
$key = 'cdLTCHW95FjHF6ESu2Rkm-90AUbzDBv71HrdshsEx3k';
$iv = 'b16ezD5O05EDNovsqLExUg';
$method = "AES-256-CBC";
$blocksize = 16;
$padwith = '~';
$decoded_secret = 'RJqA3-n6d7hmKgj7biiwUKD0SjRjm__4f42P06R-qO8='; // secret is sent as string
$hashKey = substr(hash('sha256', $key), 0, 32);
$iv_len = openssl_cipher_iv_length($method);
$iv_hash = substr(hash('sha256', $iv), 0, $iv_len); // cipher expects an IV of precisely 16 bytes, padding with \\0
$decrypted_secret = openssl_decrypt($decoded_secret, $method, $hashKey, OPENSSL_RAW_DATA, $iv_hash);
$what = rtrim($decrypted_secret, $padwith);
var_dump($decrypted_secret, $what);
Outputs[1]: bool(false) string(0) ""
我嘗試utf-8在 python 中設定為編碼,base64在 php 中解碼加密字串,將塊大小更改為 32,不在hashlibpython 端使用,但沒有任何更改給出預期的解密結果。
有人可以給我一個解決這個問題的線索嗎?
uj5u.com熱心網友回復:
你實際上需要兩條線索,所以我們稱之為假期獎金:-)
您的資料在 urlsafe-base64 中,但您的 php 沒有對其進行解碼,因此它試圖解密完全錯誤的資料。php不(AFAICS)直接支持urlsafe,所以需要轉換一下;然后你可以解碼它并傳遞給
openssl_decrypt,或者簡單地呼叫openssl_decrypt,OPENSSL_RAW_DATA因為它默認為(傳統的又名 MIME 或 PEM 或 PGP 或 XML)base64。您的加密不使用 PKCS5/7 填充,但 OpenSSL 默認使用它,因此您的解密失敗。
OPENSSL_ZERO_PADDING在這種情況下,您需要使用which 成為空操作,然后(正如您已經做過的那樣)自己進行 unpad。
使用此代碼中未注釋或注釋的行,它可以作業:
<?php
$key = 'cdLTCHW95FjHF6ESu2Rkm-90AUbzDBv71HrdshsEx3k';
$iv = 'b16ezD5O05EDNovsqLExUg';
$method = "AES-256-CBC";
$blocksize = 16; // not used
$padwith = '~';
$secret = 'RJqA3-n6d7hmKgj7biiwUKD0SjRjm__4f42P06R-qO8='; // secret is sent as string
$fixed_secret = str_replace(array('-','_'),array(' ','/'),$secret);
$decoded_secret = base64_decode($fixed_secret); // maybe used
$hashKey = substr(hash('sha256', $key), 0, 32);
$iv_len = openssl_cipher_iv_length($method);
$iv_hash = substr(hash('sha256', $iv), 0, $iv_len);
$decrypted_secret = openssl_decrypt($fixed_secret, $method, $hashKey, OPENSSL_ZERO_PADDING, $iv_hash);
//$decrypted_secret = openssl_decrypt($decoded_secret, $method, $hashKey, OPENSSL_RAW_DATA OPENSSL_ZERO_PADDING, $iv_hash);
$what = rtrim($decrypted_secret, $padwith);
var_dump($decrypted_secret, $what);
?>
->
string(32) "very secret data~~~~~~~~~~~~~~~~"
string(16) "very secret data"
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/392879.html
上一篇:如何使用函式將小寫更改為大寫
