常用加密算法笔记

一、对称性加密算法

1.概述

DES(Data Encryption Standard):数字签名算法,速度较快,适用于大量数据加密

3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。

AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高


密钥长度

运算速度

安全性

资源消耗

DES

56位

较快

3DES

112位或168位

AES

128、192、256位


2.java代码的实现

DES:下面这种实现密钥长度要大于8位

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;

public class DESTool {     
    //算法名称/加密模式/填充方式 
    //DES共有四种工作模式-->>ECB:电子密码本模式、CBC:加密分组链接模式、CFB:加密反馈模式、OFB:输出反馈模式
    public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
    /**
     *   
     * 生成密钥key对象
     * @param KeyStr 密钥字符串 
     * @return 密钥对象 
     * @throws InvalidKeyException   
     * @throws NoSuchAlgorithmException   
     * @throws InvalidKeySpecException   
     * @throws Exception 
     */
    private static SecretKey keyGenerator(String keyStr) throws Exception {
        DESKeySpec desKey = new DESKeySpec(keyStr.getBytes());
        //创建一个密匙工厂,然后用它把DESKeySpec转换成
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(desKey);
        return securekey;
    }
	/** 
     * 加密数据
     * @param data 待加密数据
     * @param key 密钥
     * @return 加密后的数据 
     */
    public static String encrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        // 实例化Cipher对象,它用于完成实际的加密操作
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        SecureRandom random = new SecureRandom();
        // 初始化Cipher对象,设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
        byte[] results = cipher.doFinal(data.getBytes());
        // 执行加密操作。加密后的结果通常都会用Base64编码进行传输 
        return Base64.encodeBase64String(results);
    }
    /** 
     * 解密数据 
     * @param data 待解密数据 
     * @param key 密钥 
     * @return 解密后的数据 
     */
    public static String decrypt(String data, String key) throws Exception {
        Key deskey = keyGenerator(key);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //初始化Cipher对象,设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        // 执行解密操作
        return new String(cipher.doFinal(Base64.decodeBase64(data)));
    }    
       
}
AES:

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class AESTool {
	/**
	 * 加密
	 * 
	 * @param content
	 *            需要加密的内容
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static String encrypt(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return Base64.encodeBase64String(result);// 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param content
	 *            待解密内容
	 * @param password
	 *            解密密钥
	 * @return
	 */
	public static String decrypt(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(Base64.decodeBase64(content));
			return new String(result); // 加密
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}	
}


二、非对称加密算法

1.概述

加密密钥和解密密钥不同

RSA:由 RSA 公司发明,是一个支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的;

DSA(Digital Signature Algorithm):数字签名算法,是一种标准的 DSS(数字签名标准);  

 

成熟度

安全性(取决于密钥长度)

运算速度

资源消耗

RSA

DSA

只能用于数字签名


2.java代码的实现

RSA:可用于加密和签名

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;

import org.apache.commons.codec.binary.Base64;

public class RSATool {
	
	public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
	public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥
	
	/**
	 * 初始化密钥
	 * @return
	 * @throws Exception
	 */
	public static Map<String,Key> initKey()throws Exception{
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		keyPairGenerator.initialize(1024);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		//公钥
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		//私钥
		RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
		
		Map<String,Key> keyMap = new HashMap<String,Key>(2);
		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
	}

        /**
	 * 用公钥加密
	 * @param data	加密数据
	 * @param key	密钥
	 * @return
	 * @throws Exception
	 */
	public static String encryptByPublicKey(String data,Key key)throws Exception{
		//取公钥
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定加密算法
		Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
		
		//对数据加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] results =cipher.doFinal(data.getBytes());
		return Base64.encodeBase64String(results);
	}
	
	 
	/**
	 * 用私钥解密 
	 * @param data 	加密数据
	 * @param key	密钥
	 * @return
	 * @throws Exception
	 */
	public static String decryptByPrivateKey(String data,Key key)throws Exception{
		//取私钥
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定加密算法
		Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		
		//对数据解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] results =cipher.doFinal(Base64.decodeBase64(data));
		return new String(results);
	}
	
