1概要

簡単に言うと、暗号化とは、許可されたユーザーだけが理解またはアクセスできるようにメッセージをエンコードするプロセスです。

プレーンテキストと呼ばれるメッセージ


は、暗号化アルゴリズム、つまり暗号を生成する暗号文を使用して暗号化されます。

この記事では、暗号化と復号化の機能をJavaで提供するコア

Cipher

クラスについて詳しく説明します。


2暗号クラス

Java Cryptography Extension(JCE)は、Java Cryptography Architecture(JCA)** の一部で、アプリケーションにデータの暗号化と復号化、および個人データのハッシュ化のための暗号化暗号を提供します。



Cipher


クラス(

javax.crypto

パッケージ内にあります)はJCEフレームワークの中核を形成し、機能を提供します暗号化と復号化のために。


2.1. 暗号化インスタンス化


Cipher

オブジェクトをインスタンス化するには、静的な

getInstance

メソッドを呼び出し、要求された変換の名前を渡します。必要に応じて、プロバイダの名前を指定できます。


Cipher

のインスタンス化を示すクラスの例を書きましょう。

public class Encryptor {

    public byte[]encryptMessage(byte[]message, byte[]keyBytes)
      throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
       //...
    }
}

変換

AES/ECB/PKCS5Padding

は、

Cipher

オブジェクトをECB付きhttps://en.wikipedia.org/wiki/Advanced

Encryption

Standard[AES]暗号としてインスタンス化するように

getInstance

メソッドに指示します[操作モード]とPKCS5

padding scheme

変換でアルゴリズムのみを指定して、

Cipher

オブジェクトをインスタンス化することもできます。

Cipher cipher = Cipher.getInstance("AES");

この場合、モードとパディング方式のプロバイダ固有のデフォルト値が使用されます。

変換が

null

、空、無効な形式の場合、または指定された暗号化アルゴリズムの実装が指定されたプロバイダから利用できない場合は、

NoSuchAlgorithmException

がスローされます。

変換に使用できないパディングスキームが含まれている場合、

NoSuchPaddingException

がスローされます。


2.2. キー



Key


インタフェースは、暗号化操作の鍵を表します。キーは、エンコードされたキー、キーのエンコード形式、およびその暗号化アルゴリズムを保持する不透明なコンテナです。

鍵は通常https://docs.oracle.com/javase/7/docs/api/javax/crypto/KeyGenerator.html[鍵生成プログラム]、証明書、またはhttps://docs.oracle.com/javase/から取得されます。 7/docs/api/java/security/spec/KeySpec.html[キー仕様]

キーファクトリ

を使用して。

与えられたキーバイトから対称的な

Key

を作りましょう:

SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");


2.3. 暗号初期化



  • Key


    またはhttps://を使用して、

    init()

    メソッドを呼び出してC


    _ipher


    オブジェクトを初期化します。 docs.oracle.com/javase/9​​/docs/api/java/security/cert/Certificate.html[

    Certificate

    ]および暗号の動作モードを示す

    opmode_

オプションとして、

乱数の発生源を渡すことができます

。デフォルトでは、最も優先順位の高いインストール済みプロバイダーのhttps://docs.oracle.com/javase/9​​/docs/api/java/security/SecureRandom.html[

SecureRandom

]実装が使用されます。何も見つからない場合は、システム提供のソースが使用されます。

  • アルゴリズム固有のパラメータのセットをオプションで指定できます。]

    初期化ベクトル

    を指定します。

利用可能な暗号操作モードは次のとおりです。


  • ENCRYPT

    MODE

    :

    cipher__オブジェクトを暗号化モードに初期化


  • DECRYPT

    MODE

    :

    cipher__オブジェクトを復号化モードに初期化する


  • WRAP

    MODE

    :

    cipher__オブジェクトを


http://en.wikipedia.org/wiki/Key


Wrap[key-wrapping]モード
**

UNWRAP

MODE

:

cipher

オブジェクトを


Cipher

オブジェクトを初期化しましょう。

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
cipher.init(Cipher.ENCRYPT__MODE, secretKey);//...

キーの長さやエンコードが無効な場合のように、指定されたキーが暗号の初期化に不適切な場合は、

InvalidKeyException

がスローされます。

