【Java】ハッシュで暗号化する

初めに

ハッシュについて

 * あるデータをハッシュ関数という特別な関数を使うと、決まった長さのビット列になる、この値を「ハッシュ値」という
 * ハッシュ値の別名として、「メッセージ・ダイジェスト (message digest) 」「フィンガープリント(指紋)」と呼ぶ場合もある
http://itpro.nikkeibp.co.jp/article/COLUMN/20060628/241960/

特徴

 * 異なるデータから同じハッシュ値が得られることはほとんどない
 * ハッシュ値ハッシュ関数が分かっていても,元データを算出できない
 => 改ざんされる恐れが減る

用途

 * ユーザー認証
 * デジタル署名(または電子署名)
etc...

注意

 * 以下のURLで言われているが、
http://www.javaroad.jp/bbs/answer.jsp?q_id=20060203152045485
「暗号化」と聞くと元に戻せる、つまり「複合化」できるイメージを抱いてしまうが、
ハッシュで暗号化すると、基本、元に戻せない
 => ハッシュ関数は、「不可逆的な一方向の関数」とも呼ばれる。
   「一方向」ってことは、元に戻せないってこと。

以下のサイトでは「ハッシュ」と「暗号化」の違いについて書いている。
http://blog.goo.ne.jp/xmldtp/e/b6a697735a597e8e41af460ae2f2875a
http://d.hatena.ne.jp/digisecdog/20101119/1290147066
このブログでは、以下のサイトであるとおり、
「暗号化」を「改ざんされたりされないよう、決まった規則に従ってデータを変換すること。」と定義し
タイトルを「ハッシュで暗号化」っとしている(ただ、混同しやすいので意識したほうがいい)
http://e-words.jp/w/E69A97E58FB7E58C96.html


サンプル

CipherHelper.java

* ハッシュ値取得クラス
import java.security.MessageDigest;

public class CipherHelper {

   public enum HashAlgorithm {
      MD2("MD2"),
      MD5("MD5"),
      SHA1("SHA-1"),
      SHA256("SHA-256"),
      SHA384("SHA-384"),
      SHA512("SHA-512");

      private String value;

      private HashAlgorithm(String value) {
         this.value = value;
      }

      public String toString() {
         return this.value;
      }
   }

   public static String getHash(String value, HashAlgorithm hashAlgorithm) {
      String returnValue = null;
      try {
         MessageDigest messageDigest = 
               MessageDigest.getInstance(hashAlgorithm.toString());
         messageDigest.update(value.getBytes());
         byte[] hashValues = messageDigest.digest();
         returnValue = DatatypeConverter.printHexBinary(hashValues);
      } catch (Exception ex) {
         ex.printStackTrace();
      }
      return returnValue;
   }
}

Main.java

* 使う側
public class Main {
   public static void main(String[] args) {
      try {
         String targetValue = "Hellow World!!";

        System.out.println("Length : 123456789|123456789|123456789|123456789|123456789+123456789|123456789|123456789|123456789|123456789+123456789|123456789|123456789|123456789|123456789+");
        String hashByMD2 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.MD2);
        System.out.println("MD2    : " + hashByMD2);
        
        String hashByMD5 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.MD5);
        System.out.println("MD5    : " + hashByMD5);
        
        String hashBySHA1 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.SHA1);
        System.out.println("SHA1   : " + hashBySHA1);
        
        String hashBySHA256 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.SHA256);
        System.out.println("SHA256 : " + hashBySHA256);
        
        String hashBySHA384 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.SHA384);
        System.out.println("SHA384 : " + hashBySHA384);
        
        String hashBySHA512 = 
              CipherHelper.getHash(targetValue, HashAlgorithm.SHA512);
        System.out.println("SHA512 : " + hashBySHA512);
         
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

出力結果

* 複雑なアルゴリズムになればなるほど、文字列が長くなる?
Length : 123456789|123456789|123456789|123456789|123456789+123456789|123456789|123456789|123456789|123456789+123456789|123456789|123456789|123456789|123456789+
MD2    : 752a4aa38b4f6d6401a7658890deba62
MD5    : 22a9f348cff599ff7c2a5caa8f4782fd
SHA1   : 94bcd8d0e86d4d6f0517c9e80c82b47dc6fe3707
SHA256 : baa04877dbe56a3941a46869982bb67e641bff08dcb7dbf7a7734421a2ecd3c9
SHA384 : 8c42ffdaa91d995a2214d7a22579c8b4c5b3b38968dc8fb4bfd80cbd8a8f1c342a27c1d86f93d1226c52e06219c4b2f3
SHA512 : a02eb48856dfc85e3875ab19c7f5b3c3e5f38f12fc480e5e7352e77bf96655fa48667d374f6c6caeee34cfece55bc4bad944c9e2d9fdd0d88f90b2955e022bb0

補足 : DatatypeConverter.printHexBinary()について

 * 以下の関連記事を参照のこと
http://blogs.yahoo.co.jp/dk521123/36555383.html


関連記事

Java で、シリアル番号生成を考える

http://blogs.yahoo.co.jp/dk521123/36538970.html

Java】 byte配列⇔16進数文字列 の変換

http://blogs.yahoo.co.jp/dk521123/36555383.html