【问题标题】:decrypting cipher results in missing letters [closed]解密密码导致丢失字母[关闭]
【发布时间】:2022-01-02 16:27:31
【问题描述】:

我有一个 python 端点,它使用 AES cbc 模式加密字符串并将其返回给用 c++ 编写的客户端软件(以十六进制空格分隔格式) link 用于 c++ 存储库


std::vector<unsigned char> cipher_as_chars(std::string cipher) 
{
    std::istringstream strm{cipher};
    strm >> std::hex;
    std::vector<unsigned char> res;
    res.reserve(cipher.size() / 3 + 1);
    int h;
    while (strm >> h) {
        res.push_back(static_cast<unsigned char>(h));
    }
    return res;
}
namespace client{
    std::string decrypt_cipher(std::string cipher, std::string usr_key)
    {
        std::string original_text  = "";
        const std::vector<unsigned char> key = key_from_string(usr_key);      // 16-char = 128-bit

        const unsigned char iv[16] = {
            0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x56, 0x34, 0x35, 0x36
        };
       
        std::vector<unsigned char> encrypted = cipher_as_chars(cipher);
        unsigned long padded_size = 0;
        std::vector<unsigned char> decrypted(encrypted.size());

        plusaes::decrypt_cbc(&encrypted[0], encrypted.size(), &key[0], key.size(), &iv, &decrypted[0], decrypted.size(), &padded_size);
        


        for (int i =0 ; i < decrypted.size(); i++)
        {
            //cout << decrypted[i] << endl;
            std::stringstream stream;
            stream << decrypted[i];
            original_text = original_text + stream.str();
        }

        return original_text;
    }
}

def encrypt_string(key,text):
    result = ''
    while len(text)% 16 != 0 :
        text = text+" "
    string_as_bytes = text.encode('utf8')
    
    obj = AES.new(key.encode("utf8"), AES.MODE_CBC, 'This is an IV456'.encode("utf8"))
    cipher_text = obj.encrypt(string_as_bytes)
    
    for item in bytearray(cipher_text):
        result += f"{hex(item).replace('0x','')} "
    return result

@api.route('/test')
def test_route():
    return encrypt_string("Encryptionkey123", "Happy new year people")


服务器具有与客户端软件相同的加密和解密功能,如果我使用 c++ 代码加密字符串并使用用 c++ 编写的解密函数解密它,它工作正常并且我得到相同的字符串,但是当客户端读取/test 的响应并对其进行加密,c++ 客户端尝试对其进行解密,最后输出缺少 n 个字母的字符串

python服务器中的原文Happy new year people

c++客户端中的输出Happy new year p

【问题讨论】:

  • 你做了什么来调试问题?您是否将所有输入/输出都打印为十六进制?您正在谈论获取字符串的一部分,您在发送之前和接收之后查看密文大小吗?您正在使用哪些库?请提供minimal reproducible example
  • @MaartenBodewes 对于 c++ 方面我提供了用于 python 的 AES 存储库的链接我正在使用 pycrypto 对于 c++ 方面的解密大小它是 16 字母长小于原始5
  • 好吧,我对 C++ 库的看法是正确的——尽管你为什么要使用这样的库超出了我的理解(我的意思是,我不是 C++ 开发人员,而是一个更改 @987654330 的推送请求@ 到 t_size 不明白。真的吗?你为什么忽略返回的Error?你不认为这是你可以做的非常基本的调试和验证吗?
  • @MaartenBodewes 我正在使用该存储库,因为它是一个支持 AES 加密的单个头库,因为 intt_size 我已经修复了这个问题,对于调试方面我不是专家这就是我在这里问的原因
  • 好,所以我假设您现在正在输入并试图找出返回值,比较两边的 ciphertext 大小并以十六进制打印输入/输出?跨度>

标签: python c++ aes


【解决方案1】:

看看this example pycrypto 确实支持 pkcs#7 填充,你对填充的看法很差,只需使用该模块中的内置填充功能

示例来自链接

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.Padding import unpad

key=b'1234567890123456'
cipher=AES.new(key,AES.MODE_CBC)

text=b'secret text'
padtext=pad(text,16,style='pkcs7')
cipherText=cipher.encrypt(padtext)
print(padtext)
print(cipherText)

plaintext=cipher.decrypt(cipherText)  #can't use same object to decrypt
print(plaintext)

您可能需要添加一些代码以将结果转换为十六进制分隔的字符串

【讨论】:

  • 好啊,注意unpadding也占用块大小,所以可以进行额外的检查。
  • @MaartenBodewes 我不是专业的程序员,但简单的谷歌搜索就可以解决问题
  • 请注意,简单的 Google 搜索也会显示无数“正常工作”的不安全加密示例。当然,对于高度使用的库的 API 信息通常很好。专业程序员和业余程序员之间没有区别,只是你如何应对挑战。在这种情况下,我忘记了这个库添加了填充方法,太好了,以至于 Weed Cookie 发布了答案。
  • @MaartenBodewes 不能再同意了
【解决方案2】:

问题在于 C++ 库使用 PKCS#7 填充,而 python 代码使用空格。可怕的 C++ 库不检查填充是否在块大小或填充范围内,因此它直接根据找到的最终字符的值取消填充 - 对于空间,这是 0x20。所以这将取消填充 32 个字节而不是任何正常的填充大小(我想知道当填充大于剩余的明文大小时它会做什么 - 可能是缓冲区下溢?)。

您必须在 python 中实现 PKCS#7 填充。这是将值 0x01 的 1 个字节添加到值 0x10 的 16 个字节。你可以看到一个实现here。请注意,此处显示的未填充与 C++ 库中一样易受攻击:相反,您 1 检查最后一个填充字节是否在 1.. 范围内,然后检查所有其他填充字节是否也正确,如果没有,则创建异常或错误代码。

还要注意 CBC 填充预言、静态 IV 的使用等。使用 TLS 来确保传输安全。

【讨论】:

    猜你喜欢
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2016-01-03
    • 1970-01-01
    • 2021-08-31
    相关资源
    最近更新 更多