我正在寻找一个安全的密钥多样化功能,为本地智能卡部署创建单独的AES密钥。这些密钥需要从一个秘密的主密钥和智能卡序列号中导出。密钥计算可以在主机系统上进行。
使用PBKDF2(password=master_key, salt=serial_number, rounds=1000, dkLen=16)获取单个密钥是安全和实用的,还是像AES(key=master_key, data=serial_number)这样更简单的方案就足够了?
编辑:master_key将仅用于此目的,至少有128位随机数据来自适当的RNG。我想知道的一个问题是:通常,盐也是一个高熵值。如果序列号不是高熵(但仍然是唯一的),这个方案会变得脆弱吗?
发布于 2013-02-12 00:35:32
如果您希望以键作为输入,则最好使用基于密钥的密钥派生函数(KBKDF),而不是基于密码的密钥派生函数(PBKDF)。不同之处在于KBKDF需要一个高熵的密钥。这也意味着它不需要salt或迭代计数。但是,它需要为每个派生键提供特定于上下文的数据。在您的情况下,当然包括序列号的编码。它还可能包括特定密钥的某种ID或标签,例如加密密钥的ASCII "ENC“和身份验证密钥的"MAC”。
如果您正在寻找密钥派生函数,最好使用NIST SP 800-108或香港发展基金。NIST SP 800-108定义了整个KBKDF的范围。不幸的是,它没有提供任何类型的推荐或默认。
正如fgrieu所指出的,对于智能卡上的散列函数,可能无法实现针对侧通道攻击的对策。因此,最好在PRF的CMAC模式中使用AES来选择计数器模式KBKDF。这是in 800-108文档中描述的第一种模式。
如果您习惯于使用二进制数据,则KBKDF和CMAC都相对容易实现。我刚刚实现了所有的KBKDF,在800-108和HKDF的Bouncy城堡框架(Java),所以他们都在那里,以防你需要一个参考实现(当然,根据官方测试向量测试)。
发布于 2013-02-11 20:19:32
为了实现密钥多样化(也就是说,为每个设备分配一个唯一的密钥),一个真正的master_key是习惯的;也就是说,一个具有大量熵(比如128位或更多的随机位)。编辑:现在问题中已经说明了这一点。
有了这个警告,是的,PBKDF2(password=master_key, salt=serial_number, rounds=1000, dkLen=16)**适合生成一个128位的键;它甚至是过分的,特别是作为参数化的:rounds可以是1,因为rounds的唯一目的是扩展password输入,如果输入是真正的键,则不需要这样做。减少rounds将加快生产速度,并由主服务器使用,没有加密缺陷。
是的,AES(key=master_key, data=serial_number)是合适的,而且是平常的。作为一种好处,这允许公正地声明:每一张卡都有一个不同的密钥,它有一个(微小的,不可利用的)机会不与PBKDF2保持。
编辑:为了拥有强大的多样化密钥,salt (通常是序列号)不需要高熵。这是足够的,它是不同的设备之间的另一个在不损害现有设备的盐类/序列号列表的情况下,在资源暂时受损的情况下出现了一个缺点:如果序列号是顺序的,则可以计算所有设备的各种密钥;PBKDF2与rounds=1000,或任何缓慢的KDF,都不是减轻风险的适当方法;延迟要好得多。。
另外,问自己一个问题:设备上的侧通道攻击 (S)有可能实现多样化吗?如果是的话,从实现的角度来看,基于散列的PBKDF2真的合适吗?我还没有看到针对DPA的哈希实现进行评估,这与AES实现相反,在这种实现中,DPA攻击的风险至少会被评估。
边注:如果需要键拉伸(它不是),rounds=1000在PBKDF2中显然是过时的;这是12年前建议的最低限度,而IMHO即使在那个时候也是不够的。摩尔定律和朋友们(以GPU和FPGA加速器的民主化形式)使得至少需要使用rounds=100000来实现同等的安全性。此外,PBKDF2作为一个关键担架已经过时了,除非您有硬件加速的散列,而且肯定没有内存;氪石是最新的技术。
https://crypto.stackexchange.com/questions/6319
复制相似问题