常用加密算法笔记

来源:互联网 发布:阿里云个人邮箱下载 编辑:程序博客网 时间:2024/06/05 06:18

一、对称性加密算法

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]));} elsesha1StrBuff.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 {// 获得KeyStoreKeyStore 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.certCertificateFactory 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 0