当前位置: 首页 > 知识库问答 >
问题:

使用初始化向量和填充正确实现 AES 128 加密

高德水
2023-03-14

我使用初始化向量和填充实现了AES 128位加密,如下面的代码所示。我碰巧使用了ColdFusion,但我认为这并不重要。加密结果显示了一些重复模式,这是我没有预料到的,但话说回来,我不知道正确输出的特征。我是否正确地进行了初始化向量和填充?

<!---
To encrypt this, for example:
    "String1"
Prefix the string with an Initialization Vector of 16 random characters,
plus enough padding ("000000001") to make the entire string a multiple of 16 characters (32 characters, here)
    "HoMoz4yT0+WAU7CX000000001String1"
Now encrypt the string to this (64 characters):
    "Bn0k3q9aGJt91nWNA0xun6va8t8+OiJVmCqv0RzUzPWFyT4jUMzZ56pG5uFt6bGG"
--->

<cfoutput>

    <cfset EncryptKey="LpEecqQe3OderPakcZeMcw==">

    <cfloop index="StringToEncrypt" list="String1,String2,String3,String3">
        <!--- Make random Initialization Vector (IV) of length 16 
        (create it from GenerateSecretKey(), but GenerateSecretKey is NOT the key that we encrypt/decrypt with) --->
        <cfset IV=left(GenerateSecretKey("AES",128),16)>
        <!--- Pad the string so its length is a multiple of 16 --->
        <cfset padlength=16 - (len(StringToEncrypt) mod 16)>
        <cfset padding=repeatstring("0",padlength-1) & "1">
        <cfset NewStringToEncrypt=IV & padding & StringToEncrypt>
        <cfset EncryptedString=encrypt(NewStringToEncrypt,EncryptKey,"AES","Base64")>
<pre>Original string: #StringToEncrypt#
StringToEncrypt: #NewStringToEncrypt#
EncryptedString: #EncryptedString#</pre>
    </cfloop>

</cfoutput>

下面是示例输出:

Original string: String1
StringToEncrypt: QLkApY6XKka7mQge000000001String1
EncryptedString: BOAVeSKidQyyHrEa15x9Uava8t8+OiJVmCqv0RzUzPWFyT4jUMzZ56pG5uFt6bGG

Original string: String2
StringToEncrypt: DboCmHHuVrU05oTV000000001String2
EncryptedString: 4Yk14F0ffz9+djbvSiwA1/X3FHhS5Vhta7Q8iocBPhmFyT4jUMzZ56pG5uFt6bGG

Original string: String3
StringToEncrypt: 8om5VbbWQgvRWK7Q000000001String3
EncryptedString: 01AF+pmF9sDsUHcIXSVfom8Egv8Oiyb2yy12hiVcJjqFyT4jUMzZ56pG5uFt6bGG

Original string: String3
StringToEncrypt: T4qJodVe6aEv0p1E000000001String3
EncryptedString: aAjCbSBRZ+cd7ZwpFPZUxW8Egv8Oiyb2yy12hiVcJjqFyT4jUMzZ56pG5uFt6bGG

每个加密字符串都以相同的21个字符结尾:

FyT4jUMzZ56pG5uFt6bGG

当原始字符串相同(第3和第4个示例中的“String3”)时,EncryptedString以相同的42个字符结尾:

8Egv8Oiyb2yy12hiVcJjqFyT4jUMzZ56pG5uFt6bGG

更新:根据公认的答案,我不应该做自己的填充或初始化向量。Cold

EncryptedString=encrypt(StringToEncrypt, EncryptKey, 'AES/CBC/PKCS5Padding', 'Base64')
DecryptedString=decrypt(EncryptedString, EncryptKey, 'AES/CBC/PKCS5Padding', 'Base64')

共有2个答案

方宏才
2023-03-14

一个可能的原因是,您使用的AES模式在加密当前块之前不会将前一块与当前块一起使用。

例如,CBC模式在加密当前块之前与前一个块密码文本和当前块明文执行异或。这意味着即使使用相同的字符串(“string3”)和相同的密钥,不同的IV也会产生完全不同的结果,并且永远不会有字符串重复。

使用xor的其他AES模式包括:CBC、PCBC、OFB和CFB。此链接更详细地描述了AES的不同模式(在“共模”部分)。

