JavaでSHA-1とか使って暗号化する
登録制のWebアプリケーションって、たぶんユーザーのパスワードを暗号化してDBに格納すると思うんですよ。そのためには、SHA-1みたいなアルゴリズムで暗号化するのが一般的(?)だと思うので、そのサンプルコードです。
main文の中に全部つっこんで書いた方が、ブログ閲覧者的には理解しやすいんだろうけど、実際はたぶんこうやって使うんだろなって思ってクラスにしてやった。
サンプルコード
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /* * いわゆるハッシュ関数を使った暗号化クラス。 */ public class Encryption { /* メッセージダイジェストアルゴリズム */ public MessageDigest md = null; /* * テストコード */ public static void main(String[] args) { final String algorithmName = "SHA-256"; final String password = "p12345"; Encryption e = new Encryption(algorithmName); byte[] bytes = e.toHashValue(password); String result = e.toEncryptedString(bytes); System.out.println(result); // 出力→ f63e7ba71de88a877e320318d0112356c381276dc6b6a58381726bef4bbc1481 } /* * 引数でメッセージダイジェストアルゴリズムを指定する。 * MD2, MD5, SHA, SHA-256, SHA-384, SHA-512が利用可能。 */ public Encryption(String algorithmName) { try { md = MessageDigest.getInstance(algorithmName); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /* * メッセージダイジェストアルゴリズムを使い、文字列をハッシュ値へ変換する。 */ public byte[] toHashValue(String password) { md.update(password.getBytes()); return md.digest(); } /* * バイト配列を16進数の文字列に変換し、連結して返す。 */ public String toEncryptedString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { String hex = String.format("%02x", b); sb.append(hex); } return sb.toString(); } }
ポイント
強いてあげるなら、String.format("%02x", b) のとこ。
C言語のprintf関数みたいな記述法は、プログラマの基本素養だと思ってますが、JavaではJDK1.5から利用可能になりました。JavaのAPIドキュメントではFormatterクラスの説明(API仕様リンク)を見ると良いです。
もしこれを使わない場合、Javaでダイジェストを生成する:JavaTips 〜Javaプログラミング編 - @ITみたいな負値の補正や0埋めするコードを書かなくちゃならないので、ちょっとだけ面倒ですね。
アルゴリズムはどれがいいの?
SHA-1って理論上はもう破られちゃうことがわかってるらしいですね。アメリカ政府でも2010年、つまり今年の年末からは新規案件でSHA-1を採用しないことに決まってるらしいです。
SHA-256やSHA-512っていう、もうちょっと強度のある第2世代のアルゴリズムがあって、しばらくはこれ使うことになるみたい。けど、これもやっぱり近い将来破られちゃうことがわかってる。コンピュータの進歩は凄まじいですからね。
実はいま絶賛コンペ中(リンク)で、第3世代(総称してSHA-3と呼ぶ)の実装を何にしようかっていう動きがあります。日本からは日立のLuffaというアルゴリズムが候補に残ってますね。
これが確定するのは2年後で、そっからはそれが世界標準となります(PDFリンク)。なので、当面はSHA-256使っとけばいいはずです。