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" ));
}
}

  

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

 

最新文章

  1. c++网络编程错误(WSAStartup)
  2. java.lang.ClassNotFoundException: Didn&#39;t find class &quot;*****(转载)
  3. 深入理解spring中的各种注解
  4. sql中更新数据库用到declare @a in
  5. Bootstrap之表格checkbox复选框全选 [转]
  6. [深入React] 1. 开发环境搭建
  7. hdu 1024(dp)
  8. Java Swing界面编程(31)---菜单条:JMenu
  9. 单例模式 - 程序实现(Java)
  10. javascript 学习总结(一)
  11. STM32F103 使用TIM3产生四路PWM
  12. Gradle 1.12用户指南翻译——第三十四章. JaCoCo 插件
  13. 小程序radio样式修改
  14. 网络编程——UDP编程
  15. OkHttp封装之后使用
  16. Python中re(正则表达式)模块学习
  17. Linux内核分析 笔记四 系统调用的三个层次 ——by王玥
  18. 【ARC077F】SS
  19. C++循环链表解决约瑟夫环问题
  20. 如何扩大重做日志(redolog)文件的大小

热门文章

  1. oracle之 数据泵dump文件存放nfs报ORA-27054
  2. springMVC等小知识点记录。。。持续更新
  3. 32位汇编基础_cpu 寄存器
  4. HDU-6156 Palindrome Function(数位DP)
  5. SecureCRT 上传/下载文件到Linux服务器
  6. Django ORM-02
  7. pandas的数据结构
  8. leetcode374
  9. python的接口
  10. SQLITE3 使用总结(转)