Variousible ホーム Developers' Room トップ

共通鍵暗号化と復号

2005/ 8/ 7

Tiger で JCE (Java Cryptography Extension) を使って共通鍵暗号方式による暗号化と復号をします。 AES により暗号化・復号する方法です。

セキュリティに関する API の解説ですが、 作者はセキュリティの専門家ではありません。 本情報をもちいて発生したいかなる問題にも責任を負いかねますので、 あらかじめご了承ください。

暗号化

共通鍵はあらかじめ用意できているものとします。 共通鍵の生成 によって生成することもできます。

AES の暗号化モードの例を以下に示します。「アルゴリズム」 を Cipher インスタンスを取得する際に指定することができます。 (もちろん JCE プロバイダによって、他のものが使えるかもしれない。) IV は、暗号化の際に必要とする 128bit のパラメータです。 暗号化モード CBC では、この IV を必要とします。 もちろん復号の際にも暗号化の際に使用したのと同じ IV を必要とします。

アルゴリズム説明IV
AES/ECB/ISO10126Padding モード: ECB、パディング: ISO10126 (XML暗号化) 不要
AES/ECB/PKCS5Padding モード: ECB、パディング: PKCS #5 version 1.5 不要
AES/CBC/ISO10126Padding モード: CBC、パディング: ISO10126 (XML暗号化) 必要
AES/CBC/PKCS5Padding モード: CBC、パディング: PKCS #5 version 1.5 必要

以下に暗号化コードを示します。平文ファイルを暗号化し、 暗号化ファイルを出力します。なお、例外処理は一応入れてあるだけで、 説明の本質ではないため手抜きです。

AES 暗号化
public void encrypt(String inFile, String outFile) { Cipher cipher = null; try { cipher = Cipher.getInstance(MODE); System.out.println("Algorithm is " + cipher.getAlgorithm() ); cipher.init(Cipher.ENCRYPT_MODE, key); } catch (Exception e) { e.printStackTrace(); return; } BufferedInputStream in = null; BufferedOutputStream out = null; try { byte[] buf = new byte[512]; byte[] cbuf = new byte[512]; in = new BufferedInputStream(new FileInputStream(inFile) ); out = new BufferedOutputStream(new FileOutputStream(outFile) ); while (true) { int readBytes = in.read(buf); int encryptedBytes; if (readBytes < 0) { try { encryptedBytes = cipher.doFinal(cbuf, 0); out.write(cbuf, 0, encryptedBytes); // AlgorithmParameters algParams = cipher.getParameters(); System.out.println("Algorithm params: " + algParams); } catch (Exception e) { e.printStackTrace(); } break; } try { encryptedBytes = cipher.update(buf, 0, readBytes, cbuf, 0); out.write(cbuf, 0, encryptedBytes); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e2) { e2.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e2) { e2.printStackTrace(); } } } }

Cipher クラスは暗号化と復号を実現するクラスです (このほかに鍵のラッピングも可能)。 アルゴリズムを指定して getInstance() メソッドにより インスタンスを取得します。MODE に上記表のアルゴリズムのいずれかを指定します。

inFileoutFile はそれぞれ平文のファイル名と 暗号化後のデータを保存するファイル名です。また、key は共通鍵を保持する Key インスタンスです。

暗号化処理自体は、update() メソッドの呼び出しの繰り返しです。 平文を順次指定して update() を呼び出し、 最後に doFinal() メソッドを呼び出してすべての暗号文を得ます。

Cipher に対する getParameters() メソッドは、 暗号化の際に使用されたパラメータを取得しています。 AES を CBC モードで使用した場合、IV が取得できます。 このパラメータは復号時に必要となります。

復号

暗号化されたファイルを復号します。もちろん共通鍵は暗号化したときのものです。 また、モードとして CBC を使用した場合など、IV を必要とするモードでは、 暗号化のときと同じパラメータを復号の際にも使用しなくてはなりません。

符号化
public void decrypt(String inFile, String outFile) { Cipher cipher = null; try { cipher = Cipher.getInstance(MODE); System.out.println("Algorithm is " + cipher.getAlgorithm() ); cipher.init(Cipher.DECRYPT_MODE, key); } catch (Exception e) { e.printStackTrace(); return; } BufferedInputStream in = null; BufferedOutputStream out = null; try { byte[] buf = new byte[512]; byte[] cbuf = new byte[512]; in = new BufferedInputStream(new FileInputStream(inFile) ); out = new BufferedOutputStream(new FileOutputStream(outFile) ); while (true) { int readBytes = in.read(buf); int decryptedBytes; if (readBytes < 0) { try { decryptedBytes = cipher.doFinal(cbuf, 0); out.write(cbuf, 0, decryptedBytes); // AlgorithmParameters algParams = cipher.getParameters(); System.out.println("Algorithm params: " + algParams); } catch (Exception e) { e.printStackTrace(); } break; } try { decryptedBytes = cipher.update(buf, 0, readBytes, cbuf, 0); out.write(cbuf, 0, decryptedBytes); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e2) { e2.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e2) { e2.printStackTrace(); } } } }

基本的には暗号化時と同様の処理手順になります。 復号するので、初期化時に Cipher.DECRYPT_MODE を指定します。 また、暗号化の際にパラメータを使用した場合、上記のコードにはありませんが、 一緒に AlgorithmParameters を指定する必要があることに注意してください。

Variousible ホーム Developers' Room トップ
※Java およびすべての Java に関する標章は、米国およびその他の国における米国 Sun Microsystems, Inc. の商標または登録商標です。
※その他の登場する製品名は、各社の商標または登録商標です。
本サイトについて
Copyright © 2005 KURIHARA, Yusuke. All rights reserved.