簡體   English   中英

用Crypto.js和pycrypto加密生成不同的加密密文

[英]Encryption with Crypto.js and pycrypto generates different encryption cipher text

我正在嘗試使用Crypto.js使用其AES算法在 Node 中生成加密文本。 它在 Js 中用於加密和解密。 同樣,我嘗試使用pycrypto在Python中實現相同的功能,它在python中都進行了加密和解密。但是當我想使用來自JS的加密密文在Python中解密時,問題就出現了。問題是JS中生成的加密文本不同根據 Python 中生成的內容。

這是基於 JS 的 AES 用法:

import CryptoJS from "crypto-js";

let str = "lol";
let salt = "ABCDEFGHIJKLMNOP";
let key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP";

salt = CryptoJS.enc.Hex.parse(salt);
key = CryptoJS.enc.Hex.parse(key);

const options = {
  iv: salt,
  padding: CryptoJS.pad.ZeroPadding,
  mode: CryptoJS.mode.CFB,
};

// function to encrypt the string
function encrypt(str, salt, key) {
  const cipher = CryptoJS.AES.encrypt(str, key, options);
  console.log("cipher", CryptoJS.enc.Hex.stringify(cipher.ciphertext));
  return cipher.ciphertext.toString(CryptoJS.enc.Base64);
}

// function to decrypt the string
function decrypt(str, salt, key) {
  const cipher = CryptoJS.AES.decrypt(str, key, options);
  return cipher.toString(CryptoJS.enc.Utf8);
}

const encrypted = encrypt(str, salt, key);
console.log("encrypted", encrypted);


const decrypted = decrypt(encrypted, salt, key);
console.log("decrypted", decrypted);

// OUTPUT
// encrypted sd4Xpz/ws8x2j+cgF17t6A==
// decrypted lol

這是基於 Python 的 AES 用法:

from Crypto.Cipher import AES
from base64 import b64encode, b64decode

str = "lol";
salt = b"ABCDEFGHIJKLMNOP";
key = "ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP";
enc_dec_method = 'utf-8'


def encrypt(str_to_enc, str_key, salt):
    aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, salt)
    hx_enc = aes_obj.encrypt(str_to_enc.encode('utf8'))
    df = b64encode(hx_enc)
    mret = b64encode(hx_enc).decode(enc_dec_method)
    return mret

def decrypt(str_to_dec, str_key, salt):
    aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, salt)
    str_tmp = b64decode(str_to_dec.encode(enc_dec_method))
    str_dec = aes_obj.decrypt(str_tmp)
    mret = str_dec.decode(enc_dec_method)
    return mret

test_enc_text = encrypt(str, key, salt)
test_dec_text = decrypt(test_enc_text, key, salt)

print(f"Encrypted Text: {test_enc_text}")
print(f"Decrypted Text: {test_dec_text}")

# OUTPUT
# Encrypted Text: o9XB
# Decrypted Text: lol
  • 我厭倦了用這兩種語言進行加密和解密,並檢查了這兩個庫的文檔和源代碼。
  • 也嘗試檢查我是否缺少編碼或解碼,但沒有運氣。

我在這里缺少什么關鍵概念可以幫助彌合兼容性差距?

這些代碼不兼容,因為:

  • Key 和 IV 不是十六進制編碼的,因此不能在 CryptoJS 代碼中使用十六進制編碼器。 如果要像在 Python 代碼中一樣應用 Utf-8 編碼,則必須改用 Utf-8 編碼器。

     salt = CryptoJS.enc.Utf8.parse(salt); key = CryptoJS.enc.Utf8.parse(key);
  • CFB 是一種不需要填充的 stream 密碼模式。 但是,在當前的 CryptoJS 代碼中,使用了零填充 ( CryptoJS.pad.ZeroPadding )。 相反,必須禁用填充(這不會隱式發生,與 Python 代碼不同):

     padding: CryptoJS.pad.NoPadding,
  • CFB 配置有一個附加參數,即段大小,它指定每個加密步驟加密的位數。 CryptoJS 代碼僅支持一種段大小,即 128 位。 使用 PyCryptodome,可以配置段大小,默認使用 8 位。 為了兼容性,必須將其更改為 128 位:

     aes_obj = AES.new(str_key.encode('utf-8'), AES.MODE_CFB, salt, segment_size=128)

通過這些更改,兩個代碼都兼容。

測試:兩種代碼都為以下明文提供以下密文:

plaintext:  The quick brown fox jumps over the lazy dog
ciphertext: m0T/7e04eV49RTcgd7KtwHxSOavNzHNwlrvjt1YmmHidBy4rHS0oovclKQ==

請注意,您所說的實際上是初始化向量IV )。 術語更常用於密鑰派生函數(如 PBKDF2)的上下文中。

關於安全性:用於 salt 和 IV 的值可用於測試,但在現實世界場景中,必須為每次加密的 IV 應用隨機字節序列,它必須與密文一起傳遞給解密方(一般串聯)。
此外,作為密鑰,不必使用密碼,而是使用隨機字節序列。 密碼短語(當然是強密碼)只能與密鑰派生 function 結合使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM