使用 Bouncy Castle 在 C# 中加密并使用 AES(EAX 模式)在 Python 中解密的问题
Issue with encrypting in C# using Bouncy Castle and decrypting in Python using AES (EAX Mode)
我正在尝试使用 AES 中的 EAX 模式在 C# 中加密文本并在 python 中解密它。我在 C# 中将 Bouncy Castle 用于 EAX,将 AES 用于 Python.
我能够在 C# 和 Python 中成功加密和解密,但是我注意到当 C# 加密文本时,输出比 Python 加密时长得多它。
不确定它是否相关,但我通过服务器将它从 C# 发送到 Python,并且我确认所有内容都按应有的方式发送。客户端是 运行 一个 Android 模拟器,而服务器是 运行 Windows 10.
我用来测试 C# 代码的方法:
const int MAC_LEN = 16
//The Key and Nonce are randomly generated
AeadParameters parameters = new AeadParameters(key, MAC_LEN * 8, nonce);
string EaxTest(string text, byte[] key, AeadParameters parameters)
{
KeyParameter sessKey = new KeyParameter(key);
EaxBlockCipher encCipher = new EAXBlockCipher(new AesEngine());
EaxBlockCipher decCipher = new EAXBlockCipher(new AesEngine());
encCipher.Init(true, parameters);
byte[] input = Encoding.Default.GetBytes(text);
byte[] encData = new byte[encCipher.GetOutputSize(input.Length)];
int outOff = encCipher.ProcessBytes(input, 0, input.Length, encData, 0);
outOff += encCipher.DoFinal(encData, outOff);
decCipher.Init(false, parameters);
byte[] decData = new byte[decCipher.GetOutputSize(outOff)];
int resultLen = decCipher.ProcessBytes(encData, 0, outOff, decData, 0);
resultLen += decCipher.DoFinal(decData, resultLen);
return Encoding.Default.GetString(decData);
}
我用来测试 python 代码的方法:
def encrypt_text(data, key):
cipher = AES.new(key, AES.MODE_EAX)
nonce = cipher.nonce
cipher_text, mac_tag = cipher.encrypt_and_digest(data)
return [cipher_text, mac_tag, nonce]
def decrypt_text(data, key, mac_tag, nonce):
decrypt = AES.new(key, AES.MODE_EAX, nonce=nonce, mac_len=16)
plaintext = decrypt.decrypt_and_verify(data, mac_tag)
return plaintext
对于字符串 "a" 的测试,在 C# 中,我始终获得 17 个字节的加密文本,而使用 python 我始终获得 1 个字节的加密文本。
当我尝试在 python 中解密时,出现此错误 [ValueError: MAC check failed]。 Mac 和 nonce 都是 16 字节。
示例 C# 输出:34 2D 0A E9 8A 37 AC 67 0E 95 DB 91 D7 8C E5 4E 9F
示例Python 输出:DD
C# 中的默认编码是 UTF-16LE,它应该为您提供两个字节的明文和两个字节的密文。但是在C#/Bouncy Castle代码中,返回的密文末尾包含16字节的认证标签。显然你少了一个字节,17 个字节少了一个字节。所以密文的传输在某处失败了。当然,那样的话,认证标签的验证也会失败。
在Python中,密文为1字节,认证标签为16字节。这对于单个字节的输入是正确的。您的编码不在给定的代码片段中,但我认为它是 UTF-8 中的一个字节。
确保您的 C# 代码也使用 UTF-8,并确保正确传输密文。确保在需要通过文本接口传输的地方使用 base 64,并且不要跳过零值字节。最后,如果您使用随机随机数,请确保将其与密文一起传输(通常带有前缀)。毕竟你应该没问题。
我正在尝试使用 AES 中的 EAX 模式在 C# 中加密文本并在 python 中解密它。我在 C# 中将 Bouncy Castle 用于 EAX,将 AES 用于 Python.
我能够在 C# 和 Python 中成功加密和解密,但是我注意到当 C# 加密文本时,输出比 Python 加密时长得多它。
不确定它是否相关,但我通过服务器将它从 C# 发送到 Python,并且我确认所有内容都按应有的方式发送。客户端是 运行 一个 Android 模拟器,而服务器是 运行 Windows 10.
我用来测试 C# 代码的方法:
const int MAC_LEN = 16
//The Key and Nonce are randomly generated
AeadParameters parameters = new AeadParameters(key, MAC_LEN * 8, nonce);
string EaxTest(string text, byte[] key, AeadParameters parameters)
{
KeyParameter sessKey = new KeyParameter(key);
EaxBlockCipher encCipher = new EAXBlockCipher(new AesEngine());
EaxBlockCipher decCipher = new EAXBlockCipher(new AesEngine());
encCipher.Init(true, parameters);
byte[] input = Encoding.Default.GetBytes(text);
byte[] encData = new byte[encCipher.GetOutputSize(input.Length)];
int outOff = encCipher.ProcessBytes(input, 0, input.Length, encData, 0);
outOff += encCipher.DoFinal(encData, outOff);
decCipher.Init(false, parameters);
byte[] decData = new byte[decCipher.GetOutputSize(outOff)];
int resultLen = decCipher.ProcessBytes(encData, 0, outOff, decData, 0);
resultLen += decCipher.DoFinal(decData, resultLen);
return Encoding.Default.GetString(decData);
}
我用来测试 python 代码的方法:
def encrypt_text(data, key):
cipher = AES.new(key, AES.MODE_EAX)
nonce = cipher.nonce
cipher_text, mac_tag = cipher.encrypt_and_digest(data)
return [cipher_text, mac_tag, nonce]
def decrypt_text(data, key, mac_tag, nonce):
decrypt = AES.new(key, AES.MODE_EAX, nonce=nonce, mac_len=16)
plaintext = decrypt.decrypt_and_verify(data, mac_tag)
return plaintext
对于字符串 "a" 的测试,在 C# 中,我始终获得 17 个字节的加密文本,而使用 python 我始终获得 1 个字节的加密文本。 当我尝试在 python 中解密时,出现此错误 [ValueError: MAC check failed]。 Mac 和 nonce 都是 16 字节。
示例 C# 输出:34 2D 0A E9 8A 37 AC 67 0E 95 DB 91 D7 8C E5 4E 9F
示例Python 输出:DD
C# 中的默认编码是 UTF-16LE,它应该为您提供两个字节的明文和两个字节的密文。但是在C#/Bouncy Castle代码中,返回的密文末尾包含16字节的认证标签。显然你少了一个字节,17 个字节少了一个字节。所以密文的传输在某处失败了。当然,那样的话,认证标签的验证也会失败。
在Python中,密文为1字节,认证标签为16字节。这对于单个字节的输入是正确的。您的编码不在给定的代码片段中,但我认为它是 UTF-8 中的一个字节。
确保您的 C# 代码也使用 UTF-8,并确保正确传输密文。确保在需要通过文本接口传输的地方使用 base 64,并且不要跳过零值字节。最后,如果您使用随机随机数,请确保将其与密文一起传输(通常带有前缀)。毕竟你应该没问题。