java-RSA加密解密,支持分段加解密
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
n:密钥长度,n是两个大质数p、q的积,它的二进制数位数,就是所谓的密钥长度。
e1:(n,e1)为公钥;
e2:(n,e2)为私钥
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n,e1),(n,e2)就是密钥对。其中(n,e1)为公钥,(n,e2)为私钥。
一、支持密钥对生成、分段加密的帮助类
二、测试分段加密;公钥加密私钥解密;私钥机密公钥解密;
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
n:密钥长度,n是两个大质数p、q的积,它的二进制数位数,就是所谓的密钥长度。
e1:(n,e1)为公钥;
e2:(n,e2)为私钥
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n,e1),(n,e2)就是密钥对。其中(n,e1)为公钥,(n,e2)为私钥。
一、支持密钥对生成、分段加密的帮助类
package me.grass.secret;
import java.io.ByteArrayOutputStream;
/**
*
* @author xxj
*/
public class RsaHelper {
/**
* 生成公钥、私钥对(keysize=1024)
* @param keySize
* @return
*/
public RsaHelper.KeyPairInfo getKeyPair() {
return getKeyPair(1024);
}
/**
* 生成公钥、私钥对
* @param keySize
* @return
*/
public RsaHelper.KeyPairInfo getKeyPair(int keySize) {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小一般要大于1024位,
// String aa=String.valueOf(new Random().nextInt(999999999));
// SecureRandom random = new SecureRandom(aa.getBytes()); //?????
// keyPairGen.initialize(keySize,random);
keyPairGen.initialize(keySize);
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey oraprivateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey orapublicKey = (RSAPublicKey) keyPair.getPublic();
RsaHelper.KeyPairInfo pairInfo = new RsaHelper.KeyPairInfo(keySize);
//公钥
byte[] publicKeybyte = orapublicKey.getEncoded();
String publicKeyString = Base64.encodeBase64String(publicKeybyte);
pairInfo.setPublicKey(publicKeyString);
//私钥
byte[] privateKeybyte = oraprivateKey.getEncoded();
String privateKeyString = Base64.encodeBase64String(privateKeybyte);
pairInfo.setPrivateKey(privateKeyString);
return pairInfo;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* 获取公钥对象
* @param publicKeyBase64
* @return
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
public PublicKey getPublicKey(String publicKeyBase64)
throws InvalidKeySpecException,NoSuchAlgorithmException{
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicpkcs8KeySpec =
new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec);
return publicKey;
}
/**
* 获取私钥对象
* @param privateKeyBase64
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public PrivateKey getPrivateKey(String privateKeyBase64)
throws NoSuchAlgorithmException, InvalidKeySpecException{
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privatekcs8KeySpec =
new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));
PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec);
return privateKey;
}
/**
* 使用共钥加密
* @param content 待加密内容
* @param publicKeyBase64 公钥 base64 编码
* @return 经过 base64 编码后的字符串
*/
public String encipher(String content,String publicKeyBase64){
return encipher(content,publicKeyBase64,-1);
}
/**
* 使用共钥加密(分段加密)
* @param content 待加密内容
* @param publicKeyBase64 公钥 base64 编码
* @param segmentSize分段大小,一般小于 keySize/8(段小于等于0时,将不使用分段加密)
* @return 经过 base64 编码后的字符串
*/
public String encipher(String content,String publicKeyBase64,int segmentSize){
try {
PublicKey publicKey = getPublicKey(publicKeyBase64);
return encipher(content,publicKey,segmentSize);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段加密
* @param ciphertext 密文
* @param key 加密秘钥
* @param segmentSize 分段大小,<=0 不分段
* @return
*/
public String encipher(String ciphertext,java.security.Key key,int segmentSize){
try {
// 用公钥加密
byte[] srcBytes = ciphertext.getBytes();
// Cipher负责完成加密或解密工作,基于RSA
Cipher cipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] resultBytes = null;
if(segmentSize>0)
resultBytes = cipherDoFinal(cipher,srcBytes,segmentSize); //分段加密
else
resultBytes = cipher.doFinal(srcBytes);
String base64Str = Base64.encodeBase64String(resultBytes);
return base64Str;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段大小
* @param cipher
* @param srcBytes
* @param segmentSize
* @return
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws IOException
*/
private byte[] cipherDoFinal(Cipher cipher,byte[] srcBytes,int segmentSize)
throws IllegalBlockSizeException, BadPaddingException, IOException{
if(segmentSize<=0)
throw new RuntimeException("分段大小必须大于0");
ByteArrayOutputStream out = new ByteArrayOutputStream();
int inputLen = srcBytes.length;
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > segmentSize) {
cache = cipher.doFinal(srcBytes, offSet, segmentSize);
} else {
cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * segmentSize;
}
byte[] data = out.toByteArray();
out.close();
return data;
}
/**
* 使用私钥解密
* @param contentBase64 待加密内容,base64 编码
* @param privateKeyBase64 私钥 base64 编码
* @segmentSize 分段大小
* @return
*/
public String decipher(String contentBase64,String privateKeyBase64){
return decipher(contentBase64, privateKeyBase64,-1);
}
/**
* 使用私钥解密(分段解密)
* @param contentBase64 待加密内容,base64 编码
* @param privateKeyBase64 私钥 base64 编码
* @segmentSize 分段大小
* @return
*/
public String decipher(String contentBase64,String privateKeyBase64,int segmentSize){
try {
PrivateKey privateKey = getPrivateKey(privateKeyBase64);
return decipher(contentBase64, privateKey,segmentSize);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 分段解密
* @param contentBase64 密文
* @param key 解密秘钥
* @param segmentSize 分段大小(小于等于0不分段)
* @return
*/
public String decipher(String contentBase64,java.security.Key key,int segmentSize){
try {
// 用私钥解密
byte[] srcBytes = Base64.decodeBase64(contentBase64);
// Cipher负责完成加密或解密工作,基于RSA
Cipher deCipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
deCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decBytes = null;//deCipher.doFinal(srcBytes);
if(segmentSize>0)
decBytes = cipherDoFinal(deCipher,srcBytes,segmentSize); //分段加密
else
decBytes = deCipher.doFinal(srcBytes);
String decrytStr=new String(decBytes);
return decrytStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 秘钥对
*
*/
public class KeyPairInfo{
public KeyPairInfo(int keySize){
setKeySize(keySize);
}
public KeyPairInfo(String publicKey,String privateKey){
setPrivateKey(privateKey);
setPublicKey(publicKey);
}
String privateKey;
String publicKey;
int keySize=0;
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public void setPublicKey(String publicKey) {
this.publicKey = publicKey;
}
public int getKeySize() {
return keySize;
}
public void setKeySize(int keySize) {
this.keySize = keySize;
}
}
}
二、测试分段加密;公钥加密私钥解密;私钥机密公钥解密;
package me.grass.secret;
import static org.junit.Assert.assertTrue;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import org.junit.Test;
import me.grass.coder.Debug;
/**
*
* @author xxj
*/
public class RsaHelperTest {
/**
* 获取秘钥对
*
*/
@Test
public void getKeyPairTest() {
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024);
assertTrue(info!=null);
Debug.printFormat("公钥:{0}", info.getPublicKey());
Debug.printFormat("私钥:{0}", info.getPrivateKey());
}
/**
* rsa 不分段加密,使用莫值为1024 时y,明文不能超过 117
*
*/
@Test
public void encipherTest() {
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
assertTrue(info!=null);
Debug.printFormat("公钥:{0}", info.getPublicKey());
Debug.printFormat("私钥:{0}", info.getPrivateKey());
String content="rsa加密、解密测试";
Debug.printFormat("明文:{0}", content);
String ciphertext = rsa.encipher(content, info.getPublicKey());
Debug.printFormat("密文:{0}", ciphertext);
String deTxt = rsa.decipher(ciphertext, info.getPrivateKey());
Debug.printFormat("解密:{0}", deTxt);
assertTrue(content.equals(deTxt));
}
/**
* rsa 分段机密测试(长内容加密)
*
*/
@Test
public void encipherSegmentTest() {
int keySize=2048;
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(keySize); //每次调用的公钥 私钥都一样
assertTrue(info!=null);
Debug.printFormat("公钥:{0}", info.getPublicKey());
Debug.printFormat("私钥:{0}", info.getPrivateKey());
String content="1.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "2.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "3.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "4.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "5.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "6.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "7.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "8.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "9.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
+ "0.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n";
Debug.printFormat("明文:{0}", content);
int enSegmentSize=245;//keysize=1024时,分段不能大于117 ;keysize>=2048时,分段不能大于keySize/8+128;
String ciphertext = rsa.encipher(content, info.getPublicKey(),enSegmentSize);
Debug.printFormat("密文:{0}", ciphertext);
int deSegmentSize=256;//等于keySize/8
String deTxt = rsa.decipher(ciphertext, info.getPrivateKey(),deSegmentSize);
Debug.printFormat("解密:{0}", deTxt);
assertTrue(content.equals(deTxt));
}
/**
* 测试公钥加密、私钥解密
*
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
@Test
public void encipherUsePublic()
throws InvalidKeySpecException, NoSuchAlgorithmException{
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
assertTrue(info!=null);
Debug.printFormat("公钥:{0}", info.getPublicKey());
Debug.printFormat("私钥:{0}", info.getPrivateKey());
String content="rsa加密、解密测试";
Debug.printFormat("明文:{0}", content);
PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
String ciphertext = rsa.encipher(content, pubKey,0);
Debug.printFormat("密文:{0}", ciphertext);
PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
String deTxt = rsa.decipher(ciphertext,privKey,0);
Debug.printFormat("解密:{0}", deTxt);
assertTrue(content.equals(deTxt));
}
/**
* 测试公钥加密、私钥解密
*
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
@Test
public void encipherUsePrivateKey()
throws InvalidKeySpecException, NoSuchAlgorithmException{
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
assertTrue(info!=null);
Debug.printFormat("公钥:{0}", info.getPublicKey());
Debug.printFormat("私钥:{0}", info.getPrivateKey());
String content="rsa加密、解密测试";
Debug.printFormat("明文:{0}", content);
PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
String ciphertext = rsa.encipher(content, privKey,0);
Debug.printFormat("密文:{0}", ciphertext);
PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
String deTxt = rsa.decipher(ciphertext,pubKey,0);
Debug.printFormat("解密:{0}", deTxt);
assertTrue(content.equals(deTxt));
}
}