3) RSA
RSA 是一种非对称加解密算法。
RSA is named from the initials of the authors, Ron Rivest, Adi Shamir, and
Leonard Adleman,who first published the algorithm.
RSA 与 DSA 都是非对称加密算法。其中RSA的安全性是基于极其困难的大整数的分解(两个素数的乘积);DSA 的安全性
是基于整数有限域离散对数难题。基本上可以认为相同密钥长度的 RSA 算法与 DSA 算法安全性相当。
公钥用于加密,它是向所有人公开的;私钥用于解密,只有密文的接收者持有。
适用OPENSSL 适用RSA 的命令如下:
生成一个密钥(私钥)
[root@hunterfu ~]# openssl genrsa -out private.key 1024
注意: 需要注意的是这个文件包含了公钥和密钥两部分,也就是说这个文件即可用来加密也可以用来解密,后面的1024是生成
密钥的长度.
通过密钥文件private.key 提取公钥
[root@hunterfu ~]# openssl rsa -in private.key -pubout -out pub.key
使用公钥加密信息
[root@hunterfu ~]# echo -n "123456" | openssl rsautl -encrypt -inkey pub.key -pubin >encode.result
使用私钥解密信息
[root@hunterfu ~]#cat encode.result | openssl rsautl -decrypt -inkey private.key
123456
package com.007.common;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
/**
*
* @author 007
* @date Jan 26, 2015 4:27:10 PM
* @version V1.0
* @Description: TODO(Rsa加密)
*
*/
public class RSAMain {
private static Logger _log = Logger.getLogger(RSAMain.class);
private PublicKey pubKey = null;
private PrivateKey priKey = null;
private static RSAMain rsaMain;
/**
* 加密长度 用4096 做的key,选500 和选400分段长度 机密后的密文长度也有很大差距 选大的加密后密文短
*
*
* 1024:加密分段长度选100 解密长度选128
* 4096:加密分段长度选500 解密长度选512
*
*
*/
private RSAMain() {
String keyinfo = "**"; //密钥信息用 BASE64 编码加密过,需要先解密
String key4096 = "**";
initRSAKEY(key4096);
// String privateKeyPath="";
// initRSAKEY(new File(privateKeyPath));
}
public static RSAMain getInstance() {
if (rsaMain == null) {
rsaMain = new RSAMain();
}
_log.debug("getInstance rsaMain is " + rsaMain == null ? "null!" : "not null!");
return rsaMain;
}
public String encryptAndBase64(String str) {
return Base64.encode(encrypt(str));
}
public String base64AndDencrypt(String str) throws Base64DecodingException {
return Dencrypt(Base64.decode(str));
}
/**
* 加密成二进制
*
* @param str
* @return
*/
public byte[] encrypt(String str) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] data = new String(str).getBytes();
byte[] enBytes = null;
for (int i = 0; i < data.length; i += 500) { // 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + 500));
enBytes = ArrayUtils.addAll(enBytes, doFinal);
}
return enBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解密二进制
*
* @param encrypted
* @return
*/
public String Dencrypt(byte[] encrypted) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < encrypted.length; i += 512) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(encrypted, i, i + 512));
sb.append(new String(doFinal));
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void initRSAKEY(String keyinfo) {
byte[] decodeKeyinfo;
try {
decodeKeyinfo = (new BASE64Decoder()).decodeBuffer(keyinfo);
DerInputStream dis = new DerInputStream(decodeKeyinfo); //密钥不含 otherPrimeInfos 信息,故只有 9 段
DerValue[] ders = dis.getSequence(9); //依次读取 RSA 因子信息
int version = ders[0].getBigInteger().intValue();
BigInteger modulus = ders[1].getBigInteger();
BigInteger publicExponentb = ders[2].getBigInteger();
BigInteger privateExponentb = ders[3].getBigInteger();
BigInteger primeP = ders[4].getBigInteger();
BigInteger primeQ = ders[5].getBigInteger();
BigInteger primeExponentP = ders[6].getBigInteger();
BigInteger primeExponentQ = ders[7].getBigInteger();
BigInteger crtCoefficient = ders[8].getBigInteger();
//generate public key and private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponentb);
PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
RSAPrivateCrtKeySpec rsaPrivateKeySpec = new RSAPrivateCrtKeySpec(modulus, publicExponentb, privateExponentb, primeP, primeQ,
primeExponentP, primeExponentQ, crtCoefficient);
PrivateKey privateKey = keyFactory.generatePrivate(rsaPrivateKeySpec);
pubKey = publicKey;
priKey = privateKey;
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
private void initRSAKEY(File file) {
// File file = new File("F:/工作任务/19IM群/private.key");
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String keyinfo = "";
String line = null; //去掉文件头尾的注释信息
while ((line = br.readLine()) != null) {
if (line.indexOf("---") == -1) {
keyinfo += line;
}
}
byte[] decodeKeyinfo = (new BASE64Decoder()).decodeBuffer(keyinfo); //使用 DerInputStream 读取密钥信息
DerInputStream dis = new DerInputStream(decodeKeyinfo); //密钥不含 otherPrimeInfos 信息,故只有 9 段
DerValue[] ders = dis.getSequence(9); //依次读取 RSA 因子信息
int version = ders[0].getBigInteger().intValue();
BigInteger modulus = ders[1].getBigInteger();
BigInteger publicExponentb = ders[2].getBigInteger();
BigInteger privateExponentb = ders[3].getBigInteger();
BigInteger primeP = ders[4].getBigInteger();
BigInteger primeQ = ders[5].getBigInteger();
BigInteger primeExponentP = ders[6].getBigInteger();
BigInteger primeExponentQ = ders[7].getBigInteger();
BigInteger crtCoefficient = ders[8].getBigInteger();
//generate public key and private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, publicExponentb);
PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
RSAPrivateCrtKeySpec rsaPrivateKeySpec = new RSAPrivateCrtKeySpec(modulus, publicExponentb, privateExponentb, primeP, primeQ,
primeExponentP, primeExponentQ, crtCoefficient);
PrivateKey privateKey = keyFactory.generatePrivate(rsaPrivateKeySpec);
// publicModule = modulus.toString();
// publicExponent = publicExponentb.toString();
// priviteExponent = privateExponentb.toString();
pubKey = publicKey;
priKey = privateKey;
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
}
/**
* @param args
* @throws Base64DecodingException
* @throws IOException
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
public static void main(String[] args) throws Base64DecodingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException {
System.out.println("start...");
RSAMain rsaMain = RSAMain.getInstance();
String teststr = "计算机<root><f><fn>>微软雅黑</fn><fs>10</fs><fe>0</fe><fc>0</fc></f><c><t>1</t><txt><![CDATA[\r"
+ "]]></txt></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><t>1</t><txt><![CDATA[\r"
+ "]]></txt></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><t>1</t><txt><![CDATA[\r"
+ "]]></txt></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c><c><id>1.0.86.gif</id><t>2</t></c></root>\r";
long s = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
String miwen = rsaMain.encryptAndBase64(teststr);
//System.out.println("miwen=" + miwen);
//System.out.println(rsaMain.base64AndDencrypt(miwen));
}
System.out.println(teststr.length());
System.out.println((System.currentTimeMillis() - s));
}
}