当前位置: 首页 > 知识库问答 >
问题:

使用AES/ECB/PKSC5加密,将Java迁移到Python

酆高翰
2023-03-14

我的任务是在一个项目上实现AES加密。参考代码是用Java编写的,需要转换成Python。当我整理笔记写一个问题时,我无意中发现了答案!希望其他人会觉得这很有用,我将在这里把我的笔记作为一个“分享你的知识”的问题提出来。

要求使用具有给定密钥的AES加密消息。下面是参考代码(Java)的简化视图,

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Encoder;


public class EncryptAES {

    private static String toHexString(byte[] data) {        
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; ++i) {
            String s = Integer.toHexString(data[i] & 0XFF);
            buf.append((s.length() == 1) ? ("0" + s) : s);
        }
        return buf.toString();
    }

    public static String encrypt(String input, String key) {
        byte[] crypted = null;
        try {
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            crypted = cipher.doFinal(input.getBytes());
            final String encryptedString = toHexString(Base64.encodeBase64(crypted));
            return encryptedString;
        } catch (Exception e) {
            System.out.println(e.toString());
        }
        return new String(new BASE64Encoder().encode(crypted));
    }

    public static void main(String[] args) {
        String key = args[0];
        String plaintext = args[1];
        System.out.println("KEY = " + key);
        System.out.println("PLAINTEXT = " + plaintext);
        System.out.println("CIPHER = " + EncryptAES.encrypt(plaintext, key));
    }
}

如果将上述内容另存为“EncryptAES”。并保留库文件commons-codec-1.7。jar在同一目录中,您可以使用以下命令编译它,

$ javac EncryptAES.java -cp commons-codec-1.7.jar

这里是运行程序几次时的输出,

$ java -cp "commons-codec-1.7.jar:." EncryptAES ddddffffeeeerrrr message
KEY = ddddffffeeeerrrr
MESSAGE = message
CRYPTO = 397a59594d35524e6b6a463253706f41467668646b773d3d
$

$ java -cp "commons-codec-1.7.jar:." EncryptAES qqqqwwwweeeerrrr ThisIsAVeryImportantMessage
KEY = qqqqwwwweeeerrrr
PLAINTEXT = ThisIsAVeryImportantMessage
CIPHER = 56536a384d667736756b595a394e396b6d504d736231444673375250736d5639596f637072792f6e4b424d3d
$

环顾四周,我发现了Python加密库。这是我复制上述输出的早期尝试之一,

#!/usr/bin/python

import sys
from Crypto.Cipher import AES

if __name__ == '__main__':
    key = sys.argv[1]
    plaintext = sys.argv[2]
    print 'KEY = ' + key
    print 'PLAINTEXT = ' + plaintext

    encobj = AES.new(key, AES.MODE_ECB)
    ciphertext = encobj.encrypt(plaintext)
    print 'CIPHER = ' + ciphertext.encode('hex') 

这不太符合我的需要。相反,我得到一个关于输入字符串长度需要为16倍的错误消息。这就引出了我的下一次尝试,

#!/usr/bin/python

import sys
from Crypto.Cipher import AES

# ref: https://gist.github.com/crmccreary/5610068
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[0:-ord(s[-1])]

class AESCipher:
    def __init__( self, key ):
        """
        Requires hex encoded param as a key
        """
        self.key = key.decode("hex")

    def encrypt( self, raw ):
        """
        Returns hex encoded encrypted value!
        """
        raw = pad(raw)
        cipher = AES.new(self.key, AES.MODE_ECB)
        return cipher.encrypt(raw).encode("hex")


if __name__ == '__main__':
    key = sys.argv[1]
    plaintext = sys.argv[2]
    print 'KEY = ' + key
    print 'PLAINTEXT = ' + plaintext

    # ref: http://stackoverflow.com/a/16882092
    hex_key = "".join("{:02x}".format(ord(c)) for c in key)

    encryptor = AESCipher(hex_key)
    ciphertext = encryptor.encrypt(plaintext)
    print 'CIPHER = ' + ciphertext

老实说,我不太确定该如何看待输出,

$ python EncryptAES2.py ddddffffeeeerrrr message
KEY = ddddffffeeeerrrr
PLAINTEXT = message
CIPHER = f7361833944d9231764a9a0016f85d93
$

我尝试了很多东西——不同的加密模式、博客、各种问题,并放弃了自己寻找解决方案。正是在这一点上,我决定收集我的笔记,并在这里提出一个问题。现在,如果我没有列出我的尝试,那就没有什么意义了,所以我开始将它们组织在一个文件夹中,并将它们标记为EncryptAES。py加密AES2。py。。等

共有3个答案

耿运浩
2023-03-14

接受@chronodekar的答案并将其更改为适用于Python 3.9。

PyCryptoDome版本的Python 3引发了一个TypeError:对象类型

    class simple_AES:

    def __init__(self, key):
        self.key = bytearray(key.encode())

    def encrypt_AES(self, raw):
        raw = bytearray(pad(raw).encode())
        cipher = AES.new(self.key, AES.MODE_ECB)
        return base64.b64encode(cipher.encrypt(raw))

然而,我也遇到了输出问题。我发现这个答案是为了将输出转换为十六进制python base64到十六进制。

    hex_ciphertext = base64.b64decode(ciphertext).hex()
    print('CIPHER = ' + hex_ciphertext)
赵英资
2023-03-14
import base64
from Crypto.Cipher import AES

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


