java中的常用种加密模式

原创
2020/03/11 10:59
阅读数 199

java加密算法有:
1、BASE64 严格地说,属于编码格式,而非加密算法
2、摘要算法
3、对称加密
4、非对称加密

一、BASE64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串, 用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性, 即所编码的数据不会被人用肉眼所直接看到。
在之前jdk1.8之前需要依赖第三方库支持Base64编码在1.8之后以及加到java8的官方库中可以直接使用Base64类进行编解码

package com.qian.encoded;
import java.util.Base64;
public class Base64Test {
    public static void main(String[] args) {
        String str =  "中国加油,武汉加油!";
        Base64.Encoder encoder = Base64.getEncoder();
        Base64.Decoder decoder= Base64.getDecoder();
        String encodeStr = encoder.encodeToString(str.getBytes());
        System.out.println("加密后str: "+encodeStr);
        String decoderStr  = new String (decoder.decode(encodeStr));
        System.out.println("解密后str: "+decoderStr);
    }
}

二、摘要算法
消息摘要算法用来验证数据的完整性,分为三类
MD(Message Digest):消息摘要
SHA(Secure Hash Algorithm):安全散列
MAC(Message Authentication Code):消息认证码
最常见的登录密码加密处理,MD5加密,MD5属于消息摘要类,用途可以用来保证内容不被篡改:密码加密、文件校验码
JDK8支持的加密种类,请参考:https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest

 

import java.math.BigInteger;
import java.security.MessageDigest;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 单向加密,消息摘要
 * Digest
 * 
 */
public class Digest {
    private static String KEY_MD5 = "MD5";
    private static String KEY_SHA = "SHA";
    private static String KEY_MAC = "HmacMD5";
    /**
     * md5加密
     * <br/>
     * MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,
     * 广泛用于加密和解密技术,常用于文件校验。管文件多大,经过MD5后都能生成唯一的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加密
     * <br/>
     * SHA(Secure Hash Algorithm,安全散列算法),
     * 数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域。
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {  
        MessageDigest md5 = MessageDigest.getInstance(KEY_SHA);
        md5.update(data);  
        return md5.digest();  
    }
    
    /** 
          * 初始化HMAC密钥 
     *  
     * @return 
     * @throws Exception 
     */  
    public static byte[] initMacKey() throws Exception {  
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);  
        SecretKey secretKey = keyGenerator.generateKey();  
        return secretKey.getEncoded();  
    }  
  
    /** 
     * HMAC加密 
     * <br/>
     *  HMAC(Hash Message Authentication Code,散列消息鉴别码,
     *  基于密钥的Hash算法的认证协议。消息鉴别码实现鉴别的原理是,
     *  用公开函数和密钥产生一个固定长度的值作为认证标识, 用这个标识鉴别消息的完整性。
     *  使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,
     *  然后传输。接收方利用与发送方共享的密钥进行鉴别认证等。 
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] encryptHMAC(byte[] data, byte[] key) throws Exception {  
  
        SecretKey secretKey = new SecretKeySpec(key, KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());  
        mac.init(secretKey);  
        return mac.doFinal(data);
  
    }  
    
    public static void main(String[] args) {
        try {
            byte[] md5 = encryptMD5("hello".getBytes());
            System.out.println("hello md5:"+new BigInteger(md5).toString(16));
            
            byte[] sha = encryptSHA("hash".getBytes());
            System.out.println("hash sha:"+new BigInteger(sha).toString(16));
            
            byte[] macKey = initMacKey();
            byte[] hmac = encryptHMAC("hello hash".getBytes(), macKey);
            System.out.println("hello hash key:"+new BigInteger(macKey).toString(16)
                    +"\r\n encrypt:"+new BigInteger(hmac).toString(16));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


三、对称加密
DES(Data Encryption Standard,数据加密算法) 
PBE(Password-based encryption,基于密码验证)

import java.security.Key;
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-Data Encryption Standard,即数据加密算法。 DES安全编码组件,
 * DES算法的入口参数有三个:Key、Data、Mode。
 * 其中Key为8个字节共64位,是DES算法的工作密钥; Data也为8个字节64位,
 * 是要被加密或被解密的数据;
 * Mode为DES的工作方式,有两种:加密或解密。 DESCoder
 * 
 */
public class DESCoder {
    public static final String ALGORITHM = "DES";
    /**
     * 转换密钥
     * 
     * @param key
     * @return
     * @throws Exception
     */
    private static Key toKey(byte[] key) throws Exception {
        DESKeySpec dks = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(dks);
        // 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码
        // SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);

        return secretKey;
    }

