首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java - Python AES加密解密

Java - Python AES加密解密
EN

Stack Overflow用户
提问于 2019-06-13 10:41:07
回答 2查看 2.3K关注 0票数 0

我有一个加密的文本从爪哇(V8)使用AES,我试图解密在python中使用相同的SecretKey,盐,但我得到的问题时,解垫的索引超出范围。当我反其道而行之时,比如在python中加密,在java中解密,那么我就能够得到文本,但是带有一些不想要的前缀。

下面是我尝试过的java和python代码。

Java代码(来自org.apache.commons.codec.binary.Base64的Base64)

代码语言:javascript
复制
public static String encrypt(String secretKey, String salt, String value) throws Exception {
        Cipher cipher = initCipher(secretKey, salt, Cipher.ENCRYPT_MODE);
        byte[] encrypted = cipher.doFinal(value.getBytes());
        return Base64.encodeBase64String(encrypted);
    }

    public static String decrypt(String secretKey, String salt, String encrypted) throws Exception {
        Cipher cipher = initCipher(secretKey, salt, Cipher.DECRYPT_MODE);
        byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
        return new String(original);
    }

    private static Cipher initCipher(String secretKey, String salt, int mode) throws Exception {

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKeySpec skeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(mode, skeySpec, new IvParameterSpec(new byte[16]));
        return cipher;
    }

    public static void main(String[] args) throws Exception {
        String secretKey = "Secret";
        String fSalt = "tJHnN5b1i6wvXMwzYMRk";
        String plainText = "England";

        String cipherText = encrypt(secretKey, fSalt, plainText);
        System.out.println("Cipher: " + cipherText);
//      cipherText = "6peDTxE1xgLE4hTGg0PKTnuuhFC1Vftsd7NH9DF/7WM="; // Cipher from python
        String dcrCipherText = decrypt(secretKey, fSalt, cipherText);
        System.out.println(dcrCipherText);

    }

Python代码(版本3.6) & Pycrypto V2.6

代码语言:javascript
复制
import base64
import hashlib
import os

from Crypto.Cipher import AES

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)

# unpad = lambda s: s[:-ord(s[len(s) - 1:])]
unpad = lambda s: s[0:-s[-1]]

def get_private_key(secretKey, salt):
    key = hashlib.pbkdf2_hmac('SHA256', secretKey.encode(), salt.encode(), 65536, 32)
    return key


def encrypt(message, salt, secretKey):
    private_key = get_private_key(secretKey, salt)
    message = pad(message)
    iv = os.urandom(BS)  # 128-bit IV
    cipher = AES.new(private_key, AES.MODE_CBC, iv, segment_size=256)
    return base64.b64encode(iv + cipher.encrypt(message))


def decrypt(enc, salt, secretKey):
    private_key = get_private_key(secretKey, salt)
    enc = base64.b64decode(enc)
    iv = enc[:BS]
    cipher = AES.new(private_key, AES.MODE_CBC, iv, segment_size=256)
    return unpad(cipher.decrypt(enc[BS:]))


secretKey = "Secret"
salt = "tJHnN5b1i6wvXMwzYMRk"
plainText = "England"
cipher = encrypt(plainText, salt, secretKey)
print("Cipher: " + bytes.decode(cipher))

# cipher = "0JrZdg9YBRshfTdr1d4zwQ==" # Cipher from java
decrypted = decrypt(cipher, salt, secretKey)
print("Decrypted " + bytes.decode(decrypted))

England解密输出:�U�����or���England当我传递python密码时,预期:England Python解密输出:unpad = lambda s : s[0:-s[-1]] IndexError: index out of range,预期:England

关于这个问题,我在堆栈上也通过了其他帖子,但由于他们使用了不同的模式,所以没有解决问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-13 11:19:55

在python中,您将iv (初始化向量)存储在加密消息的前16个字节中。

在Java中,您没有这样做-您传递一个空的IV,并将包括前16个字节在内的整个消息视为密文。

您需要确保Java和Python匹配。

要么在两者中都不使用IV,在这种情况下,您可以在Python中删除这一部分。

或者在这两种情况下都使用IV,在这种情况下,您需要更新Java代码以在加密时生成随机IV,并将其添加到加密结果中。在解密时,Java代码需要将前16个字节作为IV并将其传递给Cipher

票数 2
EN

Stack Overflow用户

发布于 2021-03-06 02:22:22

使用pycryptodome的正确python 3代码将与Java代码匹配,如下所示:

代码语言:javascript
复制
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad,pad
import hashlib

def get_private_key(secretKey, salt):
    # _prf = lambda p,s: HMAC.new(p, s, SHA256).digest()
    # private_key = PBKDF2(secretKey, salt.encode(), dkLen=32,count=65536, prf=_prf )
    # above code is equivalent but slow
    key = hashlib.pbkdf2_hmac('SHA256', secretKey.encode(), salt.encode(), 65536, 32)
    # KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
    return key

def encrypt(message, salt, secretKey):
    private_key = get_private_key(secretKey, salt)
    message = pad(message.encode(), AES.block_size)
    iv = "\x00"*AES.block_size  # 128-bit IV
    cipher = AES.new(private_key, AES.MODE_CBC, iv.encode())
    return base64.b64encode(cipher.encrypt(message))


def decrypt(enc, salt, secretKey):
    # _prf = lambda p,s: HMAC.new(p, s, SHA256).digest()
    # private_key = PBKDF2(secretKey, salt.encode(), dkLen=32,count=65536, prf=_prf )
    private_key = get_private_key(secretKey, salt)
    enc = base64.b64decode(enc)
    iv = "\x00"*AES.block_size
    cipher = AES.new(private_key, AES.MODE_CBC, iv.encode())
    return unpad(cipher.decrypt(enc), AES.block_size).decode('utf-8')


secretKey = "Secret"
salt = "tJHnN5b1i6wvXMwzYMRk"
plainText = "England"
enc_datta = encrypt(plainText, salt, secretKey)
print(f"Encrypted: {enc_datta}")
# Encrypted: 0JrZdg9YBRshfTdr1d4zwQ==

cipher = "0JrZdg9YBRshfTdr1d4zwQ==" # Cipher from java
decrypted = decrypt(cipher, salt, secretKey)
print(f"Decrypted: {decrypted}" )
# Decrypted: England
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56572677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档