	/**
	 *用私钥对信息生成数字签名
	 * @param data	原数据
	 * @param privateKey 私钥
	 * @return
	 * @throws Exception
	 */
	public static String sign(String data,Key privateKey)throws Exception{
		//取私钥
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定加密算法
		PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		
		//用私钥对信息生成数字签名
		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initSign(privateKey2);
		signature.update(data.getBytes());
		
		return Base64.encodeBase64String(signature.sign());
	}
	
	/**
	 * 公钥校验数字签名
	 * @param data	加密数据
	 * @param publicKey	公钥
	 * @param sign	数字签名
	 * @return
	 * @throws Exception
	 */
	public static boolean verify(String data,Key publicKey,String sign)throws Exception{
		//取公钥
		X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
		
		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initVerify(publicKey2);
		signature.update(data.getBytes());
		//验证签名是否正常
		return signature.verify(Base64.decodeBase64(sign));
	}
	 
}
DSA:代码跟RSA算法一样,只需把获得算法参数改成DSA.另DSA只能用于签名

三、散列算法

1.概述

这种算法只生成一串不可逆的密文

MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。

SHA-1(Secure Hash Algorithm):安全度相对高;


2.java代码的实现

说明:DM5和SHA-1写法也一样,区别只需改getInstance参数

private static String sha1X16(String data) throws Exception{
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.reset();
			md.update(data.getBytes("utf-8"));
			byte[] bytes =md.digest();
			//转16进制
			StringBuilder sha1StrBuff = new StringBuilder();
			for (int i = 0; i < bytes.length; ++i){
				if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
					sha1StrBuff.append("0").append(
							Integer.toHexString(0xFF & bytes[i]));
				} else
					sha1StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
			}		 
			return sha1StrBuff.toString().toLowerCase();
		} catch (Exception e) {
			throw e;
		}
	}


四、密钥证书

1、常见证书格式

.pfx/.p12  PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式。

.cer/.crt是用于存放证书,它是DER 编码(ASCII)的2进制形式存放的,不含私钥。

.pem是用于存放证书,它是BASE64 编码的2进制形式存放的,不含私钥。

2、java代码实现

.pfx格式:获得公钥和私钥

import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Enumeration;

public class CerTool {
	public static final String KEYSTORE_FILE = "D:/test.pfx";
	public static final String KEYSTORE_PASSWORD = "111111";

	public static void main(String[] args) {
		FileInputStream fis = null;
		try {
			// 获得KeyStore
			KeyStore ks = KeyStore.getInstance("PKCS12");
			fis = new FileInputStream(KEYSTORE_FILE);
			char[] nPassword = KEYSTORE_PASSWORD.toCharArray();
			ks.load(fis, nPassword);

			// 根据条目获得私钥
			Enumeration aliasenum = ks.aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = (String) aliasenum.nextElement();
			}
			PrivateKey priKey = (PrivateKey) ks.getKey(keyAlias,
					KEYSTORE_PASSWORD.toCharArray());

			// 根据条目获得公钥
			Certificate cert = ks.getCertificate(keyAlias);
			PublicKey pubkey = cert.getPublicKey();
			
			//使用RSA测试
			String content="hello";
			String en=RSATool.encryptByPublicKey(content,pubkey);
			System.out.println(en);
			System.out.println(RSATool.decryptByPrivateKey(en,priKey));
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fis != null) {
					fis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
.cer格式:获得公钥
public PublicKey getPublic() {
		InputStream in = null;
		try {
			//引用于java.security.cert
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			in = new FileInputStream("D:/test.cer");
			X509Certificate verifyCert = (X509Certificate) cf
					.generateCertificate(in);
			PublicKey publicKey = verifyCert.getPublicKey();
			return publicKey;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}


五、算法的选择

由于非对称加密算法的运行速度比对称加密算法的速度慢很多,当我们需要加密大量的数据时,建议采用对称加密算法,提高加解密速度。

对称加密算法不能实现签名,因此签名只能非对称算法。

由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。

在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。

那采用多少位的密钥呢? RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。

ps:数字签名和加密的区别

数字签名的作用一是保证数据的完整性,二是对发送者进行身份认证。所以它是采用非对称算法,消息发送者使用私钥加密,接收者使用公钥解密验签;

加密重点在于“数据的安全性”,可以防止数据被监听攻击。所以消息发送者采用公钥加密,只有拥有私钥的接收者才能解密;



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值