    /**
     * 加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, k);

        return cipher.doFinal(data);
    }

    /**
     * 解密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, k);

        return cipher.doFinal(data);
    }

    /**
     * 生成密钥
     * 
     * @return
     * @throws Exception
     */
    public static byte[] initKey() throws Exception {
        return initKey("1111".getBytes());
    }

    /**
     * 生成密钥
     * 
     * @param seed
     * @return
     * @throws Exception
     */
    public static byte[] initKey(byte[] seed) throws Exception {
        SecureRandom secureRandom = null;
        if (seed != null) {
            secureRandom = new SecureRandom(seed);
        } else {
            secureRandom = new SecureRandom();
        }
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
        kg.init(secureRandom);
        SecretKey secretKey = kg.generateKey();
        return secretKey.getEncoded();
    }

    public static void main(String[] args) {
        try {
            String inputStr = "DES";
            byte[] key = DESCoder.initKey();
            System.err.println("原文:\t" + inputStr);
            System.err.println("密钥:\t" + key);
            byte[] inputData = inputStr.getBytes();
            inputData = DESCoder.encrypt(inputData, key);
            System.err.println("加密后:\t" + inputData);
            byte[] outputData = DESCoder.decrypt(inputData, key);
            String outputStr = new String(outputData);
            System.err.println("解密后:\t" + new String(outputStr));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


四、非对称加密

RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman) 
DH(Diffie-Hellman算法,密钥一致协议) 
DSA(Digital Signature Algorithm,数字签名) 
ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)
目前RSA算法用的比较多,用在不可信的环境下

RSACoder.java

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/**
 * RSA安全编码组件,非对称加密算法——RSA。既能用于数据加密也能用于数字签名的算法,
 * 易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
 * <br/>
 * 流程分析:<br/>
 * <ul>
 * <li>甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。
 * <li>甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;
 * <li>乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。
 * <li>乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。 
 * </ul>
 * RSACoder
 * 
 */
public abstract class RSACoder {  
    public static final String KEY_ALGORITHM = "RSA";  
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";  
  
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";  
  
    /** 
           * 用私钥对信息生成数字签名
     *  
     * @param data  加密数据 
     * @param privateKey 私钥 
     *  
     * @return 
     * @throws Exception 
     */  
    public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
  
        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);  
  
        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
  
        // 取私钥匙对象  
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);  
  
        // 用私钥对信息生成数字签名  
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);  
        signature.initSign(priKey);  
        signature.update(data);  
        return signature.sign();  
    }  
  
    /** 
     * 校验数字签名 
     *  
     * @param data 加密数据 
     * @param publicKey 公钥 
     * @param sign 数字签名 
     *  
     * @return 校验成功返回true 失败返回false 
     * @throws Exception 
     *  
     */  
    public static boolean verify(byte[] data, byte[] publicKey, byte[] sign)  
            throws Exception {  
  
        // 构造X509EncodedKeySpec对象 
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);  
  
        // KEY_ALGORITHM 指定的加密算法  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  
        // 取公钥匙对象  
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
  
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);  
        signature.update(data);  
  
        // 验证签名是否正常 
        return signature.verify(sign);
    }  
  
    /** 
     * 解密<br> 
     * 用私钥解密 
     *  
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decryptByPrivateKey(byte[] data, byte[] keyBytes)  
            throws Exception {  
        // 取得私钥  
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);  
  
        // 对数据解密  
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
        return cipher.doFinal(data);  
    }  
  
    /** 
     * 解密<br> 
     * 用公钥解密 
     *  
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decryptByPublicKey(byte[] data, byte[] keyBytes)  
            throws Exception {  
        // 取得公钥  
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        Key publicKey = keyFactory.generatePublic(x509KeySpec);  
  
        // 对数据解密  
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, publicKey);  
  
        return cipher.doFinal(data);  
    }  
  
    /** 
     * 加密<br> 
     * 用公钥加密 
     *  
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] encryptByPublicKey(byte[] data, byte[] keyBytes)  
            throws Exception {  
  
        // 取得公钥  
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
  
        // 对数据加密  
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  
        return cipher.doFinal(data);  
    }  
  
    /** 
     * 加密<br> 
     * 用私钥加密 
     *  
     * @param data 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static byte[] encryptByPrivateKey(byte[] data, byte[] keyBytes)  
            throws Exception {  
        // 取得私钥  
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);  
  
        // 对数据加密  
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
  
        return cipher.doFinal(data);  
    }  
  
    /** 
     * 取得私钥 
     *  
     * @param keyMap 
     * @return 
     * @throws Exception 
     */  
    public static byte[] getPrivateKey(Map<String, Object> keyMap)  
            throws Exception {  
        Key key = (Key) keyMap.get(PRIVATE_KEY);  
        return key.getEncoded();  
    }  
  
    /** 
           * 取得公钥 
     *  
     * @param keyMap 
     * @return 
     * @throws Exception 
     */  
    public static byte[] getPublicKey(Map<String, Object> keyMap)  
            throws Exception {  
        Key key = (Key) keyMap.get(PUBLIC_KEY);  
  
        return key.getEncoded();  
    }  
  
    /** 
     * 初始化密钥 
     *  
     * @return 
     * @throws Exception 
     */  
    public static Map<String, Object> initKey() throws Exception {  
        KeyPairGenerator keyPairGen = KeyPairGenerator  
                .getInstance(KEY_ALGORITHM);  
        keyPairGen.initialize(1024);  
  
        KeyPair keyPair = keyPairGen.generateKeyPair();  
  
        // 公钥  
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
  
		// 私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  
  
        Map<String, Object> keyMap = new HashMap<String, Object>(2);  
  
        keyMap.put(PUBLIC_KEY, publicKey);  
        keyMap.put(PRIVATE_KEY, privateKey);  
        return keyMap;
    }  
}

