实验项目名称:单向Hash密码算法实现及应用二
1、实验要求
(1)总结HMAC的原理;
(2)利用现有开发工具实现各种HMAC算法,并对常见信息求解摘要值;
(3)对键盘输入任意谢谢输出摘要值;
(4)读入文件,把文件内容求解摘要值。
2、实现方法
在Eclipse中编程实现上述内容
3、实验过程及结果
(1)总结HMAC的原理;
【一句话总结】:
HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
【HMAC算法的定义】
HMAC算法是一种执行“校验和”的算法,它通过对数据进行“校验”来检查数据是否被更改了。在发送数据以前,HMAC算法对数据块和双方约定的公钥进行“散列操作”,以生成称为“摘要”的东西,附加在待发送的数据块中。当数据和摘要到达其目的地时,就使用HMAC算法来生成另一个校验和,如果两个数字相匹配,那么数据未被做任何篡改。否则,就意味着数据在传输或存储过程中被某些居心叵测的人作了手脚。
【HMAC算法的定义用公式表示如下:】
HMAC(K,M)=H((K’⊕opad)∣H((K’⊕ipad)∣M))
【HMAC算法的加密步骤】
(1) 在密钥K后面添加0 或者 对密钥K用H进行处理 来创建一个字长为B的字符串。(例如,如果K的字长是20字节,B=64字节,则K后会加入44个零字节0x00;如果K的字长是120字节,B=64字节,则会用H作用于K后产生64字节的字符串)
(2) 将上一步生成的B字长的字符串与ipad做异或运算。
(3) 将数据流text填充至第二步的结果字符串中。
(4) 用H作用于第三步生成的数据流。
(5) 将第一步生成的B字长字符串与opad做异或运算。
(6) 再将第四步的结果填充进第五步的结果中。
(7) 用H作用于第六步生成的数据流,输出最终结果 。
(2)利用现有开发工具实现各种HMAC算法,并对常见信息求解摘要值;
实验代码如下所示:
import java.nio.charset.Charset;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HMACSHA1 {
// 获取 HmacMD5 Key
public static byte[] getHmacMd5Key() {
return getHmacKey("HmacMD5");
}
// 获取 HmacSHA256
public static byte[] getHmacSha256Key() {
return getHmacKey("HmacSHA256");
}
// 获取 HmacSHA512
public static byte[] getHmacSha512Key() {
return getHmacKey("HmacSHA512");
}
// 获取 HMAC Key
public static byte[] getHmacKey(String type) {
try {
// 1、创建密钥生成器
KeyGenerator keyGenerator = KeyGenerator.getInstance(type);
// 2、产生密钥
SecretKey secretKey = keyGenerator.generateKey();
// 3、获取密钥
byte[] key = secretKey.getEncoded();
return key;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// HMAC MD5 加密
public static String encryptHmacMD5(byte[] data, byte[] key) {
return encryptHmac(data, key, "HmacMD5");
}
// HMAC SHA256 加密
public static String encryptHmacSHA256(byte[] data, byte[] key) {
return encryptHmac(data, key, "HmacSHA256");
}
// HMAC SHA521 加密
public static String encryptHmacSHA512(byte[] data, byte[] key) {
return encryptHmac(data, key, "HmacSHA512");
}
// 基础MAC 算法
public static String encryptHmac(byte[] data, byte[] key, String type) {
try {
// 1、还原密钥
SecretKey secretKey = new SecretKeySpec(key, type);
// 2、创建MAC对象
Mac mac = Mac.getInstance(type);
// 3、设置密钥
mac.init(secretKey);
// 4、数据加密
byte[] bytes = mac.doFinal(data);
// 5、生成数据
String rs = encodeHex(bytes);
return rs;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 数据准16进制编码
public static String encodeHex(final byte[] data) {
return encodeHex(data, true);
}
// 数据转16进制编码
public static String encodeHex(final byte[] data, final boolean toLowerCase) {
final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
final int l = data.length;
final char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return new String(out);
}
public static void main(String[] args) {
byte[] data = "hello world".getBytes(Charset.forName("UTF-8"));
// MD5
byte[] hmacMd5KeyBytes = getHmacMd5Key();
String hexHamcMd5Key = encodeHex(hmacMd5KeyBytes);
System.out.println("HMAC Md5 密钥:" + hexHamcMd5Key);
String hmacMd5Encrypt = encryptHmacMD5(data, hmacMd5KeyBytes);
System.out.println("HMAC Md5 摘要值:" + hmacMd5Encrypt);
// SHA256
byte[] hmacSha256KeyBytes = getHmacSha256Key();
String hexHamcSha256Key = encodeHex(hmacSha256KeyBytes);
System.out.println("HMAC SHA256 密钥:" + hexHamcSha256Key);
String hmacSha256Encrypt = encryptHmacSHA256(data, hmacSha256KeyBytes);
System.out.println("HMAC SHA256 摘要值:" + hmacSha256Encrypt);
// SHA512
byte[] hmacSha512KeyBytes = getHmacSha512Key();
String hexHamcSha512Key = encodeHex(hmacSha512KeyBytes);
System.out.println("HMAC SHA512 密钥:" + hexHamcSha512Key);
String hmacSha512Encrypt = encryptHmacSHA512(data, hmacSha512KeyBytes);
System.out.println("HMAC SHA512 摘要值:" + hmacSha512Encrypt);
}
}
(3)对键盘输入任意信息输出摘要值;
import java.nio.charset.Charset;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Scanner;
/*中间算法同上省略*/
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.print("请输入需要求解摘要值的信息:");
String code=sc.nextLine();
byte[] data = code.getBytes(Charset.forName("UTF-8"));
// MD5
byte[] hmacMd5KeyBytes = getHmacMd5Key();
String hexHamcMd5Key = encodeHex(hmacMd5KeyBytes);
System.out.println("HMAC Md5 密钥:" + hexHamcMd5Key);
String hmacMd5Encrypt = encryptHmacMD5(data, hmacMd5KeyBytes);
System.out.println("HMAC Md5 摘要值:" + hmacMd5Encrypt);
// SHA256
byte[] hmacSha256KeyBytes = getHmacSha256Key();
String hexHamcSha256Key = encodeHex(hmacSha256KeyBytes);
System.out.println("HMAC SHA256 密钥:" + hexHamcSha256Key);
String hmacSha256Encrypt = encryptHmacSHA256(data, hmacSha256KeyBytes);
System.out.println("HMAC SHA256 摘要值:" + hmacSha256Encrypt);
// SHA512
byte[] hmacSha512KeyBytes = getHmacSha512Key();
String hexHamcSha512Key = encodeHex(hmacSha512KeyBytes);
System.out.println("HMAC SHA512 密钥:" + hexHamcSha512Key);
String hmacSha512Encrypt = encryptHmacSHA512(data, hmacSha512KeyBytes);
System.out.println("HMAC SHA512 摘要值:" + hmacSha512Encrypt);
}
}
(4)读入文件,把文件内容求解摘要值。
import java.nio.charset.Charset;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
/*中间算法同上省略*/
public static void main(String[] args)throws Exception{
try (BufferedReader ar = new BufferedReader(new FileReader("E:\\eclipse\\a.txt"))) {
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\eclipse\\b.txt"));
String code=ar.readLine();
byte[] data = code.getBytes(Charset.forName("UTF-8"));
// MD5
byte[] hmacMd5KeyBytes = getHmacMd5Key();
String hexHamcMd5Key = encodeHex(hmacMd5KeyBytes);
String hmacMd5Encrypt = encryptHmacMD5(data, hmacMd5KeyBytes);
// SHA256
byte[] hmacSha256KeyBytes = getHmacSha256Key();
String hexHamcSha256Key = encodeHex(hmacSha256KeyBytes);
String hmacSha256Encrypt = encryptHmacSHA256(data, hmacSha256KeyBytes);
// SHA512
byte[] hmacSha512KeyBytes = getHmacSha512Key();
String hexHamcSha512Key = encodeHex(hmacSha512KeyBytes);
String hmacSha512Encrypt = encryptHmacSHA512(data, hmacSha512KeyBytes);
String text = "HMAC Md5 密钥:" + hexHamcMd5Key +"\r\n"
+"HMAC Md5 摘要值:" + hmacMd5Encrypt+"\r\n"
+"HMAC SHA256 密钥:" + hexHamcSha256Key+"\r\n"
+"HMAC SHA256 摘要值:" + hmacSha256Encrypt+"\r\n"
+"HMAC SHA512 密钥:" + hexHamcSha512Key+"\r\n"
+"HMAC SHA512 摘要值:" + hmacSha512Encrypt+"\r\n";
bw.write(text);
bw.newLine();
bw.close();
}
}
}