单向加密又称为不可逆加密算法,在加密过程中不使用密钥,明文由系统加密处理成密文,密文无法解密。一般适合于验证,在验证过程中,重新输入明文,并经过同样的加密算法处理,得到相同的密文并被系统重新认证。广泛使用于口令加密。
该算法有如下特点:
1.对同一消息反复执行加密得到相同的密文。
2.加密算法生成的密文不可预见,根明文没任何关系。
3.明文的任何微小的变化都会对密文产生很大影响。
4.不可逆,即不能通过密文获取明文。
?
比较流行的加密算法:MD5和SHA。
?
MD5:MessageDigest Algorigthm 5(信息摘要算法),MD5被广泛应用于各种软件密码认证和钥匙识别,如软件序列号。
?
Java使用MD5加密:
package com.security.example.example3;
?
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
?
public class EncrypWithMD5 {
?
/**
* @param args
*/
public static void main(String[] args) {
// 要加密的字符串
String msg = "java安全编程之单向加密MD5";
System.out.println("原文是:" + msg);
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
md.update(msg.getBytes());
byte[] encrypMsg = md.digest();
System.out.println("加密后是:" + new String(encrypMsg));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
?
}
?
输出:
原文是:java安全编程之单向加密MD5
加密后是:斧A蒮X2_娂弒懠抯
?
反复执行得到的密文都是这个。
MD5比较广泛的应用于口令管理,用户在注册后密码被经过MD5加密后保存在数据库,这样即使是数据库管理员也没法知道密码是什么。
用户登陆系统的时候,系统将用户的密码经过MD5加密与数据库中保存的密文对比,一致则通过,这样就能保证在不知道用户密码的情况下验证用户的合法性。
?
?
SHA:安全散列算法(Secure Hash Algorithm),对长度不超过264位的二进制消息产生160位的消息摘要输出。
?
Java使用SHA算法加密:
package com.security.example.example3;
?
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
?
public class EncrypWithSHA {
?
/**
* @param args
*/
public static void main(String[] args) {
// 要加密的字符串
String msg = "java安全编程之单向加密SHA";
System.out.println("原文是:" + msg);
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA");
md.update(msg.getBytes());
byte[] encrypMsg = md.digest();
System.out.println("加密后是:" + new String(encrypMsg));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
?
}
?
}
输出:
原文是:java安全编程之单向加密SHA
加密后是:Z?Vm川V1穽R__fuK挪
反复允许,结果也一样。
?
?
Java实现消息验证码
单向加密算法生成的消息摘要可以验证数据完整性。但是,如果数据在传输过程中被窃取者窃取,修改消息并重新生成摘要,将改过的数据和摘要一起发送给接收者,那这样接收者是无法判断数据是否被修改过。因为接收者根据接收到的消息产生的摘要与窃取者提供的消息摘要一致。那么,为了数据安全性,就需要知道发送方的身份,消息验证码一定程度上可以提供此功能(MAC)。
MAC:消息验证码(Message Authentication Code,MAC)。
MAC 基于秘密密钥提供一种方式来检查在不可靠介质上进行传输或存储的信息的完整性。通常,消息验证码在共享秘密密钥的两个参与者之间使用,以验证这两者之间传输的信息。
基于加密哈希函数的 MAC 机制也叫作 HMAC。结合秘密共享密钥,HMAC 可以用于任何加密哈希函数(如 MD5 或 SHA-1)。
生成摘要时,发送方和接受方拥有相同的密钥,可以通过对称算法生成事先被双方所有。
?
Java实现消息验证码:
package com.security.example.example3;
?
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
?
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
?
public class MAC {
?
public static void main(String[] args) {
try {
// 要加密的文本
String msg = "Java安全编程——实现消息验证码";
System.out.println("原文:" + msg);
Mac mac = Mac.getInstance("HMACMD5");
// 用给定的密钥初始化此 Mac 对象。
// SecretKeySpec为Key的实现类之一
// 如何构造SecretKeySpec?
// SecretKeySpec(byte[] key,String algorithm),key:密钥的密钥内容(原始密钥)。algorithm:算法
// 怎么得到密钥?KeyGenerator
// 使用DES算法得到计算验证码的密钥
KeyGenerator kg = KeyGenerator.getInstance("DES");
// 对称密钥
SecretKey sk = kg.generateKey();
// 原始密钥
byte[] encodedMsg = sk.getEncoded();
?
SecretKeySpec sks = new SecretKeySpec(encodedMsg,"HMACMD5");
// 用给定的密钥初始化
mac.init(sks);
// 处理给定的字节数组
mac.update(msg.getBytes());
?
// 计算验证码(完成MAC)
byte[] encrypMsg = mac.doFinal();
System.out.println("密文:" + new String(encrypMsg));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
?
重复执行得到的密文都不一样,因为每次DES生成的密钥不一样。
实际中,DES密钥保存在文件或数据库中,每次从中取出这样保证得到的结果是一样的。得不到密钥,当然也没法生成正确的消息验证码。