如果在encryption之前已知明文的开始处是否存在漏洞?

假设这是我的encryption和解密函数使用node.js的本机crypto

 var algo = 'aes-256-cbc'; var algoSecret = 'mySecret'; var encrypt = function(secret){ var cipher = require('crypto').createCipher(algo,algoSecret); var crypted = cipher.update(secret,'utf8','hex') crypted += cipher.final('hex'); return crypted; } var decrypt = function(text){ var decipher = require('crypto').createDecipher(algo,algoSecret); var dec = decipher.update(text,'hex','utf8'); dec += decipher.final('utf8'); return dec; } 

我必须encryption长度为20的数据。然而,前8个字符总是相同的,每个人都知道。 例如:始终以api-key=开头。 包含或删除8个首字符是否会影响系统的安全性?

例如: encrypt('api-key=askjdhaskdhaskd') 'api-key=' + encrypt('askjdhaskdhaskd')

包含或删除8个首字符是否会影响系统的安全性?

是的,但只是稍微。

具有静态IV的CBC模式是确定性的,这意味着仅观察密文的攻击者可以确定是否在之前发送了相同的明文前缀。 由于前8个字节已知是静态的,所以第一个块的接下来的8个字节的机会更可能等于另一个API密钥,其不一定完全匹配。 这个信息对攻击者是否有用是一个完全不同的问题。

总是为CBC模式生成一个不可预测的(读取:随机的)IV会更好,而不是依赖于从密码派生的相同的IV。 对于AES,无论密钥大小如何,IV总是16个字节或32个hex编码的字符。

一些示例代码:

 var crypto = require('crypto'); var algo = 'aes-256-cbc'; var algoSecret = 'mySecret'; var key = crypto.pbkdf2Sync(algoSecret, 'salt', 1000, 256, 'sha256'); // the key can also be stored in Hex in order to prevent PBKDF2 invocation var encrypt = function(secret){ var iv = crypto.randomBytes(16); var cipher = crypto.createCipheriv(algo, key, iv); var crypted = cipher.update(secret,'utf8','hex') crypted += cipher.final('hex'); return iv.toString('hex') + crypted; } var decrypt = function(text){ var iv = new Buffer(text.slice(0, 32), 'hex'); text = text.slice(32); var decipher = crypto.createDecipheriv(algo, key, iv); var dec = decipher.update(text,'hex','utf8'); dec += decipher.final('utf8'); return dec; } 

这还不够 ,因为这个代码可能容易受到填充oracle攻击的影响,这取决于你的通信架构。 您应该使用消息authentication码(MAC)来authentication密文。 HMAC-SHA256是“encryption – 然后MAC”的stream行select。

 var crypto = require('crypto'); var algo = 'aes-256-cbc'; var algoSecret = 'mySecret'; var key = crypto.pbkdf2Sync(algoSecret, 'salt', 1000, 512, 'sha512'); var keyMac = key.slice(32); var keyEnc = key.slice(0, 32); var encrypt = function(secret){ var iv = crypto.randomBytes(16); var cipher = crypto.createCipheriv(algo, keyEnc, iv); var crypted = cipher.update(secret,'utf8','hex') crypted += cipher.final('hex'); var ct = iv.toString('hex') + crypted; var hmac = crypto.createHmac('sha256', keyMac); hmac.update(ct); return ct + hmac.digest('hex'); } var decrypt = function(text){ var hmac = crypto.createHmac('sha256', keyMac); hmac.update(text.slice(0, -64)); if (hmac.digest('hex') !== text.slice(-64)) { // TODO: contant-time comparison // TODO: do some decoy decryption return false; } var iv = new Buffer(text.slice(0, 32), 'hex'); text = text.slice(32, -64); var decipher = crypto.createDecipheriv(algo, keyEnc, iv); var dec = decipher.update(text,'hex','utf8'); dec += decipher.final('utf8'); return dec; }