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 密钥存储区条目标签的密钥对象。
    // 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.
    //
    以下示例说明如何生成存储在标签为 "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,
                                                          "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
IBMJCECCA 提供程序支持将对称密钥进行 RSA 打包以导出到另一个主机。 RSA 包装支持以下密钥:
  • 包含明确的 AES , DES 或三重 DES 密钥的密钥对象
  • 包含加密 AES , DES DATA 或三重 DES DATA 密钥的 CCA 密钥存储区标签的密钥对象
  • 包含具有加密 AES , DES DATA 或三重 DES DATA 密钥的硬件令牌的密钥对象

IBMJCECCA 提供程序支持对从另一主机导入的对称密钥进行 RSA 解包。 缺省情况下,生成的 (解包的) 密钥对象包含一个清除密钥。

如果创建 CCAAlgorithmParameterSpec 对象时未指定类型,或指定了类型 CCAAlgorithmParameterSpec.SECURE_INTERNAL_TOKEN ,并且使用此 CCAAlgorithmParameterSpec 对象初始化 RSA 密码,那么生成的 (解包的) 密钥对象包含硬件令牌。 此令牌包含使用主机主密钥加密的密钥。 如果创建了类型为 CAAlgorithmParameterSpec.CKDSCCAAlgorithmParameterSpec 对象,并且使用此 CCAAlgorithmParameterSpec 对象初始化了 RSA 密码,那么生成的 (解包的) 密钥对象将包含包含硬件令牌的 CCA 密钥存储区条目的标签。 此令牌包含使用主机主密钥加密的密钥。

以下示例说明如何生成包含明确密钥的三重 DES 密钥对象,将其打包,然后将其解包到包含明确密钥的三重 DES 密钥对象。
// 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);
以下示例说明如何生成包含硬件密钥令牌的三重 DES 密钥对象,将其打包,然后将其解包到包含硬件密钥令牌的三重 DES 密钥对象。
// 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);
      
以下示例说明了如何删除标签为 "MYRSAKEY" 的存储在 CCA 密钥存储区中的密钥的 RSA 硬件密钥对象。
// 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());
      
注: DSAPrivateHWKey 类还具有 deletePKDSEntry 方法。 您可以遵循先前的代码示例,通过将 DSAPrivateHWKey 类替换为 RSAPrivateHWKey 类来删除 DSA 专用硬件 CCA 密钥存储区密钥条目。

与 OpenJCEPlus, 一样,IBMJCECCA提供程序使用OAEP(最优非对称加密填充)实现RSA的包装和解包。 IBMJCECCA 支持与软件 JCE 实现支持在以下方面有所不同:

  • 11.0.21.0 的更改开始带有 OAEP 的 IBMJCECCA RSA 包装支持 SHA-1, SHA-224, SHA-256, SHA-384和 SHA-512 填充算法。11.0.21.0 更改结束
  • 11.0.21.0 的更改开始具有 SHA-512 填充的 OAEP 需要 RSA 密钥大小 2048。11.0.21.0 更改结束
  • 使用 OAEP 进行 IBMJCECCA RSA 打包只能用于打包 CCA 密钥存储区中的 SECURE_INTERNAL_TOKEN 密钥和加密密钥。
以下示例说明如何使用 OAEP SHA-1 和 OAEP SHA-256 填充算法创建 RSA 密码实例:
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-1", "IBMJCECCA");
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-256", "IBMJCECCA");
以下示例说明了如何使用 RSA 以及 OAEP 和 SHA-256 填充来包装 DES 密钥令牌:
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); 
以下示例说明了在使用具有 OAEP 和 SHA-256 填充的 RSA 对密钥进行打包时,如何将 DES 密钥解包到 CCA 密钥存储区中存储的加密密钥:
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 密钥时才支持。