RSA 密钥和操作
键
硬件 JCE 实现 (IBMJCECCA) 扩展了软件 JCE 实现中可用的 RSA 密钥。 在软件 JCE 实现中,实际 RSA 密钥材料存储在密钥对象中。 IBMJCECCA 实现通过添加以下替代表示来扩展此功能:
先前存储在 CCA 密钥存储区中的 RSA 密钥对。 密钥对象包含密钥的 CCA 密钥存储区标签。
以下示例说明如何为已使用标签 "MYRSA.KEYPAIR" ,然后删除 CCA 密钥存储区条目。// create key objects for an existing CCA key storage area entry // (No checking is done to verify that the entry exists.) // KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA", "IBMJCECCA"); KeyLabelKeySpec spec = new KeyLabelKeySpec("MYRSA.KEYPAIR"); PublicKey pubKey = rsaKeyFactory.generatePublic(spec); PrivateKey privKey = rsaKeyFactory.generatePrivate(spec); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
由对底层硬件的 IBMJCECCA 调用生成的 RSA 密钥对,然后存储在 CCA 密钥存储区中。 密钥对象包含密钥的 CCA 密钥存储区标签。
以下示例说明生成 RSA 密钥对,该密钥对使用自动生成的标签存储在 CCA 密钥存储区中,并创建包含 CCA 密钥存储区条目标签的密钥对象。
以下示例说明如何生成存储在标签为 "ANRSA.KEYPAIR" 并创建包含 CCA 密钥存储区条目标签的密钥对象。// create a new CCA key storage area entry and key objects to represent it. // AlgorithmParameterSpec spec = new RSAKeyParameterSpec(1024, KeyHWAttributeValues.PKDS, KeyHWAttributeValues.KEYMANAGEMENT); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "IBMJCECCA"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); PublicKey pubKey = keyPair.getPublic(); PrivateKey privKey = keyPair.getPrivate(); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
// create a new CCA key storage area entry and key objects to represent it // AlgorithmParameterSpec spec = new RSAKeyParameterSpec(1024, KeyHWAttributeValues.PKDS, KeyHWAttributeValues.KEYMANAGEMENT, "ANRSA.KEYPAIR"); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "IBMJCECCA"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); PublicKey pubKey = keyPair.getPublic(); PrivateKey privKey = keyPair.getPrivate(); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
操作
RSA 加密和解密通过使用硬件密码术在 IBMJCECCA 提供程序中提供。 由于 RSA 算法是计算密集型算法,因此使用硬件密码术比软件密码术提供了显着的性能改进。 使用硬件执行 RSA 加密和解密还允许使用更安全的方法在 CCA 密钥存储器中存储密钥对。 使用存储在 CCA 密钥存储器中的密钥对,敏感专用密钥永远不会在明文中可用。
在 JCE 提供程序 (例如 OpenJCEPlus) 的软件实现中,使用 PKCS 1 type 2 填充来实现 RSA 加密和解密。 使用 PKCS 1 type 2 填充的 RSA 加密和解密也在硬件密码术中实现,并且可用于 IBMJCECCA 提供程序。
但是,硬件施加了两个限制:
- 所需密钥对的类型。 RSA 的硬件实现要求生成用于加密和解密数据的密钥,以便使用 KEYMANAGEMENT 密钥。 此限制意味着生成 RSA 密钥对时,必须将密钥使用情况设置为 KEYMANAGEMENT。
- 可以加密或解密的数据的最大长度。 RSA 的硬件实现将要加密或解密的数据量限制为 245 字节或小于密钥的模数大小 (以字节计) 的 11 字节 (以较小者为准)。
IBMJCECCA 提供程序还通过 零填充
实现 RSA 加密和解密。 并非所有 JCE 提供程序都支持此填充方案。 缺省填充方案是针对 IBMJCECCA 提供程序的 PKCS 1 type 2 填充。
零填充创建 RSA 密码实例:
Cipher myCipher = Cipher.getInstance("RSA/ /ZeroPadding", "IBMJCECCA");
PKCS 1 类型 2 padding的 RSA 密码实例:
Cipher myCipher = Cipher.getInstance("RSA/ /PKCS1Padding", "IBMJCECCA");
Cipher myCipher = Cipher.getInstance("RSA", "IBMJCECCA"); // accept the default padding
- 包含明确的 AES , DES 或三重 DES 密钥的密钥对象
- 包含加密 AES , DES DATA 或三重 DES DATA 密钥的 CCA 密钥存储区标签的密钥对象
- 包含具有加密 AES , DES DATA 或三重 DES DATA 密钥的硬件令牌的密钥对象
IBMJCECCA 提供程序支持对从另一主机导入的对称密钥进行 RSA 解包。 缺省情况下,生成的 (解包的) 密钥对象包含一个清除密钥。
如果创建 CCAAlgorithmParameterSpec 对象时未指定类型,或指定了类型 CCAAlgorithmParameterSpec.SECURE_INTERNAL_TOKEN ,并且使用此 CCAAlgorithmParameterSpec 对象初始化 RSA 密码,那么生成的 (解包的) 密钥对象包含硬件令牌。 此令牌包含使用主机主密钥加密的密钥。 如果创建了类型为 CAAlgorithmParameterSpec.CKDS的 CCAAlgorithmParameterSpec 对象,并且使用此 CCAAlgorithmParameterSpec 对象初始化了 RSA 密码,那么生成的 (解包的) 密钥对象将包含包含硬件令牌的 CCA 密钥存储区条目的标签。 此令牌包含使用主机主密钥加密的密钥。
// Generate a clear triple DES key
//
KeyGenerator keyGen =
KeyGenerator.getInstance("DESede", "IBMJCECCA");
Key tdesKey = keyGen.generateKey();
// Generate an RSA key pair
//
KeyPairGenerator rsaKeyPairGen =
KeyPairGenerator.getInstance("RSA","IBMJCECCA");
rsaKeyPairGen.initialize(1024);
KeyPair rsaKeyPair = rsaKeyPairGen.generateKeyPair();
PublicKey rsaPub = rsaKeyPair.getPublic();
PrivateKey rsaPriv = rsaKeyPair.getPrivate();
// Wrap the triple DES key as for export
//
Cipher rsaCipher = Cipher.getInstance("RSA","IBMJCECCA");
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,
(AlgorithmParameters)null, null);
byte[] wrappedKey = rsaCipher.wrap(tdesKey);
// Unwrap the triple DES key as for import
// Unwrap to a clear key
//
Key unwrappedDesKey =
rsaCipher.unwrap(wrappedKey, "DESede", Cipher.SECRET_KEY);
// Generate a secure triple DES hardware key
//
CCAAlgorithmParameterSpec ccaAlgParmSpec =
new CCAAlgorithmParameterSpec();
KeyGenerator keyGen =
KeyGenerator.getInstance("DESede", "IBMJCECCA");
keyGen.init(ccaAlgParmSpec, null);
Key tdesKey = keyGen.generateKey();
// Generate an RSA key pair
//
KeyPairGenerator rsaKeyPairGen =
KeyPairGenerator.getInstance("RSA","IBMJCECCA");
rsaKeyPairGen.initialize(1024);
KeyPair rsaKeyPair = rsaKeyPairGen.generateKeyPair();
PublicKey rsaPub = rsaKeyPair.getPublic();
PrivateKey rsaPriv = rsaKeyPair.getPrivate();
// Wrap the triple DES hardware key as for export
//
Cipher rsaCipher = Cipher.getInstance("RSA","IBMJCECCA");
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,
(AlgorithmParameters)null, null);
byte[] wrappedKey = rsaCipher.wrap(tdesKey);
// Unwrap the triple DES key as for import
// Unwrap to a secure hardware key
//
CCAAlgorithmParameterSpec ccaAlgParmSpec_forUnwrap =
new CCAAlgorithmParameterSpec();
rsaCipher.init(Cipher.UNWRAP_MODE, rsaPriv,
ccaAlgParmSpec_forUnwrap, null);
Key unwrappedDesKey =
rsaCipher.unwrap(wrappedKey, "DESede", Cipher.SECRET_KEY);
// Get the key store instance, open an input stream to the
// keystore file and load the key store.
//
KeyStore jceccaks = KeyStore.getInstance("JCECCAKS", "IBMJCECCA");
InputStream istream = new FileInputStream("keyStore.cca");
jceccaks.load(istream, "keystorePW".toCharArray());
// Given the alias for the CCA key storage area key entry, retrieve the private
// hardware key from the key store.
//
PrivateKey privateKey = (PrivateKey) jceccaks.getKey("MYRSAKEY", "myrsakeyPW".toCharArray());
// Delete the RSA hardware CCA key storage area key entry.
//
((RSAPrivateHWKey)privateKey).deletePKDSEntry();
// Delete the RSA key store object.
//
jceccaks.deleteEntry("MYRSAKEY");
// Write the modified key store contents to the key store file.
//
OutputStream ostream = new FileOutputStream("keyStore.cca");
jceccaks.store(ostream, "keystorePW".toCharArray());
与 OpenJCEPlus, 一样,IBMJCECCA提供程序使用OAEP(最优非对称加密填充)实现RSA的包装和解包。 IBMJCECCA 支持与软件 JCE 实现支持在以下方面有所不同:
带有 OAEP 的 IBMJCECCA RSA 包装支持 SHA-1, SHA-224, SHA-256, SHA-384和 SHA-512 填充算法。
具有 SHA-512 填充的 OAEP 需要 RSA 密钥大小 2048。
- 使用 OAEP 进行 IBMJCECCA RSA 打包只能用于打包 CCA 密钥存储区中的 SECURE_INTERNAL_TOKEN 密钥和加密密钥。
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-1", "IBMJCECCA");
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-256", "IBMJCECCA");
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
CCAAlgorithmParameterSpec ccaSpec = new CCAAlgorithmParameterSpec(CCAAlgorithmParameterSpec.SECURE_INTERNAL_TOKEN);
ccaSpec.setOAEPParameterSpec(oaepSpec);
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,ccaSpec, null);
byte[] wrappedKey = rsaCipher.wrap(desKey);
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
CCAAlgorithmParameterSpec ccaSpec = new CCAAlgorithmParameterSpec(CCAAlgorithmParameterSpec.CKDS);
ccaSpec.setOAEPParameterSpec(oaepSpec);
rsaCipher.init(Cipher.UNWRAP_MODE, rsaPriv, ccaSpec, null);
Key unwrappedKey = rsaCipher.unwrap(wrappedKey, "DES" Cipher.SECRET_KEY);
IBMJCECCA 提供程序中的 RSA 密码支持使用带有 OAEP 的 RSA 对 AES 传输密钥 (例如, AES 导出器和 AES IMPORTER 密钥) 进行打包和解包。 请注意, IBMJCECCA 传输键对象包含可能无法通过打包和解包操作持久存储的瞬态字段。 有关更多信息,请参阅 对称传输密钥 (密钥加密密钥)。
IBMJCECCA 提供程序中的 RSA 密码支持对 DES 和三重 DES 密钥进行打包和解包,但仅当它们是 DATA 密钥时才支持。