我正在研究使用AES256-GCM加密某些数据库字段。我知道对于AES256-CBC,我需要为每个加密生成一个新的IV,但是我可以使用相同的密钥。 IV可以与密文一起公开存储(即可以公开)。

我开始阅读有关GCM的文章,但我不太了解某些内容。在此Stackexchange线程上声明:


GCM不需要提供IV。
关联标签不是必需的,但可以提高安全性(例如,他们给出的使用数据库ID)

,但是Wikipedia陈述了有关GCM的信息:


GCM已在具体安全模型中被证明是安全的。[13]当它与无法与随机置换区分开的分组密码操作模式一起使用时,它是安全的。但是,安全性取决于为使用同一密钥执行的每种加密选择唯一的初始化向量(请参阅流密码攻击)。需要随机生成并提供给使用GCM进行的每次加密,因此为什么stackexchange回答用户中的用户说我们不需要提供IV?

维基百科还指出:


和所有对称消息身份验证代码一样,身份验证强度取决于身份验证标签的长度。但是,不建议在GCM中使用较短的身份验证标签。标签的位长(表示为t)是安全参数。通常,它可以是以下五个值之一:128、120、112、104或96。


在OP的stackexchange线程中,OP使用tag = cipher.auth_tag。默认情况下是96吗?如果是这样,有没有办法改变它?使用128而不是96时是否存在重大的性能问题?
是否需要对关联标签(cipher.auth_data)和身份验证标签(cipher.auth_tag)保密?还是可以像IV一样保持开放?

最后,有人可以进一步解释关联标签的含义吗? OP线程中给出的答案中的示例是,我们可以使用数据库ID来确保数据属于某个数据库用户。假设一个用户具有以下数据库字段:

User
- primary_id
- encrypted_email


并且我们想在插入之前加密用户的电子邮件。使用用户primary_id==10(修改OP的ruby代码):

cipher = OpenSSL::Cipher::AES.new(128, :GCM)
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
cipher.auth_data = "10"    # Using DB user's id!

encrypted = cipher.update(data) + cipher.final
tag = cipher.auth_tag


我用数据库用户的primary_id替换了cipher.auth_data。这是正确的吗?



评论

GCM绝对需要IV。关于该线程的评论是,它不需要作为auth_data的一部分包含在内。

auth_data是任意上下文信息(例如,加密消息的数据库主密钥,用户名或将操作限定为特定“目的”的字符串),必须在解密时逐字提供。它可以是公共的,但不应由提供要解密的密文的实体控制。 auth_tag是密码的一半身份验证的输出,是解密时用来检测密钥,密文,IV或auth数据的任何更改的内容。它可以与加密输出一起存储。

#1 楼

在回答您的问题之前:
GCM是一种经过身份验证的加密操作模式,它由两个独立的功能组成:一个用于加密(AES-CTR),另一个用于认证(GMAC)。
它接收作为输入:


密钥
唯一的IV
仅通过身份验证处理的数据(关联数据)
数据将通过加密和身份验证进行处理

输出:


输入4的加密数据
身份验证TAG

身份验证TAG是解密的输入,如果有人篡改了您的关联数据或加密的数据,则GCM解密会注意到这一点,并且不会输出任何数据(或返回错误,您应该丢弃接收到的数据而不进行处理) )

现在:


,这意味着IV仍然需要随机生成并提供给使用GCM进行的每次加密,因此为什么用户
StackExchange回答帖子说我们不需要提供IV?


GCM需要IV,AES-CTR和AES-都使用它GMAC,所以无论您使用GCM做什么,都需要通过IV。
要求是唯一的,不一定是随机的。通常,实现采用96位IV,这是根据NIST推荐的使用GCM的方法。


在OP的StackExchange线程中,OP使用tag = cipher.auth_tag。默认情况下是96吗?如果是这样,是否有办法
进行更改?使用128而不是96时是否存在明显的性能问题?


默认情况下,身份验证标签为128位。您应该向邮件的接收者提供身份验证TAG,因此在某些应用程序中使用较小的标签是有意义的。请记住,标签越小,可能会遇到更多的冲突。如果带宽不是问题,请使用128。

另请参见有关auth_tag([tag_len]→此处的字符串的详细信息


关联标签(cipher.auth_data)和身份验证标签(cipher.auth_tag)是否都需要保密?还是可以像IV一样保持开放状态?


关联数据(您写错了Associated Tag)是用于公开数据的。示例是标头或目标地址。因此,它不是必须是秘密的,但是如果需要加密所有内容,则将相关数据设置为“”。
身份验证标签不是必须是秘密的,实际上,它必须未经加密地提供给接收者(像IV)。


最后,有人可以进一步解释关联标签的含义吗? OP线程中给出的答案中的示例是,我们可以使用数据库ID来确保数据属于某个数据库用户。假设用户具有以下数据库字段:


您似乎混淆了身份验证数据和身份验证标签。
身份验证数据(或关联数据)是您想通过身份验证来保护(如果有人修改了身份,您就会知道),但是不需要加密。如上所述,通常情况下,报头必须由不能解密加密消息的中间路由器读取。

身份验证标签将取决于您加密的数据和关联的数据。因此,在解密中,您还需要处理关联的数据,否则将失败。

在您的示例中(我不太清楚),您需要对主要ID和电子邮件进行身份验证,然后对电子邮件。如果将IV和TAG都存储在数据库中,则可以根据需要解密电子邮件。
如果没有身份验证标签,攻击者可以将user1的电子邮件复制到user2的电子邮件,如果他也复制了IV,那么当您查找user2的电子邮件时,您将成功解密user1的电子邮件,而无需注意任何事情。

相反,如果您还使用TAG并将相应用户的ID作为关联数据进行处理,那么攻击者将无法进行前一次攻击,因为在解密时,我们会注意到关联数据不是加密和操作中使用的数据。将失败(您将知道有人篡改了user2数据)。