将C#加密算法转换为Python 3
我已经得到了一个现有的加密算法,在将密码发送到API之前需要对密码进行加密 除了Python,我以前没有任何其他语言的经验,因此我无法理解在功能上我需要做什么来复制它 我相信C#中AES的默认模式是CBC。我想我已经复制了所需的大部分工作,但我需要填充数据,我不知道这到底发生在什么阶段,或者长度是在哪里添加的。我不明白在C代码中事情发生的顺序。我还相信默认的填充方法是PKCS#7,尽管我很高兴在这方面得到纠正将C#加密算法转换为Python 3,c#,python,.net,encryption,aes,C#,Python,.net,Encryption,Aes,我已经得到了一个现有的加密算法,在将密码发送到API之前需要对密码进行加密 除了Python,我以前没有任何其他语言的经验,因此我无法理解在功能上我需要做什么来复制它 我相信C#中AES的默认模式是CBC。我想我已经复制了所需的大部分工作,但我需要填充数据,我不知道这到底发生在什么阶段,或者长度是在哪里添加的。我不明白在C代码中事情发生的顺序。我还相信默认的填充方法是PKCS#7,尽管我很高兴在这方面得到纠正 Original code public static string Encrypt
Original code
public static string EncryptStringToBytes_Aes(string username, string password)
{
string encrypted = string.Empty;
byte[] clearBytes = Encoding. UTF8.GetBytes(password);
using (Aes aesAlg = Aes.Create())
{
byte[] k;
byte[] iv;
byte[] bytes = Encoding.UTF8.GetBytes(username);
k = SHA256.Create().ComputeHash(bytes);
iv = MD5.Create().ComputeHash(bytes);
aesAlg.Key = k;
aesAlg.IV = iv;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key,
aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt,
encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(clearBytes, 0, clearBytes.Length);
}
encrypted = Convert.ToBase64String(msEncrypt.ToArray());
}
}
return encrypted;
}
我得到一个“ValueError:输入字符串的长度必须是16的倍数”
当我尝试一些填充时,encode状态为“AttributeError:‘bytes’对象没有属性‘encode’”
我希望能够阅读此代码的人能够帮助我完成用Python重新创建功能的最后步骤。看看,您没有正确使用密码模块
调用AES.new()
时,传入的键需要是16个字节的字符串,因此需要将key
属性填充为16个字节的长度
encrypt()
方法将字节字符串作为输入,当您试图传入一个长度时(在您的示例中甚至没有定义)
您的评论表明您已经通过了,否则您将不会看到AttributeError
异常
您看到的AttributeError
是因为Cipher.encrypt()
返回一个字节数组,而字节数组没有encode()
方法。您需要首先将字节数组转换为字符串。来自的以下代码段应有帮助:
import array
decoded = array.array('b', your_input).tostring().decode('utf-8')
显然,您应该将'utf-8'
替换为'base64'
查看,您没有正确使用密码模块
调用AES.new()
时,传入的键需要是16个字节的字符串,因此需要将key
属性填充为16个字节的长度
encrypt()
方法将字节字符串作为输入,当您试图传入一个长度时(在您的示例中甚至没有定义)
您的评论表明您已经通过了,否则您将不会看到AttributeError
异常
您看到的AttributeError
是因为Cipher.encrypt()
返回一个字节数组,而字节数组没有encode()
方法。您需要首先将字节数组转换为字符串。来自的以下代码段应有帮助:
import array
decoded = array.array('b', your_input).tostring().decode('utf-8')
显然,您应该将
'utf-8'
替换为'base64'
我相信我已经成功了,使用了这里的答案和注释。不需要填充密钥,因为哈希值已经是16的倍数。下面是(希望)成功的代码供参考。(不幸的是,在我测试连接之前,我还要翻译另外两段C代码!)
我相信我已经成功了,在这里我综合运用了答案和评论。不需要填充密钥,因为哈希值已经是16的倍数。下面是(希望)成功的代码供参考。(不幸的是,在我测试连接之前,我还要翻译另外两段C代码!)
对不起,我漏掉了这一行
length=password+'0'+str(len(clearbytes))
看起来不错,应该可以修复输出,我希望一切都只需要PKCS#7填充,但是原始代码行csEncrypt.Write(clearbytes,0,clearbytes.length)
让我担心,因为我不确定它到底在做什么!建议按键不是好建议。应该说为AES-128生成一个随机的16字节密钥。可能可以通过使用PBKDF函数Argon2、Bcrypt和PBKDF2从密码生成length=password+'0'+str(len(clearbytes))
看起来不错,应该可以修复输出,我希望一切都只需要PKCS#7填充,但是原始代码行csEncrypt.Write(clearbytes,0,clearbytes.length)
让我担心,因为我不确定它到底在做什么!建议按键不是好建议。应该说为AES-128生成一个随机的16字节密钥。可能可以通过使用PBKDF函数Argon2、Bcrypt和PBKDF2从密码生成。您可以在Crypto.Util.padding
中找到填充函数,或者如果您使用PyCrypto,则可以复制PyCryptodome的填充函数。然而,您的C#代码看起来并不好:它使用散列作为kdf、确定性IV,并且没有身份验证。这些因素可能会降低甚至破坏加密方案的安全性。感谢您的帮助!是的,我知道加密不是很好,它是一个外部公司的API,所以我们必须按要求跳转。幸运的是,这不是我们特别需要保持安全的东西:我们只需要它工作!您可以在Crypto.Util.padding
中找到填充函数,或者如果您使用的是PyCrypto,则可以复制PyCryptodome的填充函数。然而,您的C#代码看起来并不好:它使用散列作为kdf、确定性IV,并且没有身份验证。这些因素可能会降低甚至破坏加密方案的安全性。感谢您的帮助!是的,我知道加密不是很好,它是一个外部公司的API,所以我们必须按要求跳转。幸运的是,这不是我们特别需要保持安全的东西:我们只需要它工作!
Python Conversion
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import hashlib
import base64
username = "example"
password = "example"
mode = AES.MODE_CBC
bytes = username.encode('utf-8')
data_for_padding = password + '0' + str(len(password))
padded = pad(data_for_padding)
key = hashlib.sha256(bytes).digest()
iv = hashlib.md5(bytes).digest()
encryptor = AES.new(key, mode, IV = iv)
clearbytes = padded.encode('utf-8')
ciphertext = encryptor.encrypt(clearbytes)
result = base64.b64encode(ciphertext)