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

■ はじめに

Java の ハッシュについて、メモ。

目次

【1】ハッシュ
 1)特徴
 2)用途
 3)使用上の注意
【2】MessageDigest・API仕様
【3】サンプル

【1】ハッシュ

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

## 1)特徴
## 2)用途
  • ユーザー認証
  • デジタル署名(または電子署名) etc...
## 3)使用上の注意
  • 以下の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  

# 【2】MessageDigest・API仕様
** API仕様 **  
http://docs.oracle.com/javase/jp/7/api/java/security/MessageDigest.html  
** アルゴリズム種類 **  
http://docs.oracle.com/javase/jp/7/technotes/guides/security/StandardNames.html#MessageDigest  

# 【3】サンプル
** 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

# 参考文献
http://itmemo.net-luck.com/java-messagedigest-hash/  
http://www.websec-room.com/2013/02/27/238