簡體   English   中英

從 java 到 python 的 AES/CBC/PKCS5Padding

[英]AES/CBC/PKCS5Padding from java to python

我的任務是將這個 java 代碼轉換為 python。 而且我無法在 python 中獲得與 java 相同的結果。 我需要幫助來轉換此代碼。 非常感謝任何提示。

Java代碼

import org.apache.commons.lang.RandomStringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.util.Base64;
    
        public String decryptTextusingAES(String text, String kek) throws Exception{
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] keyBytes= new byte[16];  
        byte[] b= kek.getBytes("UTF-8");
        int len= b.length;
        if (len> keyBytes.length) len = keyBytes.length;
        System.arraycopy(b, 0, keyBytes, 0, len);
    
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        
        IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
        
        cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
        BASE64Decoder decoder = new BASE64Decoder();
        
        byte [] results = cipher.doFinal(decoder.decodeBuffer(text));

        return new String(results,"UTF-8");
    }
    

Python代碼

from Crypto.Cipher import AES  
from base64 import b64decode

BLOCK_SIZE = AES.block_size
pad = lambda s: s + (BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]


class AESCipher:
    def __init__(self, secretkey: str):
        self.key = secretkey  # key
        self.iv = secretkey[0:16]  # offset

    def decrypt(self, encrypted_text):
        encrypted_text = b64decode(encrypted_text)
        cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
        decrypted_text = cipher.decrypt(encrypted_text)
        print("unpad : ",decrypted_text)
        return unpad(decrypted_text).decode('utf-8')

if __name__ == '__main__':
    # message to encrypt 
    message = "mxoqPaEdpujwTOmeKGomHgXAgdVc0Ca7cm0Qqjm2WMQ="
    secret_key = "935554679694777871163316"
    AES_pkcs5_obj = AESCipher(secret_key)
    
    decrypted_message = AES_pkcs5_obj.decrypt(message)
    print("Decrypted : ",decrypted_message)

Python 代碼不斷給出這個 output:

unpad :  b'rt\xfb\x98o\x8f.\t\xb1d0tx-i\x88\xd1\xfdV\xef\xece\xf2\x8a\xf7\xf8\x00O\xdb\x8c\xcb\xf2'
Decrypted : 

但它應該在解密時給出這個:284174634921775587013963

這是加密字符串“mxoqPaEdpujwTOmeKGomHgXAgdVc0Ca7cm0Qqjm2WMQ=”

這是應該使用“935554679694777871163316”來解密上述字符串的密鑰。

您的密鑰似乎只有 192 位(24 個字符)...您依賴於自動檢測正確的 AES 算法。 據我所知,此配置中的 python 只有 AES256 可用,您需要 256 位密鑰(32 個字符)。 算法試圖拉伸密鑰以適應 AES256 的使用也可能存在問題,這可能在語言/框架之間以不同的方式完成。

看看那些參考實現,它們是相互兼容的。 您可以從那里開始 go 並繼續您的開發。

Java:

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

    private static final IvParameterSpec IV = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

    void testEncryption() throws GeneralSecurityException {
        final byte[] key = "AnyRandomInsecure256bitLongKeyXX".getBytes(StandardCharsets.US_ASCII);

        final SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

        final String encrypted = encrypt("data", keySpec, IV);
        final String decrypted = decrypt(encrypted, keySpec, IV);

        System.out.printf("%s <-> %s", encrypted, decrypted);
    }

    String encrypt(final String data, final SecretKeySpec keySpec, final IvParameterSpec ivSpec)
            throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)));
    }

    String decrypt(final String cipherText, final SecretKeySpec keySpec, final IvParameterSpec ivSpec)
            throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)), StandardCharsets.UTF_8);
    }

Python:

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

IV = bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]


def encrypt(plain_text, key):
    plain_text = pad(plain_text)
    cipher = AES.new(key, AES.MODE_CBC, IV)
    return b64encode(cipher.encrypt(plain_text))


def decrypt(cipher_text, key):
    cipher_text = b64decode(cipher_text)
    cipher = AES.new(key, AES.MODE_CBC, IV)
    return unpad(cipher.decrypt(cipher_text))

if __name__ == '__main__':
    key = "AnyRandomInsecure256bitLongKeyXX".encode()

    encrypted = encrypt("data", key)
    decrypted = decrypt(encrypted, key)
    print(f"{encrypted} <-> {decrypted}")

生成隨機 IV 然后將其添加到您生成的密文的前綴也是最佳實踐。 看看這里

暫無
暫無

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

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