首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个对称密钥MAC然后加密令牌方法是否安全?

这个对称密钥MAC然后加密令牌方法是否安全?
EN

Cryptography用户
提问于 2016-12-17 01:28:53
回答 1查看 620关注 0票数 1

注意:这个问题最初把“数字签名”和"MAC“混为一谈,而我后来了解到,这并不是一回事。对“签名”的任何提及(在答复或任何评论中)都应理解为"MAC“。

我正在试验奥斯代币,我正试着用最好的方法来解决这个问题。

目标

  1. 成功登录后,将创建包含用户accountIDnonceexpiry的令牌。然后将令牌传递回客户端,用于下一个请求。
  2. 客户端将令牌与每个请求一起传递回服务器,以标识任何给定请求的来源(accountID)。
  3. 该令牌包含一个随每个请求而更改的值。
  4. MAC是从plaintext值创建的,以确保它没有被篡改。
  5. 然后对令牌的plaintext值(包括MAC)进行加密,以确保其安全模糊。
  6. 客户端从来不了解macKeyencryptionKey。客户端不打算访问令牌的plaintext内容。

电流法

代码语言:javascript
复制
///process.env.TOKEN_ENCRYPTION_PASSWORD = '13sd4089f-268c-483d-9e82-jk3c1b47c77a';
///process.env.TOKEN_MAC_KEY = '1fde05f4-268c-483d-9e82-85fc1b42321';

/// Successful login by user ...

var token = {
    nonce : 'SOME-UUID-GOES-HERE',
    accountID : 'account-12345',
    expires : 1234567890
};

token.mac = crypto.createHmac('sha512', TOKEN_MAC_KEY)
                  .update(JSON.stringify(token))
                  .digest('base64');

var encryptedToken = cryptoJS.AES.encrypt(JSON.stringify(token), TOKEN_ENCRYPTION_PASSWORD).toString();

response.send({
    message : 'Created, MAC'd, and encrypted an auth token.',
    authToken : encryptedToken
});

问题

  1. 在这种情况下,使用MAC-then-encrypt方法安全吗?我读过一些关于这方面的意见,比我开始的时候更困惑地走开了。
  2. 我已经读过,在使用cbc-mode方法时应该使用MAC-then-encrypt。这是CryptoJS.AES.encrypt()的默认模式吗?
  3. CryptoJS.AES似乎相当通用。这是默认的AES256吗?或者这是我需要在代码中明确声明的东西吗?
  4. 当将字符串传递给CryptoJS.AES.encrypt()时,我看到它会自动生成一个“幕后”的keyiv。生成自己的keyiv会更安全吗?还是应该让CryptoJS来处理呢?
  5. 通过使用MAC-encrypt-MAC方法可以获得更多的安全性,还是仅仅增加了我的应用程序逻辑的复杂性?
EN

回答 1

Cryptography用户

回答已采纳

发布于 2016-12-19 20:09:56

  1. 在这种情况下,使用签名加密方法安全吗?我读过一些关于这方面的意见,比我开始的时候更困惑地走开了。

首先,考虑到您的示例代码使用的是HMAC,而不是数字签名,我想您的意思是MAC然后加密。

通常组合MAC和加密的安全方法是加密-然后- MAC :首先加密消息,然后计算加密文本上的MAC(包括IV和任何相关的数据!)。解密时,首先验证MAC,然后尝试解密消息。

加密MAC是安全的,因为它保证MAC和密码各自只需要完成自己的工作:加密时,MAC只接收已经加密的输入,因此不能意外泄露明文的信息;解密时,密码只接收已经通过MAC认证的输入,因此不需要担心安全处理伪造或修改的消息。

然而,如果MAC和密码选择得当,MAC-然后加密(甚至MAC加加密)可以是安全的.特别是,MAC-然后加密的一个充分条件是密码模式必须保持长度-也就是说,密码文本(不包括IV)必须与输入明文一样长。

CFB、OFB和CTR模式都是保持长度的,但CBC不是(除非与被称为“窃取密文”的修改相结合)。特别是,由于普通的CBC模式需要将消息填充到整数个密码块中,所以它通常容易受到填充甲骨文攻击的攻击,除非在加密后应用了一个MAC保护(因此在解密之前进行了验证)。因此,您不应该使用CBC模式与MAC-然后-加密.

  1. 我读过cbc模式在使用签名加密方法时应该使用.这是CryptoJS.AES.encrypt()的默认模式吗?

这很难说,而且可能取决于您正在使用的CryptoJS版本。此页说默认的是OFB模式。此页 (代表CryptoJS v3)表示,这是CFB。这两种方式似乎都是非官方的第三方来源,但我还没有为这个库找到任何全面的官方文档。显然是“还是有点稀疏”

在任何情况下,如上所述,您不应该使用CBC模式与MAC-然后-加密.如果您想使用CBC,加密后应用MAC。

  1. CryptoJS.AES似乎相当通用。这是默认的AES256吗?或者这是我需要在代码中明确声明的东西吗?

见先前的答案。根据链接的Google组帖子(当然也可能不可靠),库可以处理AES-128、AES-192或AES-256,这可能取决于您传入的密钥的大小。如果你只输入一个密码,我不知道它会选择哪个AES变体。

(我还想借此机会重申我不喜欢文件不全的密码库。 --无论您的库编码得有多好,如果没有人知道它应该做什么,以及如何正确和安全地使用它。)

  1. 当将字符串传递给CryptoJS.AES.encrypt()时,我看到它自动生成一个键和iv‘幕后’。生成自己的密钥和iv会更安全吗?还是应该让CryptoJS来处理呢?

看起来,如果您将一个普通字符串作为键传递给encrypt()方法,它将假设该字符串是用户提供的密码,并在其上应用基于密码的密钥派生函数(如PBKDF2 )。这样的功能被故意设计为缓慢,以抵抗蛮力密码破解.因此,只要有可能,只调用键派生函数一次,并存储它输出的原始AES和/或HMAC密钥,效率更高。

您几乎肯定没有任何理由提供您自己的IV;任何像样的密码库都应该能够为您生成非常好的随机IVs。

  1. 通过使用符号加密签名方法是否有更多的安全性,还是仅仅增加了我的应用程序逻辑的复杂性?

一般来说,没有必要做MAC加密-MAC,而不是普通加密-然后-MAC。尽管如此,它也不应该伤害(除了浪费几个CPU周期,并稍微增加您的密文长度),它可能会保护您避免一些实现错误(比如忘记在外部MAC输入中包含IV )。

但是,如果可能的话,您真正应该做的是使用一个集成的认证加密模式,比如SIV (我当前的个人最爱)或GCM (甚至是结合它们的新的GCM模式)。这些加密模式都内置了消息认证,并注意将加密和认证安全、正确地结合在一起。

(对于实际的数字签名,签名-加密-签名有时可能是有用的,因为双重签名可以防止一些攻击,例如攻击者获取有效的加密-然后签名的消息,去掉签名并替换自己的签名,或者恶意接收者解密签名后加密的消息,并将其重发给其他人,同时保留原始签名。然而,在大多数情况下,有更有效的方法来避免这种攻击。参见这个先前的问题获取更多详细信息。)

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

https://crypto.stackexchange.com/questions/42369

复制
相关文章

相似问题

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