MD5和SHA-1加密后生成的字符串长度分别为32和40。
MD5算法普遍用于数字签名技术
数字签名技术:可以检测文件或其他应用的完整性,判断有无修改;
简单应用如下:
假设通信的两端,一端为文件的发送者,而另一端为文件的接受者。
发送端:发送者对所发送的文件调用相关的函数来生成该文件的摘要信息,然后将该摘要信息用其本人的私钥进行加密处理,将摘要信息的密码模式与该文件一起发送给接受者;
接受端:这时接受者共得到两样东西,一个是所需要的文件,另一个是已加密摘要信息,接受端处理如下,
首先使用发送者提供的公钥对已加密的摘要信息进行解密处理,还原摘要信息的明码格式;
然后对接受到的文件像发送端那样进行函数处理,将得到的摘要信息与解密出来的摘要信息进行比对。
如果比对结果相同,则说明接受的文件是完整的;如果不同,说明文件在传输的过程中可能被修改过或已感染病毒。
由上可以看出:数字签名实际上是一个加密的过程;而数字签名的验证实际上是一个解密的过程。
数字签名技术普遍应用于软件下载站,论坛数据库,系统文件安全等方面,如:当我们下载某一软件时,经常会在该软件的描述信息中找到其MD5值来用于下载后的校验过程,从而有效防止病毒。
MD5还普遍应用于操作系统或一般系统的登录认证上,如当我们开发使用人员管理系统时,发现数据库表中所存储的用户密码并不是用户所输入的原生态的密码格式,而是经过MD5处理后的一段字符串。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,在和数据库表中的md5值进行比较来确定输入密码是否正确。这样便避免了普通用户的密码被具有系统管理员权限的用户查到,即使查数据库,得到的也只是MD5处理后的信息,而摘要信息向源信息的转变是一个不可逆的过程。
工作应用:
前段时间一直在做银行全国影像的项目,在央行与商业银行影像交互的过程中,涉及到报文的编签、核签过程,其实也是数字签名的使用过程,以此来确保报文信息的完整性。
实用类:获取某一字节流的摘要信息
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
public String getMD5(byte[] source){
String s=null;
//用来将字节转换成16进制表示的字符
char[] hexDigits={'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f'};
try {
MessageDigest md=MessageDigest.getInstance("MD5");
md.update(source);
//MD5的计算结果是一个128位的长整数,用字节表示为16个字节
byte[] tmp=md.digest();
//每个字节用16进制表示的话,使用2个字符(高4位一个,低4位一个),所以表示成16进制需要32个字符
char[] str=new char[16*2];
int k=0;//转换结果中对应的字符位置
for(int i=0;i<16;i++){//对MD5的每一个字节转换成16进制字符
byte byte0=tmp[i];
str[k++]=hexDigits[byte0>>>4 & 0xf];//对字节高4位进行16进制转换
str[k++]=hexDigits[byte0 & 0xf]; //对字节低4位进行16进制转换
}
s=new String(str);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return s;
}
public static void main(String[] args) {
MD5Util md5Util=new MD5Util();
String result=md5Util.getMD5("abc".getBytes());
System.out.println(result);
}
}
java加密解密应用——DES算法
应用领域:IC卡,POS机,ATM机,加油站,高速公路收费站。
应用场景:信用卡持卡人的PIN的加密传输,IC卡与 POS机之间的双向认证。
算法入口参数:KEY,Data,Mode
key:DES算法的工作密钥
Mode:DES算法的工作模式(加密|解密)
Data:需要加密或解密的数据
工作方式:
如果Mode为加密模式,则用key对数据data进行加密处理,生成data的密码模式
如果Mode为解密模式,则用key对数据data进行解密处理,还原data的明码模式
这样,在通信网络的两端,双方约定好一致的key,源端用key对核心数据进行DES加密,以密码形式传输到目的端,数据到达目的端后,用同样的key对密码数据进行解密,便再现了明码形式的核心数据,从而确保了通信数据在网络传输过程中的安全性和可靠性。
而通过定期在源端和目的端同时更新相同的key,便更进一步提高数据的保密性。
应用实例:加密解密文件操作
步骤1:调用java API生成DES算法的key值,将该key保存到文件中去,供网络通信的源端和目的端使用。
步骤2:源端对测试文件进行加密处理,加密后将文件以密码的形式发送到目的端。
步骤3:目的端对已加密的文件进行解密,还原文件的明码模式。
方法:
savePriveKey(String keyFile):将密钥保存到指定文件中
encryptionFile(String file,String keyFile)//加密文件,通过指定的key文件
decryptionFile(String file,String keyFile)//解密文件,通过指定的key文件
java源码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
/**
* DES加密解密操作
* @author chenxu
*/
public class DESUtil {
/**
* 将私钥保存到指定文件中
* @param keyFile 保存私钥的文件
*/
public void savePriveKey(String keyFile){
FileOutputStream fos=null;
try {
KeyGenerator keyGen=KeyGenerator.getInstance("DES");
SecureRandom sr=new SecureRandom();
keyGen.init(sr);
SecretKey key=keyGen.generateKey();
byte[] rawKeyData=key.getEncoded();
fos=new FileOutputStream(keyFile);
fos.write(rawKeyData);
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}finally{
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 加密字符串
* @param text 要加密的字符串
* @param keyFile 密钥文件
*/
public void encryptionFile(String file,String keyFile){
SecureRandom sr=new SecureRandom();
SecretKey key=getPrivetKey(keyFile);
FileInputStream fis=null;
FileOutputStream fos=null;
try {
Cipher cipher=Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key,sr);
fis=new FileInputStream(new File(file));
byte[] data=new byte[fis.available()];
fis.read(data);
byte[] encryptedData=cipher.doFinal(data);
fos=new FileOutputStream(new File(file));
fos.write(encryptedData);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 对已加密的文件进行解密
* @param file 已加密的文件
* @param keyFile 密钥文件
*/
public void decryptionFile(String file,String keyFile){
SecretKey key=getPrivetKey(keyFile);
SecureRandom sr=new SecureRandom();
FileInputStream fis=null;
FileOutputStream fos=null;
try {
Cipher cipher=Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE,key,sr);
fis=new FileInputStream(new File(file));
byte[] encryptedData=new byte[fis.available()];
fis.read(encryptedData);
byte[] decryptedData=cipher.doFinal(encryptedData);
fos=new FileOutputStream(new File(file));
fos.write(decryptedData);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取私钥
* @param keyFile 私钥文件
* @return 个人私钥
*/
private SecretKey getPrivetKey(String keyFile) {
FileInputStream fis=null;
SecretKey key=null;
try {
fis=new FileInputStream(new File(keyFile));
byte[] rawKeyData=new byte[fis.available()];
fis.read(rawKeyData);
DESKeySpec dks=new DESKeySpec(rawKeyData);
key=SecretKeyFactory.getInstance("DES").generateSecret(dks);
}catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return key;
}
public static void main(String[] args){
DESUtil desUtil=new DESUtil();
// desUtil.savePriveKey("key.txt");
// desUtil.encryptionFile("test.txt", "key.txt");
desUtil.decryptionFile("test.txt", "key.txt");
}
}
package com.ice.webos.util.security;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.Key;
import java.security.MessageDigest;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* <ul>
* <li>BASE64的加密解密是双向的,可以求反解。</li>
* <li>MD5、SHA以及HMAC是单向加密,任何数据加密后只会产生唯一的一个加密串,通常用来校验数据在传输过程中是否被修改。</li>
* <li>HMAC算法有一个密钥,增强了数据传输过程中的安全性,强化了算法外的不可控因素。</li>
* <li>DES DES-Data Encryption Standard,即数据加密算法。
* DES算法的入口参数有三个:Key、Data、Mode。
* <ul>
* <li>Key:8个字节共64位,是DES算法的工作密钥;</li>
* <li>Data:8个字节64位,是要被加密或被解密的数据;</li>
* <li>Mode:DES的工作方式,有两种:加密或解密。</li>
* </ul>
* </li>
* <ul>
*
* @author Ice_Liu
*
*/
public class CryptUtil {
private static final String KEY_MD5 = "MD5";
private static final String KEY_SHA = "SHA";
/**
* MAC算法可选以下多种算法
*
* <pre>
*
* HmacMD5
* HmacSHA1
* HmacSHA256
* HmacSHA384
* HmacSHA512
* </pre>
*/
public static final String KEY_MAC = "HmacMD5";
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64 加密
*
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}
/**
* MD5加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptMD5(byte[] data) throws Exception {
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
md5.update(data);
return md5.digest();
}
/**
* SHA加密
*
* @param data
* @return
* @throws Exception
*/
public static byte[] encryptSHA(byte[] data) throws Exception {
MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
sha.update(data);
return sha.digest();
}
/**
* 初始化HMAC密钥
*
* @return
* @throws Exception
*/
public static String initMacKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
SecretKey secretKey = keyGenerator.generateKey();
return encryptBASE64(secretKey.getEncoded());
}
/**
* HMAC 加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return mac.doFinal(data);
}
/**
* DES 算法 <br>
* 可替换为以下任意一种算法,同时key值的size相应改变。
*
* <pre>
* DES key size must be equal to 56
* DESede(TripleDES) key size must be equal to 112 or 168
* AES key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
* Blowfish key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
* RC2 key size must be between 40 and 1024 bits
* RC4(ARCFOUR) key size must be between 40 and 1024 bits
* </pre>
*/
public static final String ALGORITHM = "DES";
/**
* DES 算法转换密钥<br>
*
* @param key
* @return
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
SecretKey secretKey = null;
if (ALGORITHM.equals("DES") || ALGORITHM.equals("DESede")) {
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
secretKey = keyFactory.generateSecret(dks);
} else {
// 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码
secretKey = new SecretKeySpec(key, ALGORITHM);
}
return secretKey;
}
/**
* DES 算法解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] data, String key) throws Exception {
Key k = toKey(decryptBASE64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* DES 算法加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] data, String key) throws Exception {
Key k = toKey(decryptBASE64(key));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* DES 算法生成密钥
*
* @return
* @throws Exception
*/
public static String initKey() throws Exception {
return initKey(null);
}
/**
* DES 算法生成密钥
*
* @param seed
* @return
* @throws Exception
*/
public static String initKey(String seed) throws Exception {
SecureRandom secureRandom = null;
if (seed != null) {
secureRandom = new SecureRandom(decryptBASE64(seed));
} else {
secureRandom = new SecureRandom();
}
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
kg.init(secureRandom);
SecretKey secretKey = kg.generateKey();
return encryptBASE64(secretKey.getEncoded());
}
public static void main(String[] args) {
try {
String s = "阿伯才的覆盖";
String b = CryptUtil.encryptBASE64(s.getBytes("UTF-8"));
System.out.println("BASE64加密后:" + b);
byte[] c = CryptUtil.decryptBASE64(b);
System.out.println("BASE64解密后:" + new String(c, "UTF-8"));
c = encryptMD5(s.getBytes());
System.out.println("MD5 加密后:" + new BigInteger(c).toString(16));
c = encryptSHA(s.getBytes());
System.out.println("SHA 加密后:" + new BigInteger(c).toString(16));
String key = initMacKey();
System.out.println("HMAC密匙:" + key);
c = encryptHMAC(s.getBytes(), key);
System.out.println("HMAC 加密后:" + new BigInteger(c).toString(16));
key = initKey();
System.out.println(ALGORITHM + "密钥:\t" + key);
c = encrypt(s.getBytes("UTF-8"), key);
System.out.println(ALGORITHM + " 加密后:" + new BigInteger(c).toString(16));
c = decrypt(c, key);
System.out.println(ALGORITHM + " 解密后:" + new String(c, "UTF-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}