web-dev-qa-db-ja.com

Javaでパスワードからキーを取得するときに、SecretKeySpecが必要なのはなぜですか?

JavaのSecretKeyクラスとSecretKeySpecクラスの違いは何ですか?

SecretKeySpecのドキュメントはこう言っています:

バイト配列からSecretKeyを構築するために使用できます

このコードでは、secretKey.getEncoded()またはsecret.getEncoded()を16進数で出力すると、どちらも同じ出力が得られます。では、なぜSecretKeySpecが必要なのでしょうか。

_final String password = "test";
int pswdIterations = 65536  ;
int keySize = 256;
byte[] ivBytes;
byte[] saltBytes = {0,1,2,3,4,5,6};

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

PBEKeySpec spec = new PBEKeySpec(
                    password.toCharArray(), 
                    saltBytes, 
                    pswdIterations, 
                    keySize
                    );

SecretKey secretKey = factory.generateSecret(spec);

SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(),"AES");
_

以下は、getEncoded()の両方の呼び出しの出力です。

_00367171843C185C043DDFB90AA97677F11D02B629DEAFC04F935419D832E697_

13
Riley Willow

すべてのSecretKeyには、関連付けられたアルゴリズム名があります。たとえば、AESキーが必要なコンテキストでは、アルゴリズム_"DES"_でSecretKeyを使用できません。

コードでは、次の行によってSecretKeyが生成されます。

_SecretKey secretKey = factory.generateSecret(spec);
_

ただし、この時点でのキーはnot AESキーです。 secretKey.getAlgorithm()を呼び出すと、結果は_"PBKDF2WithHmacSHA1"_になります。 Java=これが実際にはAESキーであることを伝える何らかの方法が必要です。

これを行う最も簡単な方法は、元のキーデータを使用し、アルゴリズム名を明示的に指定して、新しいSecretKeySpecオブジェクトを作成することです。

_SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(),"AES");
_

注:secretSecretKeyとして個人的に宣言します。これは、この後の具体的な実装について気にする必要がないためです。

17
Duncan Jones

SecretKeyは、プロバイダー固有の実装を必要とする単なるインターフェースです。 SecretKeySpecは、既存の鍵素材からSecretKeyを簡単に構築できる具象クラスです。したがって、SecretKeyを取得するには、適切なファクトリクラスまたはSecretKeySpecをショートカットとして使用する必要があります。

8

SecretKeyはインターフェースであり、SecretKeySpecSecretKeyの実装です

4
Buhake Sindi