注意:这个问题最初把“数字签名”和"MAC“混为一谈,而我后来了解到,这并不是一回事。对“签名”的任何提及(在答复或任何评论中)都应理解为"MAC“。
我正在试验奥斯代币,我正试着用最好的方法来解决这个问题。
accountID、nonce和expiry的令牌。然后将令牌传递回客户端,用于下一个请求。accountID)。MAC是从plaintext值创建的,以确保它没有被篡改。plaintext值(包括MAC)进行加密,以确保其安全模糊。macKey或encryptionKey。客户端不打算访问令牌的plaintext内容。///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
});MAC-then-encrypt方法安全吗?我读过一些关于这方面的意见,比我开始的时候更困惑地走开了。cbc-mode方法时应该使用MAC-then-encrypt。这是CryptoJS.AES.encrypt()的默认模式吗?CryptoJS.AES似乎相当通用。这是默认的AES256吗?或者这是我需要在代码中明确声明的东西吗?CryptoJS.AES.encrypt()时,我看到它会自动生成一个“幕后”的key和iv。生成自己的key和iv会更安全吗?还是应该让CryptoJS来处理呢?MAC-encrypt-MAC方法可以获得更多的安全性,还是仅仅增加了我的应用程序逻辑的复杂性?发布于 2016-12-19 20:09:56
首先,考虑到您的示例代码使用的是HMAC,而不是数字签名,我想您的意思是MAC然后加密。
通常组合MAC和加密的安全方法是加密-然后- MAC :首先加密消息,然后计算加密文本上的MAC(包括IV和任何相关的数据!)。解密时,首先验证MAC,然后尝试解密消息。
加密MAC是安全的,因为它保证MAC和密码各自只需要完成自己的工作:加密时,MAC只接收已经加密的输入,因此不能意外泄露明文的信息;解密时,密码只接收已经通过MAC认证的输入,因此不需要担心安全处理伪造或修改的消息。
然而,如果MAC和密码选择得当,MAC-然后加密(甚至MAC加加密)可以是安全的.特别是,MAC-然后加密的一个充分条件是密码模式必须保持长度-也就是说,密码文本(不包括IV)必须与输入明文一样长。
CFB、OFB和CTR模式都是保持长度的,但CBC不是(除非与被称为“窃取密文”的修改相结合)。特别是,由于普通的CBC模式需要将消息填充到整数个密码块中,所以它通常容易受到填充甲骨文攻击的攻击,除非在加密后应用了一个MAC保护(因此在解密之前进行了验证)。因此,您不应该使用CBC模式与MAC-然后-加密.
这很难说,而且可能取决于您正在使用的CryptoJS版本。此页说默认的是OFB模式。此页 (代表CryptoJS v3)表示,这是CFB。这两种方式似乎都是非官方的第三方来源,但我还没有为这个库找到任何全面的官方文档。显然是“还是有点稀疏”:
在任何情况下,如上所述,您不应该使用CBC模式与MAC-然后-加密.如果您想使用CBC,加密后应用MAC。
见先前的答案。根据链接的Google组帖子(当然也可能不可靠),库可以处理AES-128、AES-192或AES-256,这可能取决于您传入的密钥的大小。如果你只输入一个密码,我不知道它会选择哪个AES变体。
(我还想借此机会重申我不喜欢文件不全的密码库。 --无论您的库编码得有多好,如果没有人知道它应该做什么,以及如何正确和安全地使用它。)
看起来,如果您将一个普通字符串作为键传递给encrypt()方法,它将假设该字符串是用户提供的密码,并在其上应用基于密码的密钥派生函数(如PBKDF2 )。这样的功能被故意设计为缓慢,以抵抗蛮力密码破解.因此,只要有可能,只调用键派生函数一次,并存储它输出的原始AES和/或HMAC密钥,效率更高。
您几乎肯定没有任何理由提供您自己的IV;任何像样的密码库都应该能够为您生成非常好的随机IVs。
一般来说,没有必要做MAC加密-MAC,而不是普通加密-然后-MAC。尽管如此,它也不应该伤害(除了浪费几个CPU周期,并稍微增加您的密文长度),它可能会保护您避免一些实现错误(比如忘记在外部MAC输入中包含IV )。
但是,如果可能的话,您真正应该做的是使用一个集成的认证加密模式,比如SIV (我当前的个人最爱)或GCM (甚至是结合它们的新的GCM模式)。这些加密模式都内置了消息认证,并注意将加密和认证安全、正确地结合在一起。
(对于实际的数字签名,签名-加密-签名有时可能是有用的,因为双重签名可以防止一些攻击,例如攻击者获取有效的加密-然后签名的消息,去掉签名并替换自己的签名,或者恶意接收者解密签名后加密的消息,并将其重发给其他人,同时保留原始签名。然而,在大多数情况下,有更有效的方法来避免这种攻击。参见这个先前的问题获取更多详细信息。)
https://crypto.stackexchange.com/questions/42369
复制相似问题