ラッピングと暗号化は非常に似ていますが、ラッピングは何をしようとしているのかをより正確に表現します。一般的な「暗号化」は、セマンティックな意味を持たない生データを操作しますが、ラッピングはキーに関連することが知られています。したがって、このCipher.unwrap()
メソッドはKey
非バイト配列を返します。
キーのラッピングに wrap を使用すると、コードの移植性が向上します (特にハードウェア セキュリティ モジュールに関して)。状況によっては、キーのアクセス許可によってラッピング操作は許可されますが、キー バイトの生の暗号化は許可されません。
もちろん、JCE アーキテクチャ全体がプロバイダーの概念に基づいているため、目的の出力形式を取得するために、選択したプロバイダーに指定するアルゴリズムを正確に確認する必要があります。これは、ラップされた鍵データをサードパーティに送信する場合に特に重要です。
あなたの特定のケースでは、以下に示すように、 と の両方で同じ動作が示されWRAP
、ENCRYPT
結果を交換します。
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SunJSSE");
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
SecretKey sessionKey = new SecretKeySpec(new byte[16], "AES");
Cipher c = Cipher.getInstance("RSA", "SunJCE");
c.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] result1 = c.doFinal(sessionKey.getEncoded());
c.init(Cipher.WRAP_MODE, keyPair.getPublic());
byte[] result2 = c.wrap(sessionKey);
c.init(Cipher.UNWRAP_MODE, keyPair.getPrivate());
SecretKey sessionKey1 = (SecretKey) c.unwrap(result1, "AES",
Cipher.SECRET_KEY);
c.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
SecretKey sessionKey2 = new SecretKeySpec(c.doFinal(result2), "AES");
System.out.println(Arrays.equals(sessionKey1.getEncoded(),
sessionKey2.getEncoded()));
これは以下を出力します:true