1、加密概述:
加密就是是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使以获得了加密的信息,但因不知解密方式,仍无法了解信息的内容。大体上又分为双向加密和单向加密。
2、单项加密
2.1、概述:
单向加密又称为不可逆加密算法,在加密过程中不使用密钥,明文由系统加密成密文,密文无法破解,一般都是采用验证的方式,具体是:在验证过程中,重新输入明文,并经过同样的加密算法后,得到相同的密文。单向加密广泛用于口令加密。
2.2、特点:
(1)对同一消息反复执行加密得到相同的密文;
(2)加密算法生成密文不可预见;
(3)不可逆,一般不能通过密文获取明文
2.3、类别
2.3.1、MD5加密
2.3.1.1、概述:
MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。
MD5用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。
MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
2.3.1.2、算法原理:
对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。
2.3.1.3、java代码中使用MD5加密
/**
* md5计算.
*
* @param datas
* 待计算的数据
* @return 计算结果
*/
public static byte[] md5(byte[] datas) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
md.reset();
md.update(datas);
return md.digest();
} catch (Exception e) {
log.error("MD5计算失败", e);
return null;
}
}
2.3.2、SHA加密
2.3.2.1、概述
其思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)的密文。可以简单的理解为取一串输入码(称为预映射或信息),并把他们转化为长度较短、位数固定的输出序列的过程。
安全散列算法SHA(Secure Hash Algorithm,SHA)是美国国家标准技术研究所发布的国家标准FIPS PUB 180,最新的标准已经于2008年更新到FIPS PUB 180-3。其中规定了SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512这几种单向散列算法。SHA-1,SHA-224和SHA-256适用于长度不超过2^64二进制位的消息。SHA-384和SHA-512适用于长度不超过2^128二进制位的消息。
2.3.2.2、原理
SHA-1是一种数据加密算法,该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。
单向散列函数的安全性在于其产生散列值的操作过程具有较强的单向性。如果在输入序列中嵌入密码,那么任何人在不知道密码的情况下都不能产生正确的散列值,从而保证了其安全性。SHA将输入流按照每块512位(64个字节)进行分块,并产生20个字节的被称为信息认证代码或信息摘要的输出。
该算法输入报文的长度不限,产生的输出是一个160位的报文摘要。输入是按512 位的分组进行处理的。SHA-1是不可逆的、防冲突,并具有良好的雪崩效应。
通过散列算法可实现数字签名实现,数字签名的原理是将要传送的明文通过一种函数运算(Hash)转换成报文摘要(不同的明文对应不同的报文摘要),报文摘要加密后与明文一起传送给接受方,接受方将接受的明文产生新的报文摘要与发送方的发来报文摘要解密比较,比较结果一致表示明文未被改动,如果不一致表示明文已被篡改。
MAC (信息认证代码)就是一个散列结果,其中部分输入信息是密码,只有知道这个密码的参与者才能再次计算和验证MAC码的合法性。
2.3.2.3、java中的SHA实现
/**
* SHA1签名
* @param paramStr 要加签的字符串
* @return
*/
public static String SHA1(String paramStr) {
MessageDigest alg;
String result = "";
String tmp = "";
try {
alg = MessageDigest.getInstance("SHA-1");
alg.update(paramStr.getBytes());
byte[] bts = alg.digest(); for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1)
result += "0";
result += tmp;
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return result;
}
2.4、SHA与MD5的区别:
(1)对强行攻击的安全性:最显著和最重要的区别是:SHA-1的摘要比MD5的摘要长32位。使用强行技术,产生任何一个报文使其摘要等于给定摘要的难度对MD5是是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
(2)对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1不易受这样的攻击。
3、双向加密
3.1概述
大体意思是明文加密后形成密文,可以通过算法还原成明文。
3.2分类
3.2.1对称加密
3.2.1.1概述
对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
3.2.1.2特点
优点:
(1)算法公开,计算量小、加密速度快、加密效率高
缺点:
(1)交易双方都使用同样的密钥,安全性得不到保证
(2)每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一密钥,这会使得发收信双方所拥有的钥匙数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。
3.2.1.3常用对称加密算法
基于“对称密钥”的加密算法比较常用的主要有:DES 、 3DES 、AES
(1)DES
概述:
DES算法全称为Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。
算法原理:
DES算法的入口参数有三个:Key、Data、Mode。
(1)Key为8个字节共64位,是DES算法的工作密钥;
(2)Data也为8个字节64位,是要被加密或被解密的数据;
(3)Mode为DES的工作方式,有两种:加密或解密。
链接:https://www.zhihu.com/question/36767829/answer/68911532
算法应用:
java代码实现:
/**
* 3DES加密
*
* @param key
* 密钥信息
* @param content
* 待加密信息
* @return
* @throws Exception
*/
public static byte[] encode3DES(byte[] key, byte[] content) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// 不是8的倍数的,补足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 长度为16位,转换成24位的密钥
if (key.length == 16) {
byte[] temp = new byte[24];
System.arraycopy(key, 0, temp, 0, key.length);
System.arraycopy(key, 0, temp, key.length, temp.length - key.length);
key = temp;
} // 不是8的倍数的,补足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} SecretKey deskey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] temp = cipher.doFinal(srcBytes);
byte[] tgtBytes = new byte[content.length];
System.arraycopy(temp, 0, tgtBytes, 0, tgtBytes.length);
return tgtBytes;
} /**
* 3DES解密
*
* @param key
* 密钥
* @param content
* 待解密信息
* @return
* @throws Exception
*/
public static byte[] decode3DES(byte[] key, byte[] content) throws Exception {
// 不是8的倍数的,补足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 长度为16位,转换成24位的密钥
if (key.length == 16) {
byte[] temp = new byte[24];
System.arraycopy(key, 0, temp, 0, key.length);
System.arraycopy(key, 0, temp, key.length, temp.length - key.length);
key = temp;
} // 不是8的倍数的,补足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} SecretKey deskey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, deskey);
byte[] tgtBytes = cipher.doFinal(srcBytes);
return tgtBytes;
} /**
* DES加密
*
* @param key
* 密钥信息
* @param content
* 待加密信息
* @return
* @throws Exception
*/
public static byte[] encodeDES(byte[] key, byte[] content) throws Exception {
// 不是8的倍数的,补足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
} // 不是8的倍数的,补足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv, sr);
byte[] tgtBytes = cipher.doFinal(srcBytes);
return tgtBytes;
} /**
* DES解密
*
* @param key
* 密钥信息
* @param content
* 待加密信息
* @return
* @throws Exception
*/
public static byte[] decodeDES(byte[] key, byte[] content) throws Exception {
// 不是8的倍数的,补足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 不是8的倍数的,补足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv, sr);
byte[] tgtBytes = cipher.doFinal(content);
return tgtBytes;
}
(2)3DES
概述:
3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。
算法原理:
package cn.mars.app.txn.bjyl; import java.security.Key;
import java.security.Security; import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec; /**
* 3DES加密
*
* @version 1.0
* @author
*
*/
public class DesUtil { /**
* 密钥算法
*/
public static final String KEY_ALGORITHM = "DESede";
public static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
private static String strDefaultKey = "national";
private Cipher encryptCipher = null;
private Cipher decryptCipher = null; public DesUtil() throws Exception {
this(strDefaultKey);
} public static String byteArr2HexStr(byte[] arrB) throws Exception {
int iLen = arrB.length;
StringBuffer sb = new StringBuffer(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
while (intTmp < 0) {
intTmp = intTmp + 256;
}
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
} public static byte[] hexStr2ByteArr(String strIn) throws Exception {
byte[] arrB = strIn.getBytes();
int iLen = arrB.length;
byte[] arrOut = new byte[iLen / 2];
for (int i = 0; i < iLen; i = i + 2) {
String strTmp = new String(arrB, i, 2);
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
}
return arrOut;
}
/**
* @param strKey
* @throws Exception
*/
public DesUtil(String strKey) throws Exception {
Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(StringUtil.hexStringToByteArray(strKey));
encryptCipher = Cipher.getInstance("DES/ECB/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
decryptCipher = Cipher.getInstance("DES/ECB/NoPadding");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
} public byte[] encrypt(byte[] arrB) throws Exception {
return encryptCipher.doFinal(arrB);
} public String encrypt(String strIn) throws Exception {
return byteArr2HexStr(encrypt(strIn.getBytes()));
} public byte[] decrypt(byte[] arrB) throws Exception {
return decryptCipher.doFinal(arrB);
} public String decrypt(String strIn) throws Exception {
return new String(decrypt(hexStr2ByteArr(strIn)));
} private Key getKey(byte[] arrBTmp) throws Exception {
byte[] arrB = new byte[8];
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
arrB[i] = arrBTmp[i];
}
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
return key;
} public static String printbytes(String tip, byte[] b) {
String ret = "";
String str;
System.out.println(tip);
for (int i = 0; i < b.length; i++) {
str = Integer.toHexString((int) (b[i] & 0xff));
if (str.length() == 1)
str = "0" + str;
System.out.print(str + " ");
ret = ret + str + " ";
}
return ret;
}
/**
* 加密
* @param data
* @param key
* @return
* @throws Exception
* @author yangxing
* 2014-7-22
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
Key k = toKey(key);// 还原密钥
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* 解密
*
* @param data 待解密数据
* @param key 密钥
* @return byte[] 解密数据
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 转换密钥
* @param key 二进制密钥
* @return key 密钥
*/
public static Key toKey(byte[] key) throws Exception {
DESedeKeySpec dks = new DESedeKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generateSecret(dks);
} public static void main(String[] args) {
try {
byte[] data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 };
DesUtil des1 = new DesUtil("498F456AC9D9CBA0");
printbytes("data", des1.encrypt(data));
} catch (Exception e) {
e.printStackTrace();
}
}
}
(3)AES
java代码实现:
package cn.mars.app.txn.wanglian; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import cfca.util.Base64; /**
* java实现AES256加密解密
* @author xiaoqiang
*
*/ public class AES256Util { public static byte[] encrypt(String content, String password) {
try {
// "AES":请求的密钥算法的标准名称
KeyGenerator kgen = KeyGenerator.getInstance("AES");
// 256:密钥生成参数;securerandom:密钥生成器的随机源
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(256, securerandom);
// 生成秘密(对称)密钥
SecretKey secretKey = kgen.generateKey();
// 返回基本编码格式的密钥
byte[] enCodeFormat = secretKey.getEncoded();
// 根据给定的字节数组构造一个密钥。enCodeFormat:密钥内容;"AES":与给定的密钥内容相关联的密钥算法的名称
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
// 将提供程序添加到下一个可用位置
Security.addProvider(new BouncyCastleProvider());
// 创建一个实现指定转换的 Cipher对象,该转换由指定的提供程序提供。
// "AES/ECB/PKCS7Padding":转换的名称;"BC":提供程序的名称
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
byte[] cryptograph = cipher.doFinal(byteContent);
byte[] encode = Base64.encode(cryptograph); return encode;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static String decrypt(byte[] cryptograph, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(256, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, key);
byte[] content = cipher.doFinal(Base64.decode(cryptograph));
return new String(content);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
} /*
* private static byte[] parseHexStr2Byte(String hexStr) { if
* (hexStr.length() < 1) return null; byte[] result = new
* byte[hexStr.length()/2]; for (int i = 0;i< hexStr.length()/2; i++) { int
* high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16); int low =
* Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16); result[i] = (byte)
* (high * 16 + low); } return result; }
*/ private static byte[] tohash256Deal(String datastr) {
try {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(datastr.getBytes());
byte[] hex = digester.digest();
return hex;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
}
} /**
* 生成随机密钥
*
* @param size
* 位数
* @return
*/
public static String generateRandomKey(int size) {
StringBuilder key = new StringBuilder();
String chars = "0123456789ABCDEF";
for (int i = 0; i < size; i++) {
int index = (int) (Math.random() * (chars.length() - 1));
key.append(chars.charAt(index));
}
return key.toString();
} public static void main(String[] args) { String content = "123456";
String password = generateRandomKey(32);
System.out.println("明文:" + content);
System.out.println("key:" + password); byte[] encryptResult = AES256Util.encrypt(content, password);
System.out.println(encryptResult);
System.out.println("密文:" + AES256Util.parseByte2HexStr(encryptResult)); String decryptResult = AES256Util.decrypt(encryptResult, password);
System.out.println("解密:" + decryptResult);
}
}
3.2.2非对称加密
3.2.2.1概述
package cn.mars.app.txn.zjyl; import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
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工具类
*
* @author ThinkPad
*
*/
public abstract class RsaUtils {
/**
* 生成公钥私钥对,使用默认模长1024。
*
* @return Object[] : 0:公钥( RSAPublicKey ),1:私钥( RSAPrivateKey )
*/ private static final int DEFAULT_KEY_LEN = 2048; public static Map<String, String> genKeyPair() {
return genKeyPair(DEFAULT_KEY_LEN); } /**
* 指定模长生成公私钥对
*
* @param modulus
* @return
*/
public static Map<String, String> genKeyPair(int modulus) {
KeyPairGenerator keyPairGen;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(modulus);
KeyPair keyPair = keyPairGen.generateKeyPair(); Map<String, String> keyMaps = new HashMap<String, String>();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
keyMaps.put("publicKey", new String(Base64.encode(publicKey.getEncoded())));
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
keyMaps.put("privateKey", new String(Base64.encode(privateKey.getEncoded()))); return keyMaps;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
} /**
* 公钥加密
*
* @param publicKeyBytes
* @param data
* @param modulus
* 公钥模长,范围512-2048。
* @return
*/
public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data, int modulus) {
try {
// RSA最大加密明文大小
int maxEncryptBlock = modulus / 8 - 11; X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxEncryptBlock) {
cache = cipher.doFinal(data, offSet, maxEncryptBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxEncryptBlock;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
} } /**
* 公钥加密,密钥模长使用默认长度1024。
*
* @param publicKeyBytes
* 公钥RSAPublicKey getEncoded()
* @param data
* 要加密的字节数组
*/
public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data) {
return encryptByPublicKey(publicKeyBytes, data, DEFAULT_KEY_LEN);
} /**
* 公钥解密
*
* @param publicKeyBytes
* 公钥RSAPublicKey getEncoded()
* @param encryptedData
* 被(私钥)加密过的字节数组
* @param modulus
* 模长,范围512-2048
* @return
*/
public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData, int modulus) {
// RSA最大解密密文大小
int maxDecryptBlock = modulus / 8;
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxDecryptBlock) {
cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxDecryptBlock;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 公钥解密,默认模长1024
*
* @param publicKeyBytes
* 公钥RSAPublicKey getEncoded()
* @param encryptedData
* 被(私钥)加密过的字节数组
*/
public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData) {
return decryptByPublicKey(publicKeyBytes, encryptedData, DEFAULT_KEY_LEN);
} /**
* 私钥加密
*
* @param privateKeyBytes
* 私钥RSAPrivateKey getEncoded()
* @param data
* 要加密的字节数组
* @param modulus
* 模长,范围512-2048。
*/
public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data, int modulus) {
try {
// RSA最大加密明文大小
int maxEncryptBlock = modulus / 8 - 11; PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxEncryptBlock) {
cache = cipher.doFinal(data, offSet, maxEncryptBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxEncryptBlock;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 私钥加密,默认模长1024。
*
* @param privateKeyBytes
* 私钥RSAPrivateKey getEncoded()
* @param data
* 要加密的字节数组
*/
public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data) {
return encryptByPrivateKey(privateKeyBytes, data, DEFAULT_KEY_LEN);
} /**
* 私钥解密
*
* @param privateKeyBytes
* 私钥RSAPrivateKey getEncoded()
* @param encryptedData
* 被(公钥)加密过的字节数组
* @param modulus
* 模长,范围512-2048
*/
public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData, int modulus) {
try {
// RSA最大解密密文大小
int maxDecryptBlock = modulus / 8; PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxDecryptBlock) {
cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxDecryptBlock;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 私钥解密,默认模长1024。
*
* @param privateKeyBytes
* 私钥RSAPrivateKey getEncoded()
* @param encryptedData
* 被(公钥)加密过的字节数组
*/
public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData) {
return decryptByPrivateKey(privateKeyBytes, encryptedData, DEFAULT_KEY_LEN);
} public static void main(String[] args) {
genKeyPair();
}
}
此文只是简单介绍了java常用的加减密算法,之后文章会对每种算法做具体说明。