JavaはMD 5の暗号化と復号化を実現する

10643 ワード

MD 5の紹介
        本質的にMD 5は暗号化アルゴリズムではなく、そのフルネームはMessage Digest Algorithm MD 5(中国語名:情報要約アルゴリズム第5版)であり、コンピュータセキュリティ分野で広く使用されているハッシュ関数であり、主に情報伝送の完全な一致を確保するために用いられる.コンピュータで広く使われているコンパクトアルゴリズムの一つ(要約アルゴリズム、ハッシュアルゴリズム)であり、主流のプログラミング言語ではMD 5が一般的に実現されている.MD 5は、データ(例えば漢字)を別の固定長値に演算するコンパクトアルゴリズムの基礎原理であり、MD 5の前身にはMD 2、MD 3、MD 4がある.MD 5の役割は、大容量情報をデジタル署名ソフトウェアで秘密鍵に署名する前に「圧縮」されて秘密のフォーマットにすることである(任意の長さのバイト列を一定の長さの16進数列に変換することである).情報要約アルゴリズムはMD 5の他にsha−1,RIPEMD,Havalなどが有名である.
MD 5の応用
整合性の検証
MD 5の典型的な応用は、改ざんを防止するために、情報(Message)の要約(Message-Digest)を生成することである.たとえば、UNの下にはダウンロード時に同じファイル名を持つソフトウェアがたくさんあります.ファイル拡張子は.md 5のファイルです.このファイルには通常1行のテキストしかありません.大体の構造は次のようです. MD 5(tanajiya.tar.gz)=0 ca 175 b 9 c 0 f 726 a 831 d 895 e 269332461これがtanajiya.tar.gzファイルのデジタル署名です.MD 5はファイル全体を大きなテキスト情報とし,その不可逆的な文字列変換アルゴリズムにより,この一意のMD 5情報要約を生成した.読者の友达にMD 5の応用に対して直観的な認識を持つために、筆者は1つの例と1つの例でその仕事の過程を簡単に説明します:みんなはすべて知っていて、地球上のいかなる人はすべて自分の唯一無二の指紋を持っていて、これはいつも公安機関が犯罪者の身分を鑑別する最も信頼できる方法になります;これと同様に、MD 5は、サイズ、フォーマット、数にかかわらず、任意のファイルに対して同じユニークな「デジタル指紋」を生成することができ、誰がファイルを変更した場合、そのMD 5値、すなわち対応する「デジタル指紋」が変化します.私たちはよくいくつかのソフトウェアダウンロードサイトのあるソフトウェア情報の中でそのMD 5値を見て、その役割は私たちがこのソフトウェアをダウンロードした後に、ダウンロードしたファイルに対して専門のソフトウェア(例えばWindows MD 5 Checkなど)でMD 5検査をして、私たちが得たファイルがそのサイトが提供したファイルと同じファイルであることを確保することです.MD 5アルゴリズムを用いたファイル検証のスキームは,ソフトウェアダウンロード局,フォーラムデータベース,システムファイルセキュリティなどに多く応用されている.
デジタル証明書
MD 5の典型的な応用は、「改ざん」を防止するために、1つのMessage(バイト列)に対してfingerprint(指紋)を生成することである.たとえば、readme.txtというファイルに話を書き、このreadme.txtに対してMD 5の値を生成して記録します.その後、このファイルを他の人に伝えることができます.他の人がファイルの内容を変更した場合、このファイルに対してMD 5を再計算すると(2つのMD 5の値が異なる).もう1つのサードパーティの認証機関があれば、MD 5でファイル作成者の「言い逃れ」を防ぐことができる、いわゆるデジタル署名アプリケーションです.
セキュリティ・アクセス認証
MD 5は、Unix、各種BSDシステムのログインパスワード、デジタル署名など、オペレーティングシステムのログイン認証にも広く用いられている.UNシステムにおけるユーザのパスワードはMD 5(または他の類似のアルゴリズム)であるHash演算後、ファイルシステムに格納される.ユーザがログインすると、ユーザが入力したパスワードをMD 5 Hash演算し、ファイルシステムに格納されているMD 5値と比較して、入力したパスワードが正しいか否かを判定する.このような手順により、ユーザパスワードの明示コードが分からない場合に、ユーザログインシステムの正当性を判定することができる性.これにより、ユーザーのパスワードがシステム管理者権限を持つユーザーに知られないようにします.MD 5は任意の長さのバイト列を使用します.128 bitの大きな整数にマッピングし、この128 bitで元の文字列を反転させることは困難です.言い換えれば、ソースプログラムやアルゴリズムの記述を見ても、MD 5の値を元の文字列に変換することはできません.数学の原理から言えば、元の文字列は無限に複数あるので、反関数の数学関数が存在しないような気がします.md 5パスワードの問題になると、このシステムのmd 5()関数でパスワードを再設定することができます.adminのように、生成された一連のパスワードのHash値を元のHash値に上書きすればいいのです.そのため、現在ハッカーに最も多く使われている暗号解読方法は「辞書を走る」と呼ばれていますの方法です.辞書を得る方法は2つあります.1つは、日常的に収集されたパスワードとして使用される文字列表で、もう1つは、並べ替えの組み合わせ方法で生成され、MD 5プログラムでこれらの辞書項目のMD 5値を計算してから、ターゲットのMD 5値でこの辞書で検索します.パスワードの最大長は8ビットバイト(8 Bytes)と仮定します.,同時にパスワードはアルファベットと数字のみで,26+26+10=62文字であり,組み合わせられた辞書を並べた項目数はP(62,1)+P(62,2)….+P(62,8)である.ああ、それはもう天文的な数字です.この辞書を保存するにはTB級のディスクアレイが必要です.そして、この方法にはもう一つの前提があります.ターゲットアカウントの暗号MD 5値を得ることができる場合です.この暗号化技術はUNIXシステムに広く応用されています.これもUNIXシステムが一般的なオペレーティングシステムよりも堅固な理由です.
 
