• java MD5 并发


    Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。

    查看MessageDigest源码

    public void update(byte[] input) {
            engineUpdate(input, 0, input.length);
            state = IN_PROGRESS;
    }
    

    可以看到这里调用了engineUpdate方法,此方法进行一个更新操作。

    然后state属性的状态就被改变了,表明当前计算正在处理过程中。

    state默认属性

    private int state = INITIAL;

    然后需要调用MessageDigest.digest()方法计算哈希值

     

    public byte[] digest() {
            /* Resetting is the responsibility of implementors. */
            byte[] result = engineDigest();
            state = INITIAL;
            return result;
    }
    

    到这里已经完成了MD5值的计算,state属性恢复初始状态,如果想要重用MessageDigest对象,还需要调用MessageDigest.reset()方法进行重置,以免这次计算数据会对下一次的计算造成影响,从而导致计算结果错误。

    而我所遇到的问题就是,在MessageDigest在多线程的环境下,Thread-1的计算还没有完成的情况下,Thread-2又开始使用该MessageDigest对象进行下一次的计算,Thread-2修改了MessageDigest的状态,Thread-1使用被修改过后的MessageDigest进行计算,从而导致了计算结果错误。

    解决方案有两个:

    1、加锁来共享同一个MessageDigest;

    public class MD5 {
    private static final byte[] ToHex_ =
    { '0','1','2','3','4','5','6','7',
    '8','9','a','b','c','d','e','f'
    };
    private MessageDigest md5_ = null;
    static private MessageDigest Md5_;
    static
    {
    try { Md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
    catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
    };
    
    public MD5()
    {
    try { md5_ = MessageDigest.getInstance("MD5");} // MD5 is supported
    catch ( NoSuchAlgorithmException e ) {}; // safe to swallow
    }
    /**
    * 
    */
    public static synchronized String Digest(byte[] dataToHash)
    {
    Md5_.update(dataToHash, 0, dataToHash.length);
    return HexStringFromBytes( Md5_.digest() );
    }
    /**
    * Non-threadsafe MD5 digest (hashing) function
    */
    public String digest(byte[] dataToHash)
    {
    md5_.update(dataToHash, 0, dataToHash.length);
    return HexStringFromBytes( md5_.digest() );
    }
    private static String HexStringFromBytes(byte[] b)
    {
    byte [] hex_bytes = new byte[ b.length * 2 ];
    int i,j=0;
    for (i=0; i < b.length; i++)
    {
    hex_bytes[j] = ToHex_[ ( b[i] & 0xF0 ) >> 4 ] ;
    hex_bytes[j+1] = ToHex_[ b[i] & 0xF ];
    j+=2;
    }
    return new String( hex_bytes );
    }
    }
    

      

    2、每次新创建一个MessageDigest;

    class  MD5_test {  
       public   final   static  String MD5(String s) {  
        char  hexDigits[] = {  '0' ,  '1' ,  '2' ,  '3' ,  '4' ,  '5' ,  '6' ,  '7' ,  '8' ,  '9' ,  
          'a' ,  'b' ,  'c' ,  'd' ,  'e' ,  'f'  };  
        try  {  
       byte [] strTemp = s.getBytes();  
       MessageDigest mdTemp = MessageDigest.getInstance("MD5" );  
       mdTemp.update(strTemp);  
       byte [] md = mdTemp.digest();  
       int  j = md.length;  
       char  str[] =  new   char [j *  2 ];  
       int  k =  0 ;  
       for  ( int  i =  0 ; i < j; i++) {  
        byte  byte0 = md[i];  
        str[k++] = hexDigits[byte0 >>> 4  &  0xf ];  
        str[k++] = hexDigits[byte0 & 0xf ];  
       }  
       return   new  String(str);  
      } catch  (Exception e) {  
       return   null ;  
      }  
     }  
      
     public   static   void  main(String[] args) {  
      // MD5_Test aa = new MD5_Test();   
    	 System.out.print(MD5_test.MD5("a" ));  
    //  System.out.print(MD5_test.MD5("%7B%7DAHRCU" ));  
     }  
    } 
    

      

    这两种方案都可解决并发问题。

     

  • 相关阅读:
    C#中正则表达式的分组构造
    CompressionModule压缩模块
    BS程序代码与安全与基本攻击/防御模式
    mssql 性能优化的一些认识
    sql语句基础
    利用.net2.0中的GZip或Deflate压缩文件
    一个完整的ID生成器,并极大地降低了并发重复的概率,转换成十六进制 时间戳
    IE中的条件注释表
    DevExpress的10个使用技巧
    几种检查调试CSS布局的有效方法
  • 原文地址:https://www.cnblogs.com/xujishou/p/8044339.html
Copyright © 2020-2023  润新知