首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python加密填充在C#解密中引起问题

Python加密填充在C#解密中引起问题
EN

Stack Overflow用户
提问于 2015-11-17 12:44:13
回答 1查看 1.8K关注 0票数 2

我对跨语言的加密/解密有点问题。

下面是我的python代码来加密一些文本:

代码语言:javascript
复制
class AESCipher:
    def __init__( self, key, iv ):
        self.key = base64.b64decode(key)
        self.iv = base64.b64decode(iv)
    def encrypt( self, raw ):

        BS = 16
        pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
        raw = pad(raw)


        cipher = AES.new( self.key, AES.MODE_CBC, self.iv)
        res = self.iv + cipher.encrypt( raw )
        return base64.b64encode(res) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        unpad = lambda s : s[:-ord(s[len(s)-1:])]
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
        return unpad(cipher.decrypt( enc[16:] ))

crypt = AESCipher("key", "iv")
print "{0}".format(crypt.encrypt("Hallow"))

和C#解密:

代码语言:javascript
复制
public static string DecryptStringFromBase64(string base64String)
{
    byte[] bytes = Decrypt(Convert.FromBase64String(base64String));
    var utf8 = Encoding.UTF8.GetString(bytes);
    return utf8;
}

public static byte[] Decrypt(byte[] bytes)
{
    AesManaged algorithm = new AesManaged();
    algorithm.IV = Convert.FromBase64String("IV");
    algorithm.Key = Convert.FromBase64String("KEY");

    byte[] ret = null;
    using (var decryptor = algorithm.CreateDecryptor())
    {
        using (MemoryStream msDecrypted = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msDecrypted, decryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(bytes, 0, bytes.Length);
            }
            ret = msDecrypted.ToArray();
        }
    }
    return ret;
}

然而,解密后的值总是不正确地显示如下:

我想这和垫子有关,谁能建议怎么绕过这件事?

EN

回答 1

Stack Overflow用户

发布于 2015-11-17 13:01:12

问题不是填充物。是你还没切掉的静脉输液。IV不一定是秘密的,但每次加密都应该随机生成。由于您已经将IV包含到Python中的密文中,所以您必须在解密期间在C#中使用它(当然,应该对实际的密文进行解密,不包括IV):

C#

代码语言:javascript
复制
public static string DecryptStringFromBase64(string base64String)
{
    byte[] bytes = Decrypt(Convert.FromBase64String(base64String));
    var utf8 = Encoding.UTF8.GetString(bytes);
    return utf8;
}

public static byte[] Decrypt(byte[] bytes)
{
    byte[] iv = new byte[16]; // change
    Array.copy(bytes, iv, 16); // change
    AesManaged algorithm = new AesManaged();
    algorithm.IV = iv; // change
    algorithm.Key = Convert.FromBase64String("KEY");

    byte[] ret = null;
    using (var decryptor = algorithm.CreateDecryptor())
    {
        using (MemoryStream msDecrypted = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msDecrypted, decryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(bytes, 16, bytes.Length - 16); // change
            }
            ret = msDecrypted.ToArray();
        }
    }
    return ret;
}

Python代码也不是没有问题的。你不需要通过静脉注射,因为你把它放在密文里。因此,您可以创建一个新的随机IV。此外,unpad函数是不正确的(或者至少不必要地复杂)。

代码语言:javascript
复制
class AESCipher:
    def __init__( self, key):
        self.key = base64.b64decode(key)

    def encrypt( self, raw ):

        BS = 16
        pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
        raw = pad(raw)

        iv = Random.new().read(BS)

        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        res = iv + cipher.encrypt( raw )
        return base64.b64encode(res) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        BS = 16
        iv = enc[:BS]
        unpad = lambda s : s[:-ord(s[-1])]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[BS:] ))

crypt = AESCipher("key", "iv")
print "{0}".format(crypt.encrypt("Hallow"))

别忘了验证你的密文。否则,可能会对您的系统发起填充oracle攻击,从而使攻击能够使用多个联机查询对每个密文进行解密。

您可以使用经过身份验证的模式,如GCM或EAX,也可以使用加密后MAC方案,使用强MAC(如HMAC-SHA256 256)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33757283

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档