アルゴリズムの原理
MD 5アルゴリズムについて簡単に述べると、MD 5は512ビットパケットで入力された情報を処理し、各パケットは16個の32ビットパケットに分割され、一連の処理を経て、アルゴリズムの出力は4個の32ビットパケットからなり、この4個の32ビットパケットをカスケードした後、128ビットハッシュ値を生成する.
 
MD 5の復号化について
2004年8月17日の米カリフォルニア州サンババラの国際暗号学会議(Crypto’2004)中国山東大学の王小雲教授は、MD 5、HAVAL-128、MD 4、RIPEMDアルゴリズムを解読したと報告し、MDシリーズアルゴリズムの解読結果を発表した.
なお、王小雲教授が研究した解読方法は、本質的には本格的な解読ではなく、コンパクトな衝突を加速させただけだ.通俗的に言えば、MD 5列を1つ知ってから、原文を用いてMD 5列をハッシュした後、同じMD 5列を生成する.つまり、異なる原文を見つけて同じMD 5列を生成する方法は、解読ではなく衝突と呼ばれる.MD 5は128位しかない解読すると、超圧縮ツールになります!
ネットワーク上で流行しているMD 5復号ツールとオンライン復号サイトは、通常、ユーザーのパスワード、または比較的簡単な数字に対してのみ解読されます.その方法は、よく使われる文字列のMD 5パスワードをデータベースに保存し、復号される文字列と比較して、最終的に一致するソースコードを見つけることです.
 
JAva MD 5の暗号化とパスワード検証を実現
先に述べたように、MD 5自体に復号化のアルゴリズムはなく、プログラミング言語を用いて復号化のアルゴリズムを記述することは言うまでもない.以下、javaが実現したMD 5の暗号化とユーザーパスワードの検証に用いるプログラムを示し、参考に供する.
ツールクラスMyMD 5 Util.java:
package com.zyg.security.md5;   
  
import java.io.UnsupportedEncodingException;   
import java.security.MessageDigest;   
import java.security.NoSuchAlgorithmException;   
import java.security.SecureRandom;   
import java.util.Arrays;   
  
public class MyMD5Util {   
       
    private static final String HEX_NUMS_STR="0123456789ABCDEF";   
    private static final Integer SALT_LENGTH = 12;   
       
