Java加密解密(2)消息摘要(Message Digest)
Java加密解密(二)消息摘要(Message Digest)
消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。 不同的消息获得的消息摘要各异,但相同的消息其消息摘要是唯一的。
消息验证码
当一个文件和它的消息摘要一起从发送方传递到接收方时,接收方利用消息摘要验证数据,可以判断传输过程中有无修改过(判断完整性)。但是这样做的前提是消息摘要传输要正确无误。若传输过程中某人修改过文件,同时重新生成对应的消息摘要再传给对方,这样就无法验证是否原文被修改过,消息验证码就是用来解决这一问题。
消息通讯双方具有的共同密钥叫消息验证码。使用消息验证码的双方要有共同的密钥,发送方将消息摘要加密后发送,这样由于用密钥加密了消息摘要,无密钥难于修改消息摘要。接收方一定程度上可以验证发送方身份。javax.crypto包中的类Mac提供了计算消息摘要验证码的方法。
数字签名
在java中完成数据签名的类是Signature。
消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了。因此消息摘要保证了消息的完整性。 不同的消息获得的消息摘要各异,但相同的消息其消息摘要是唯一的。
public class TestMD5MessageDigest { private static String str = "Hello,I sent to you 80 yuan."; public static void main(String[] args) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(str.getBytes("UTF-8")); byte[] re = md.digest(); System.out.println(re); String result = ""; for (int i = 0; i < re.length; i++) { result += Integer.toHexString((0x000000ff & re[i]) | 0xffffff00).substring(6); } System.out.println(result); } }
消息验证码
当一个文件和它的消息摘要一起从发送方传递到接收方时,接收方利用消息摘要验证数据,可以判断传输过程中有无修改过(判断完整性)。但是这样做的前提是消息摘要传输要正确无误。若传输过程中某人修改过文件,同时重新生成对应的消息摘要再传给对方,这样就无法验证是否原文被修改过,消息验证码就是用来解决这一问题。
消息通讯双方具有的共同密钥叫消息验证码。使用消息验证码的双方要有共同的密钥,发送方将消息摘要加密后发送,这样由于用密钥加密了消息摘要,无密钥难于修改消息摘要。接收方一定程度上可以验证发送方身份。javax.crypto包中的类Mac提供了计算消息摘要验证码的方法。
public class TestMD5MAC { private static String message = "Hello World !"; public static void main(String[] args) { byte[] bytes = message.getBytes("utf-8"); KeyGenerator ken = KeyGenerator.getInstance("DESede"); ken.init(168); SecretKey key = ken.generateKey(); Mac mac = Mac.getInstance("HmacMD5"); mac.init(key); mac.update(bytes); byte[] encryCodes = mac.doFinal(); System.out.println("============消息摘要验证码============="); StringBuffer res = new StringBuffer(); for (int j = 0; j < encryCodes.length; j++) { res.append(res); res.append(Integer.toHexString((0x000000ff & encryCodes[j]) | 0xffffff00).substring(6)); } System.out.println(res.toString()); System.out.println(); // 保存到文件中,以便验证消息摘要 FileOutputStream fos = new FileOutputStream("mac.dat"); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(encryCodes); } }
数字签名
在java中完成数据签名的类是Signature。
public class TestSignature { private static String str = "I'm live in china !"; public static void main(String[] args) { byte[] bytes = str.getBytes("utf-8"); String str = new String(bytes); System.out.println("==========要签名的原文==========="); System.out.println(str); KeyPairGenerator ken = KeyPairGenerator.getInstance("RSA"); ken.initialize(1024); KeyPair pair = ken.genKeyPair(); PrivateKey pri = pair.getPrivate(); Signature signer = Signature.getInstance("MD5withRSA"); //初始化私钥,若为公钥则使用initVeriry signer.initSign(pri); signer.update(bytes); byte[] signs = signer.sign(); System.out.println("============签名============="); for (int j = 0 ; j < signs.length ; j++) { System.out.print(signs[j]); if ((j % 8) == 7 ) { System.out.println(); } } //保存签名到rsasign.sig FileOutputStream fos = new FileOutputStream("rsasign.sig"); for (int j = 0 ; j < signs.length ; j++) { fos.write(signs[j]); } fos.flush(); fos.close(); PublicKey pub = pair.getPublic(); RSAPublicKey rpub = (RSAPublicKey)pub; byte [] kb = rpub.getEncoded(); //保存公钥 FileOutputStream fos2 = new FileOutputStream("rsapub.dat"); fos2.write(kb); fos2.close(); signer.initVerify(rpub); signer.update(bytes); boolean ok = false; FileInputStream fis = new FileInputStream("rsasign.sig"); int num = fis.available(); byte [] bytes2 = new byte[num]; fis.read(bytes2); ok = signer.verify(bytes2); System.out.println("签名验证结果 :"+ok); } }
<<To Be Continued>>