暗号で鍵から特定できない特定のアルゴリズムパラメータが必要な場合、または鍵の鍵サイズが最大許容鍵サイズ(https://docs.oracle.com/javase/9​​から決定)を超える場合もスローされます。/security/java-cryptography-architecture-jca-reference-guide.htm#JSSEC-GUID-EFA5AC2D-644E-4CD9-8523-C6D3936D5FB1[設定済みのJCE管轄]ポリシーファイル)。


Certificate

を使用した例を見てみましょう。

public byte[]encryptMessage(byte[]message, Certificate certificate)
  throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT__MODE, certificate);
   //...
}


Cipher

オブジェクトは、

getPublicKey

メソッドを呼び出すことによって、証明書からデータ暗号化のための公開鍵を取得します。


2.4. 暗号化と復号化


Cipher

オブジェクトを初期化した後、

doFinal()

メソッドを呼び出して暗号化または復号化操作を実行します。このメソッドは、暗号化または復号化されたメッセージを含むバイト配列を返します。


doFinal()

メソッドはまた、

Cipher

オブジェクトを、

init()

メソッドの呼び出しによって以前に初期化されたときの状態にリセットし、

Cipher

オブジェクトを追加のメッセージの暗号化または復号化に使用できるようにします。


encryptMessage

メソッドで

doFinal

を呼び出しましょう。

public byte[]encryptMessage(byte[]message, byte[]keyBytes)
  throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException,
    BadPaddingException, IllegalBlockSizeException {

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
    cipher.init(Cipher.ENCRYPT__MODE, secretKey);
    return cipher.doFinal(message);
}

復号化操作を実行するには、

opmode



DECRYPT

MODE__に変更します。

public byte[]decryptMessage(byte[]encryptedMessage, byte[]keyBytes)
  throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
    BadPaddingException, IllegalBlockSizeException {

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
    cipher.init(Cipher.DECRYPT__MODE, secretKey);
    return cipher.doFinal(encryptedMessage);
}


2.5. プロバイダ


プロバイダベースのアーキテクチャ

を使用するように設計されているため、** JCEはhttps://www.bouncycastle.org/[BouncyCastle]などの修飾された暗号ライブラリをプラグインすることを可能にします。セキュリティプロバイダとして、および新しいアルゴリズムがシームレスに追加される予定です。

それでは、BouncyCastleをセキュリティプロバイダとして追加しましょう。セキュリティプロバイダを静的または動的に追加できます。

  • BouncyCastleを静的に追加するには、

    <JAVA

    HOME>/jre/lib/security

    フォルダにある

    java.security__ファイルを変更します。

リストの最後に行を追加します。

...
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider

プロバイダプロパティを追加する場合、プロパティキーは

security.provider.N

の形式になります。ここで、番号

N

はリストの最後の番号よりも1つ大きくなります。

  • セキュリティファイルを変更することなく、BouncyCastleセキュリティプロバイダを動的に追加することもできます。

Security.addProvider(new BouncyCastleProvider());

暗号の初期化中にプロバイダを指定できるようになりました。

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");


BC

は、BouncyCastleをプロバイダとして指定します。登録されているプロバイダの一覧は__Security.getProviders()メソッドで取得できます。


3暗号化と復号化のテスト

メッセージの暗号化と復号化を説明するためのテスト例を書きましょう。

このテストでは、128ビットキーを使用したAES暗号化アルゴリズムを使用して、復号化された結果が元のメッセージテキストと等しいと主張します。

@Test
public void whenIsEncryptedAndDecrypted__thenDecryptedEqualsOriginal()
  throws Exception {

    String encryptionKeyString =  "thisisa128bitkey";
    String originalMessage = "This is a secret message";
    byte[]encryptionKeyBytes = encryptionKeyString.getBytes();

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(encryptionKeyBytes, "AES");
    cipher.init(Cipher.ENCRYPT__MODE, secretKey);

    byte[]encryptedMessageBytes = cipher.doFinal(message.getBytes());

    cipher.init(Cipher.DECRYPT__MODE, secretKey);

    byte[]decryptedMessageBytes = cipher.doFinal(encryptedMessageBytes);
    assertThat(originalMessage).isEqualTo(new String(decryptedMessageBytes));
}


4結論

この記事では、

Cipher

クラスについて説明し、使用例を紹介しました。

Cipher

クラスとJCEフレームワークの詳細については、https://docs.oracle.com/javase/9​​/docs/api/javax/crypto/Cipher.html[class documentation]およびhttps://を参照してください。 docs.oracle.com/javase/9​​/security/java-cryptography-architecture-jca-reference-guide.htm[JCA暗号化アーキテクチャリファレンスガイド]。