    /**   
     *  16               
     * @param hex   
     * @return   
     */  
    public static byte[] hexStringToByte(String hex) {   
        int len = (hex.length() / 2);   
        byte[] result = new byte[len];   
        char[] hexChars = hex.toCharArray();   
        for (int i = 0; i < len; i++) {   
            int pos = i * 2;   
            result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4    
                            | HEX_NUMS_STR.indexOf(hexChars[pos + 1]));   
        }   
        return result;   
    }   
  
       
    /**  
     *    byte     16       
     * @param b  
     * @return  
     */  
    public static String byteToHexString(byte[] b) {   
        StringBuffer hexString = new StringBuffer();   
        for (int i = 0; i < b.length; i++) {   
            String hex = Integer.toHexString(b[i] & 0xFF);   
            if (hex.length() == 1) {   
                hex = '0' + hex;   
            }   
            hexString.append(hex.toUpperCase());   
        }   
        return hexString.toString();   
    }   
       
    /**  
     *           
     * @param password  
     * @param passwordInDb  
     * @return  
     * @throws NoSuchAlgorithmException  
     * @throws UnsupportedEncodingException  
     */  
    public static boolean validPassword(String password, String passwordInDb)   
            throws NoSuchAlgorithmException, UnsupportedEncodingException {   
        // 16                   
        byte[] pwdInDb = hexStringToByte(passwordInDb);   
        //        
        byte[] salt = new byte[SALT_LENGTH];   
        //                        
        System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH);   
        //           
        MessageDigest md = MessageDigest.getInstance("MD5");   
        //               
        md.update(salt);   
        //                 
        md.update(password.getBytes("UTF-8"));   
        //              
        byte[] digest = md.digest();   
        //                      
        byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH];   
        //                
        System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length);   
        //                               
        if (Arrays.equals(digest, digestInDb)) {   
            //               
            return true;   
        } else {   
            //                 
            return false;   
        }   
    }   
  
  
    /**  
     *       16        
     * @param password  
     * @return  
     * @throws NoSuchAlgorithmException  
     * @throws UnsupportedEncodingException  
     */  
    public static String getEncryptedPwd(String password)   
            throws NoSuchAlgorithmException, UnsupportedEncodingException {   
        //               
        byte[] pwd = null;   
        //         
        SecureRandom random = new SecureRandom();   
        //          
        byte[] salt = new byte[SALT_LENGTH];   
        //             
        random.nextBytes(salt);   
  
        //           
        MessageDigest md = null;   
        //         
        md = MessageDigest.getInstance("MD5");   
        //               
        md.update(salt);   
        //                 
        md.update(password.getBytes("UTF-8"));   
        //              
        byte[] digest = md.digest();   
  
        //               ,             
        pwd = new byte[digest.length + SALT_LENGTH];   
        //                     12   ,              
        System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);   
        //                  13           
        System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);   
        //                16             
        return byteToHexString(pwd);   
    }   
}  

MD 5の暗号化およびパスワードの検証に使用されるテストクラスClient.java:
package com.zyg.security.md5;   
  
import java.io.UnsupportedEncodingException;   
import java.security.NoSuchAlgorithmException;   
import java.util.HashMap;   
import java.util.Map;   
  
public class Client {   
    private static Map users = new HashMap();   
       
    public static void main(String[] args){   
        String userName = "zyg";   
        String password = "123";   
        registerUser(userName,password);   
           
        userName = "changong";   
        password = "456";   
        registerUser(userName,password);   
           
        String loginUserId = "zyg";   
        String pwd = "1232";   
        try {   
            if(loginValid(loginUserId,pwd)){   
                System.out.println("    !!!");   
            }else{   
                System.out.println("    ,     !!!");   
            }   
        } catch (NoSuchAlgorithmException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (UnsupportedEncodingException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        }    
    }   
       
    /**  
     *       
     *   
     * @param userName  
     * @param password  
     */  
    public static void registerUser(String userName,String password){   
        String encryptedPwd = null;   
        try {   
            encryptedPwd = MyMD5Util.getEncryptedPwd(password);   
               
            users.put(userName, encryptedPwd);   
               
        } catch (NoSuchAlgorithmException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        } catch (UnsupportedEncodingException e) {   
            // TODO Auto-generated catch block   
            e.printStackTrace();   
        }   
    }   
       
    /**  
     *       
     *   
     * @param userName  
     * @param password  
     * @return  
     * @throws UnsupportedEncodingException   
     * @throws NoSuchAlgorithmException   
     */  
    public static boolean loginValid(String userName,String password)    
                throws NoSuchAlgorithmException, UnsupportedEncodingException{   
        String pwdInDb = (String)users.get(userName);   
        if(null!=pwdInDb){ //         
                return MyMD5Util.validPassword(password, pwdInDb);   
        }else{   
            System.out.println("      !!!");   
            return false;   
        }   
    }   
}

 
以上の内容は主に以下の資源によって整理された.
http://baike.baidu.com/view/7636.htm
http://cnzhangleon.lofter.com/post/4b3a3_c41a4