宓跃
2023-03-14

不要自己填充,而是让加密函数来填充。它附加在明文后面,而不是前面。通常的填充称为PKCS5填充,并将$t$乘以{1,2,3,\ldots,16}$中的字节$t\,以组成完整的块。

此外,iv 是加密函数的参数,而不是在明文之前预置。它实际上(当您使用像 CBC、OFB、CFB 这样的链模式时)附加到密文前面。

因此,您可以像这样生成IV(尽管可能有更好的函数来完成它),然后按原样使用明文并加密:

EnCryptedString=加密(StringToEnCrypt, EnCryptKey,'AES/CBC/PKCS5P的','Base64', bin ary Decode(IV,"Bas64"))

(基于本文档)

添加了2根据这些文档,iv应该是二进制的,因此必须转换来自genateKey的Bas64。感谢@Agax和他的“cftry”示例的评论…

增加了1原来省略IV会导致函数生成自己的IV,而且是以一种看似不重复的方式。在任何情况下我们都可以使用

EncryptedString=encrypt(StringToEncrypt, EncryptKey, 'AES/CBC/PKCS5Padding', 'Base64')

相反。使用像CBC这样的链接模式来获得随机IV的传播效果是至关重要的,该随机IV屏蔽了相同的明文并且默认的“AES”使其可见(大概是ECB模式)。

当我们将其作为参数给出时,IV实际上并没有附加到密文前面,因此您必须以某种方式记住它才能解密第一块纯文本。相当不标准。当您让加密自己生成它时,它确实会先置它。因此,您必须使用相同的签名版本的解密。

 类似资料:
  • 在从Delphi2007迁移到XE2的过程中,我们正在考虑将加密库从DCPCrypt切换到Turbopower Lockbox 3。 a) 在DCPCrypt中,我可以显式控制初始化向量。如何在TPLB3中设置IV? b)DCPCrypt没有填充,我们在加密前用零填充明文。TPLB垫如何?当然,我们仍然可以自己做。 密码=AES-256; 链接模式=CBC; 终止=C#样式全零填充; IV传输=在

  • 问题内容: 我有一个关于在AES加密中使用初始化向量的问题。我引用以下文章/帖子将加密功能构建到程序中: [1] 基于Java256位AES密码的加密 [2]http://gmailassistant.sourceforge.net/src/org/freeshell/zs/common/Encryptor.java.html 我最初从第一个链接开始关注erickson的解决方案,但是据我所知,我

  • 问题内容: 当我运行此代码时: 但是我得到警告 所以我去看了看文档,但是“没有文档”。但仍然没有提到初始化向量是什么以及如何使用它。谁能启发我? 我知道我可以做更多的Google搜索工作,但是在众多搜索结果中排在首位,我认为这个问题对其他遇到此问题的人可能很有用。 问题答案: IV通常是一个随机数,可确保加密文本是唯一的。 为了解释为什么需要它,让我们假设我们有一个用密钥“秘密”而不用IV加密的人

  • 我在一个项目中工作,在这个项目中,我通过XML流向web服务发帖。在这种情况下,提供程序请求使用密码块链接(CBC)模式下的高级加密标准(AES)和128位初始化向量对路由xml进行加密。我是用VB.NET编码的,从我可以看出我已经满足了他们所有的加密要求,但当我提交帖子时,我总是得到一个“无效的路由输入加密”的错误响应。我没有做很多与加密,所以我希望有人与一些加密经验可以帮助我在这里。它失败是因

  • 我已经编写了一个Java程序,它要求用户指定一个随机密钥(以base 64编码),指定要加密的纯文本文件,以及输出文件的名称(加密的文本文件)。 然后反向解密(密钥输入加密文件名输出解密文件)。 这遵循与OpenSSL提供的非常相似的行为。 我的java代码使用模式。 我已经使用文件输出流事先将随机生成的初始化向量(16 字节 IV)附加到我的密文中。然后我相信密码输出流在 IV 之后写入密文。

  • 假设我初始化一个空数据帧如下: 生成的具有以下形式 有没有一种pythonic方法可以将s替换为其他值,例如?当然,一种方法是简单地将其指定为数据: 也许有更简洁的方法?