Java加密解密(二)消息摘要(Message Digest)
消息摘要(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");//初始化私钥,若为公钥则使用initVerirysigner.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.sigFileOutputStream 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>>