java密码学信息摘要
注意:这里说的摘要和加密是两个不同的概念,摘要是哈希值,我们通过散列函数比如MD5或者SHA-1算法等计算出来的值,用于验证数据完整性和唯一性的哈希值,不管原始数据是什么样的,得到的哈希值都是固定长度的,同时,它的结果是唯一的,也就是说一个消息对应着唯一结果;加密是通过“加密算法”将明文加密成密文。
散列函数只要是应用于信息安全应用程序中。哈希函数是将数字输入值转换为另一个压缩数值的数学函数。 散列函数的输入具有任意长度,但输出始终具有固定长度。
散列函数的原理:用户将需要加密的数据经过hash函数转换成信息摘要。
日常应用
校验数据的完整性,防止在传输途中被篡改
消息摘要的分类
(1)MD5(Message Digest)消息摘要算法
(2)SHA(Secure Hash Algorithm)安全散列算法
(3)MAC(Message Authentication Code)消息认证码算法,结合了MD5和SHA的优势,同时用密钥对摘要进行加密,是一种更为安全的消息摘要算法。
java包中提供了一个MessageDigest的类,它属于java.security包,里面有SHA,HMAC,MD算法之类的算法,以将任意长度的消息转换为信息摘要。
以下以sha算法为例,具体的步骤具体:
第1步:创建MessageDigest对象:
MessageDigest类提供名为getInstance()的方法。 此方法接受String变量,该变量指定要使用的算法的名称,并返回实现指定算法的MessageDigest对象。使用getInstance()方法创建MessageDigest对象,如下所示
MessageDigest md = MessageDigest.getInstance("SHA-256");
第2步:将数据传递给创建的MessageDigest对象:
创建消息摘要对象后,需要将消息/数据传递给它。 可以使用MessageDigest类的update()方法执行此操作,此方法接受表示消息的字节数组,并将其添加/传递给上面创建的MessageDigest对象。
md.update(msg.getBytes());
第3步:生成消息摘要:
可以使用digest()方法生成消息摘要,MessageDigest类此方法计算当前对象的散列函数,并以字节数组的形式返回消息摘要。
byte[] digest = md.digest();
举一个例子,下面是从控制台中读取一段字符串,然后生成他的信息摘要。
import java.security.MessageDigest;
import java.util.Scanner;
public class MessageDigestExample {
public static void main(String args[]) throws Exception{
//Reading data from user
Scanner sc = new Scanner(System.in);
System.out.println("Enter the message");
String message = sc.nextLine();
//Creating the MessageDigest object
MessageDigest md = MessageDigest.getInstance("SHA-256");
//Passing data to the created MessageDigest Object
md.update(message.getBytes());
//Compute the message digest
byte[] digest = md.digest();
System.out.println(digest);
//Converting the byte array in to HexString format
StringBuffer hexString = new StringBuffer();
for (int i = 0;i<digest.length;i++) {
hexString.append(Integer.toHexString(0xFF & digest[i]));
}
System.out.println("Hex format : " + hexString.toString());
}
}
下面其他一些算法的例子:
import java.io.File;
import java.io.FileInputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class MessageDigestUtil {
/**
* 计算MD5值
*/
public static String encryptMD5(byte[] data) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");//MD5,MD2
messageDigest.update(data);
return BytesToHex.fromBytesToHex(messageDigest.digest());
}
/**
* 计算文件的MD5值(指纹签名)
*/
public static String getFileMD5(String path) throws Exception {
FileInputStream fis = new FileInputStream(new File(path));
DigestInputStream dis = new DigestInputStream(fis, MessageDigest.getInstance("MD5"));
try {
byte[] buffer = new byte[1024];
int read = dis.read(buffer, 0, 1024);
while (read != -1) {
read = dis.read(buffer, 0, 1024);
}
MessageDigest md = dis.getMessageDigest();
return BytesToHex.fromBytesToHex(md.digest());
} finally {
dis.close();
fis.close();
}
}
/**
* 计算SHA值
*/
public static String encryptSHA(byte[] data) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA");//SHA,SHA1,SHA-1,SHA-256,SHA-384,SHA-512
messageDigest.update(data);
return BytesToHex.fromBytesToHex(messageDigest.digest());
}
/**
* 初始化HMAC密钥
*/
public static byte[] initHmacKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA512");//HmacMD5,HmacSHA1,HmacSHA256,HmacSHA384,HmacSHA512
return keyGenerator.generateKey().getEncoded();
}
/**
* 使用Hmac生成的密钥对数据进行加密
*/
public static String encryptHmac(byte[] data, byte[] key) throws Exception {
SecretKey secretKey = new SecretKeySpec(key, "HmacSHA512");
Mac mac = Mac.getInstance("HmacSHA512");
mac.init(secretKey);
return BytesToHex.fromBytesToHex(mac.doFinal(data));
}
public static void main(String[] args) throws Exception {
String data = "123456";
String path = "/Users/admin/Downloads/httpd-2.4.20.tar.gz";
System.out.println(data + " 的MD5值: " + MessageDigestUtil.encryptMD5(data.getBytes()));
System.out.println(path + " 的文件MD5签名: " + MessageDigestUtil.getFileMD5(path));
System.out.println(data + " 的SHA值: " + MessageDigestUtil.encryptSHA(data.getBytes()));
byte[] hmacKey = initHmacKey();
System.out.println("初始化Hmac密钥:" + BytesToHex.fromBytesToHex(hmacKey));
System.out.println(data + " 是的Hmac加密值为: " + MessageDigestUtil.encryptHmac(data.getBytes(), hmacKey));
}
}
字节码数组转成16进制字符串工具类:
public class BytesToHex {
public static String fromBytesToHex(byte[] resultBytes) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < resultBytes.length; i++) {
if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
builder.append("0").append(
Integer.toHexString(0xFF & resultBytes[i]));
} else {
builder.append(Integer.toHexString(0xFF & resultBytes[i]));
}
}
return builder.toString();
}
}