在AutoIt和Python之间进行加密和解密转换,通常涉及使用相同的加密算法和密钥。以下是一个示例,演示如何在AutoIt和Python中使用AES对称加密算法进行加密和解密。
1、问题背景
有一位用户尝试使用 AutoIt 与 Python TCP 服务器进行加密通信,但他发现加密/解密的结果不同。
AutoIt 代码如下:
#include <Crypt.au3>
Global $key = "pjqFX32pfaZaOkkCFQuYziOApaBgRE1Y";
Global $str = "Am I welcome???"
_Crypt_Startup()
$hKey = _Crypt_DeriveKey($key, $CALG_AES_256)
$s = _Crypt_EncryptData($str, $hKey, $CALG_USERKEY)
$s = _Base64Encode($s)
ConsoleWrite("Encrypted: " & $s & @CRLF)
$s = _Base64Decode($s)
$str = _Crypt_DecryptData($s, $hKey, $CALG_USERKEY)
ConsoleWrite("Decrypted: " & BinaryToString($str) & @CRLF)
Python 代码如下:
#!/usr/bin/env python
from Crypto.Cipher import AES
import base64
import binascii
BLOCK_SIZE = 16
PADDING = binascii.unhexlify(b"07")
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
secret = 'pjqFX32pfaZaOkkCFQuYziOApaBgRE1Y'
cipher=AES.new(key=secret, mode=AES.MODE_ECB)
encoded = EncodeAES(cipher, 'Am I welcome???')
print 'Encrypted string:', encoded
decoded = DecodeAES(cipher, encoded)
print 'Decrypted string:', decoded
AutoIt 输出:
Encrypted: ZFBnThUDPRuIUAPV6vx9Ng==
Decrypted: Am I welcome???
Python 输出:
Encrypted string: NDJepp4CHh5C/FZb4Vdh4w==
Decrypted string: Am I welcome???
从输出中可以看出,加密后的结果不一致,解密后的结果也存在差异。
2、解决方案
问题可以通过改变填充方式,并在 AutoIt 中使用 rijndael.au3 来解决,具体如下:
AutoIt 代码:
#include <rijndael.au3>
#include <String.au3>
Global $key = "pjqFX32pfaZaOkkC";
Global $text = "Am I welcome???"
$encrypted = _StringToHex(BinaryToString(_rijndaelCipher($key, $text, 128, 0, '')))
ConsoleWrite("Encrypted: " & $encrypted & @CRLF)
$decrypted = BinaryToString(_rijndaelInvCipher($key, _HexToString($encrypted), 128, 0, ''))
ConsoleWrite("Decrypted: " & $decrypted & @CRLF)
Python 代码:
#!/usr/bin/env python
from Crypto.Cipher import AES
import base64
BLOCK_SIZE = 16
PADDING = chr(0)
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b16encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b16decode(e)).rstrip(PADDING)
text = 'Am I welcome???'
secret = 'pjqFX32pfaZaOkkC'
cipher=AES.new(key=secret, mode=AES.MODE_ECB)
encoded = EncodeAES(cipher, text)
print 'Python Encrypted string: ', encoded
decoded = DecodeAES(cipher, encoded)
print 'Python Decrypted string: ', decoded.encode("hex")
print 'Python Decrypted string: ', decoded
myencoded = "A6848F1EF8C7C1313689E18567235A93"
print "AutoIt Result: ", myencoded
decoded = DecodeAES(cipher, myencoded)
print 'From AU Decrypted string:', decoded
mydecoded = EncodeAES(cipher, decoded)
print 'Re-Encrypted string: ', mydecoded.upper()
AutoIt 输出:
Encrypted: A6848F1EF8C7C1313689E18567235A93
Decrypted: Am I welcome???
Python 输出:
Python Encrypted string: A6848F1EF8C7C1313689E18567235A93
Python Decrypted string: 416d20492077656c636f6d653f3f3f
Python Decrypted string: Am I welcome???
AutoIt Result: A6848F1EF8C7C1313689E18567235A93
From AU Decrypted string: Am I welcome???
Re-Encrypted string: A6848F1EF8C7C1313689E18567235A93
可以看出,使用 rijndael.au3 和相同的填充方式后,加密和解密的结果是一致的。
关键点
- 密钥:确保在AutoIt和Python中使用相同的密钥。
- 填充:确保在加密和解密过程中使用相同的填充方式。
- IV(初始向量):对于CBC模式,IV必须一致。在AutoIt中,
Crypto.au3
库会自动处理IV。 在Python中,我们显式地编码和传递IV。
注意事项
1、密钥管理:妥善保管加密密钥,不要将其暴露在不安全的环境中。
2、IV管理:对于CBC模式,加密过程中生成的IV需要在解密过程中使用,因此在传输或存储密文时需要保存IV。
通过以上示例代码,可以实现AutoIt和Python之间的AES加密和解密转换。
总体来说不是太难,只要注意知识点就没有任何问题。