Java加密解密(2)消息摘要(Message Digest)

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");
		//初始化私钥,若为公钥则使用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>>