class AESCipher:
    def __init__(self, key):
        self.key = key

    def encrypt(self, raw):
        raw = pad(raw)
        cipher = AES.new(self.key, AES.MODE_ECB)
        raw = cipher.encrypt(raw)
        encrypt_val = base64.b64encode(raw)
        return encrypt_val

    def decrypt(self, raw):
        raw = raw.decode('base64')
        cipher = AES.new(self.key, AES.MODE_ECB)
        raw = cipher.decrypt(raw)
        raw = unpad(raw)
        return raw


if __name__ == '__main__':
    key = '123456789012345678901234'
    plaintext = '111122223333'
    print 'KEY = ' + key
    print 'PLAINTEXT = ' + plaintext

    ## Encrptor logic
    encryptor = AESCipher(key)
    ciphertext = encryptor.encrypt(plaintext)

    hex_ciphertext = "".join("{:02x}".format(ord(c)) for c in ciphertext)
    print 'Encrypted value : ' + hex_ciphertext

    bytesarray = []
    hexstr = ''.join(hex_ciphertext.split(" "))
    for i in range(0, len(hexstr), 2):
        bytesarray.append(chr(int(hexstr[i:i+2], 16)))

    val = ''.join(bytesarray)
    decrypt_ciphertxt = encryptor.decrypt(val)
    print 'Decrypted value  : ' + decrypt_ciphertxt
时衡虑
2023-03-14

当我准备这个列表时,我受到了启发,最后一次尝试时,我决定用十六进制重新格式化输出。令我惊喜的是,它成功了!这是获奖代码,

#!/usr/bin/python

import sys
import base64
from Crypto.Cipher import AES

# ref: http://stackoverflow.com/a/12525165
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 

class AESCipher:
    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        cipher = AES.new(self.key, AES.MODE_ECB)
        return base64.b64encode(cipher.encrypt(raw)) 


if __name__ == '__main__':
    key = sys.argv[1]
    plaintext = sys.argv[2]
    print 'KEY = ' + key
    print 'PLAINTEXT = ' + plaintext

    encryptor = AESCipher(key)
    ciphertext = encryptor.encrypt(plaintext)

    hex_ciphertext = "".join("{:02x}".format(ord(c)) for c in ciphertext)

    print 'CIPHER = ' + hex_ciphertext

这里是我在Java示例中使用的早期输入的输出,仅供参考,

$ python EncryptAES3.py ddddffffeeeerrrr message
KEY = ddddffffeeeerrrr
PLAINTEXT = message
CIPHER = 397a59594d35524e6b6a463253706f41467668646b773d3d
$

$ python EncryptAES3.py qqqqwwwweeeerrrr ThisIsAVeryImportantMessage
KEY = qqqqwwwweeeerrrr
PLAINTEXT = ThisIsAVeryImportantMessage
CIPHER = 56536a384d667736756b595a394e396b6d504d736231444673375250736d5639596f637072792f6e4b424d3d
$

找到这个解决方案花了我很多的尝试和错误。如果有一种更严格的方法将Java转换为Python,我很乐意听一听!

 类似资料:
  • 这是提供的文件:- 加密算法 为了在传输和发布数据时减轻参数调整/修改,商家可以使用Telenor PoC提供的散列密钥加密请求。该加密请求与主请求一起发送,然后在OPS端对主请求进行协调,以检测参数是否更改。加密可以使用以下算法完成: Put(“StoreID”,“28”); Fields.Put(“OrderRefNum”,“11001”); Fields.Put(“ExpiryDate”,“

  • 问题内容: 我有一个使用第三方付款门户的在线电子商务网站。在第三方支付门户要求所有人开始使用具有其他支付参数的哈希键之前,支付门户一直工作良好。 现在的问题是,第三方支付门户网站仅提供了一页文档来实现哈希密钥。 这是提供的文档: 加密演算法 为了减轻数据传输和发布过程中的参数调整/修改,商家可以使用Telenor POC提供的哈希密钥对请求进行加密。该加密请求与主请求一起发送,然后在OPS端进行协

  • 以下是我的加密/解密方法: 所以现在当我尝试加密时,我得到了这个异常: 我已经尝试在encrypt和Decrpt中使用密码实例。它只用于加密而不用于解密。我认为需要填充,因为数据大小不是16字节的倍数。“data”字节长度打印为,因此尝试将字符附加到数据中,然后进行加密,但也不起作用。

  • 我用Delphi加密“sifrelenecek”字符串,使用AES 128 ECB,使用密钥为“KRPTTT101103”,它给了我“FBE4A4405D6C1B54503D9B213E41AE56”,我正在检查http://aes.online-domain-tools.com/,它是正确的。我试图使用此功能创建相同的PHP加密; 但是php给我的结果是“wL2yf 72thixicjw0duQ

  • 问题内容: 我想知道AES加密后的数据大小,这样我就可以避免主要出于了解大小而缓存我的后AES数据(在磁盘或内存上)。 我使用128位AES 和进行加密。 使用各种输入大小执行的一些测试表明,如下计算的后期加密大小是正确的: 但是我不确定以上公式是否适用于所有可能的输入大小。 在应用AES加密后,是否有一种方法可以计算数据的大小-事先无需缓存(磁盘或内存中的)加密数据即可知道其加密后的大小? 问题

  • 字符串像这里一样用php加密。可以用这个用参数解密:Rijndael-256,ECB,Base64。但是我的ActionScript代码无法解密它: 更新: “它无法解密”意味着我弄错了纯文本。 在php中,明文首先由aes-256-ecb加密。然后由Base64编码。在ActionScript中,这些步骤以相反的顺序进行。 UPD2: 编码-解码测试: 在 停止后的输出是: 更新3: 它适用于P