在Java加密库中,密钥有两种不同的表示形式 - Key
和KeySpec
。文档暗示两者之间存在差异 - KeySpec
是"透明的"(无论这意味着什么),但没有方法,而Key
有一个getEncoded
方法。您打算使用KeyFactory
在两者之间进行转换(它确实有一种getKeySpec
的转换方法)。
但是,SecretKeySpec
实现了Key
和KeySpec
!但是还有一个SecretKeyFactory
类,它不会继承KeyFactory
。
这一切让我彻底迷茫了。Key
和KeySpec
有什么区别,SecretKeySpec
和SecretKeyFactory
是如何进入的?
这里的透明意味着所有实现/扩展KeySpec
接口的类/接口都应该以独立于提供程序的方式揭示有关密钥的元数据。此元数据实际上从未用于密钥的常见用途(加密等),而是仅在需要查看密钥的数学属性时使用。了解有关密钥的此类提供程序独立数据可能很有用,例如,如果要从字节流生成密钥/到字节流生成密钥,如果密钥驻留在 HSM 上,则挂钩密钥,甚至找出密钥是否弱,例如:
DESKeySpec.isWeak(byte[] key, int offset)
您想要公开有关密钥的任何元数据都由您决定。 KeySpec
仅充当标记接口(标记接口设计模式)。
与这种可能的KeySpec
自省相反,使用SecretKeyFactory
生成的密钥是"不透明的",从某种意义上说,您无法获得有关密钥的完整数学(模数,指数,编码等)和其他(如果像上面DESKeySpec
提供)元数据。
另一方面,SecretKeySpec
是 JCE 的开箱即用解决方案,用于从字节流生成密钥,因此它实现了 Key
和 KeySpec
- 使用提供的KeySpec
生成密钥,并使用 Key.getEncoded()
使密钥可用。
密钥对象和密钥规范 (KeySpecs) 是密钥数据的两种不同表示形式。
密码使用 Key 对象来初始化其加密算法,但可能需要将密钥转换为更便携的格式以进行传输或存储。
键的透明表示意味着您可以通过相应规范类中定义的 get 方法之一单独访问每个键材料值。
For example, DSAPrivateKeySpec defines getX, getP, getQ, and getG methods, to access the private key x, and the DSA algorithm parameters used to calculate the key(the prime p, the sub-prime q, and the base g).
如果密钥存储在硬件设备上,则其规范可能包含有助于识别设备上的密钥的信息。此表示形式与 Key 接口定义的不透明表示形式形成对比,在该表示形式中,您无法直接访问关键材料字段。换句话说,"不透明"表示形式为您提供了对键的有限访问权限 - 只有由Key接口定义的三种方法:getAlgorithm,getFormat和getEncoded。
密钥可以以特定于算法的方式指定,也可以以与算法无关的编码格式(如 ASN.1)指定。
For example, a DSA private key may be specified by its components x, p, q, and g (eg: DSAPrivateKeySpec), or it may be specified using its DER encoding (eg: PKCS8EncodedKeySpec).
KeyFactory 和 SecretKeyFactory 类可用于在不透明和透明键表示形式之间进行转换,即在 Keys 和 KeySpecs 之间进行转换。
参考和更多详细信息,请访问:https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#KeySpecs