测试RSACoderTest.java

package edu.dongnao.study.balancer.lesson2_security;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Base64;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import edu.dongnao.study.balancer.lesson2_security.algorithm.RSACoder;

/**
 * RSACoderTest
 * 
 */
public class RSACoderTest {
	private byte[] publicKey;
	private byte[] privateKey;
	final Base64.Decoder decoder = Base64.getDecoder();
	final Base64.Encoder encoder = Base64.getEncoder();

	@Before
	public void setUp() throws Exception {
		Map<String, Object> keyMap = RSACoder.initKey();
		publicKey = RSACoder.getPublicKey(keyMap);
		privateKey = RSACoder.getPrivateKey(keyMap);
		System.out.println("获取新的秘钥对,私钥公钥");
	}
	@After
	public void after() {
		System.out.println();
	}

	@Test
	public void test() throws Exception {
		System.out.println("=====================公钥加密——私钥解密=====================");
		System.out.println("公钥:\r" + encoder.encodeToString(publicKey));
		System.out.println("私钥:\r" + encoder.encodeToString(privateKey)+ "\n\r");
		String inputStr = "abc";
		byte[] data = inputStr.getBytes();
		// 客户端用公钥加密数据
		byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);
		// 服务端用私钥解密数据
		byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData, privateKey);
		
		// 解密后的内容
		String outputStr = new String(decodedData);
		System.out.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
		assertEquals(inputStr, outputStr);
		System.out.println("==============私钥加密——公钥解密======================");
		// 客户端用公钥加密数据
		byte[] privateKeyEncodedData = RSACoder.encryptByPrivateKey(data, privateKey);
		// 服务端用私钥解密数据
		byte[] publicKeyDecodedData = RSACoder.decryptByPublicKey(privateKeyEncodedData, publicKey);
		String publicKeyOutputStr = new String(publicKeyDecodedData);
		System.out.println("加密前: " + inputStr + "\n\r" +"解密后: " + publicKeyOutputStr);
	}

	/**
	 * 数字签名验证
	  * <ul>
	 * <li>甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。
	 * <li>甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;
	 * <li>乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。
	 * <li>乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。 
	 * </ul>
	 * @throws Exception
	 */
	@Test
	public void testSign() throws Exception {
		System.out.println("=====================验证数字签名=====================");
		System.out.println("公钥:\r" + encoder.encodeToString(publicKey));
		System.out.println("私钥:\r" + encoder.encodeToString(privateKey)+ "\n\r");
		String inputStr = "sign";
		byte[] data = inputStr.getBytes();
		// 服务端用私钥加密
		byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
		// 客户端用公钥解密
		byte[] decodedData = RSACoder.decryptByPublicKey(encodedData, publicKey);
		String outputStr = new String(decodedData);
		System.out.println("加密前:" + inputStr + "\n\r解密后: " + outputStr+"\r\n");
		assertEquals(inputStr, outputStr);
		System.out.println("私钥签名——公钥验证签名");
		// 产生签名
		byte[] sign = RSACoder.sign(encodedData, privateKey);
		System.out.println("签名:\r\n" + encoder.encodeToString(sign)+"\r\n");
		// 验证签名
		boolean status = RSACoder.verify(encodedData, publicKey, sign);
		System.out.println("签名验证结果:" + status);
	}
}

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
2 评论
0 收藏
0
分享
返回顶部
顶部