Cryptography 如何使用javacardx.security.derivation定义的KDF(X9.63)提取加密和MAC密钥

Cryptography 如何使用javacardx.security.derivation定义的KDF(X9.63)提取加密和MAC密钥,cryptography,javacard,Cryptography,Javacard,根据Java Card v3.1,新包定义为javacardx.security.derivation KDFX9.63使用三种输入:输入秘密、计数器和共享信息。 根据生成的密钥材料的长度,对哈希执行多轮操作以生成最终输出 我通过JCAPI使用此KDF生成了64字节的输出(由2轮SHA-256执行),用于16字节加密密钥、16字节IV和32字节MAC密钥 注意:这只是一段伪代码,用于将我的问题与必要的细节结合起来 DerivationFunction df = DerivationFuncti

根据Java Card v3.1,新包定义为javacardx.security.derivation

KDFX9.63使用三种输入:输入秘密、计数器和共享信息。 根据生成的密钥材料的长度,对哈希执行多轮操作以生成最终输出

我通过JCAPI使用此KDF生成了64字节的输出(由2轮SHA-256执行),用于16字节加密密钥、16字节IV和32字节MAC密钥

注意:这只是一段伪代码,用于将我的问题与必要的细节结合起来

DerivationFunction df = DerivationFunction.getInstance(DerivationFunction.ALG_KDF_ANSI_X9_63, false);
df.init(KDFAnsiX963Spec(MessageDigest.ALG_SHA_256, input, sharedInfo, (short) 64);

SecretKey encKey = KeyBuilder.buildKey(KeyBuilder.TYPE_AES, (short)16, false);
SecretKey macKey = KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short)32, false);

df.nextBytes(encKey); 
df.nextBytes(IVBuffer, (short)0, (short)16);
df.lastBytes(macKey);
我有以下问题:

  • 何时执行KDF轮次?这些是在df.init()期间还是在df.nextBytes()期间执行的

  • 一轮KDF将生成32字节的输出(考虑SHA-256算法),那么API的
    df.nextBytes()
    &
    df.lastBytes()
    将如何处理任何预期长度<32字节的输出

  • 在这个KDF中,计数器在下一轮中递增,那么如何在
    df.nextBytes()
    df.lastBytes()之间管理计数器

  • 何时执行KDF轮次?这些是在df.init()期间还是在df.nextBytes()期间执行的
  • 这似乎是我所特有的。一次执行所有计算可能会更快,但在这种情况下,等待字节的第一个请求仍然是有意义的。另一方面,RAM也常常是一个问题,因此随需应变生成也有一定的意义。不过,这需要一个更复杂的实现

    输出大小预先指定的事实可能表明,API设计人员至少可以预见一次生成所有关键材料的更简单方法(他们可能在JCF中接受同行评审之前创建了一个实现)

  • 一轮KDF将生成32字节的输出(考虑SHA-256算法),那么API的
    df.nextBytes()
    &
    df.lastBytes()
    将如何处理任何预期长度<32字节的输出
  • 它通常会返回(散列输出)最左边的字节,并可能将其余字节留在缓冲区中。当调用
    lastBytes
    时,此缓冲区可能会与状态的其余部分一起被销毁(因此不要忘记这样做)

    请注意,API明确指出,如果要再次使用
    派生函数
    实例,必须重新初始化该实例。因此,这是一个非常强烈的迹象,表明他们对关键材料的销毁(这是FIPS和通用标准认证所要求的,而不仅仅是常识)

    其他KDF可能有不同的返回字节的方式,但使用最左边的字节,然后在右边添加轮数是非常常见的,您可以称之为通用。对于ANSI X9.63 KDF来说,情况确实如此,并且在标准中明确规定了这种方式

  • 在这个KDF中,计数器在下一轮中递增,那么如何在
    df.nextBytes()
    df.lastBytes()之间管理计数器

  • 这些是同一类的方法,不能单独查看,因此它们不是单独的API。类实例可以以任何方式保持状态。它可能只是将计数器作为类变量保存,但是如果它决定在
    init
    或第一次
    nextBytes
    /
    lastBytes
    调用期间生成字节,那么计数器就不再是必需的了。

    嗨,Maarten Bodewes,我真的受到了你的启发。你在stack overflow论坛上的详细回答非常出色,这对其他人很有帮助。请接受我的问候。欢迎:)我感谢Oracle按照我的要求发布了API,并为此发布了一个干净的类。