RSA非对称加密
2021-08-10 本文已影响0人
霁逸lei
1.简介
对称加密: 加密和解密的秘钥使用的是同一个。算法公开、计算量小、加密速度快、加密效率高。AES、DES、3DES
非对称加密: 与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。一般用公钥加密私钥解密,当然反过来用也一样。安全但速度慢。RSA、DSA(数字签名用)
2.RSA代码
/**
* 非对称加密
* @param content
*/
public void rsaEncryption(String content) {
try {
//1,获取cipher 对象
Cipher cipher = Cipher.getInstance("RSA");
//2,通过秘钥对生成器KeyPairGenerator 生成公钥和私钥
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
//使用公钥进行加密,私钥进行解密(也可以反过来使用)
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
byte[] publicEncoded = privateKey.getEncoded();
String strPublicEncoded = Base64.encodeToString(publicEncoded, Base64.DEFAULT);
PrivateKey privateKey1 = getPrivateKey(strPublicEncoded);
Log.d("TEST", "privateKey = " + strPublicEncoded);
//解密
//3.使用私钥初始化密码器
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//4.执行解密操作 (如果要转成String,一定要用Base64转换,否则会乱码解密失败)
byte[] result = cipher.doFinal(content.getBytes());
byte[] base64Rel = Base64.encode(result, Base64.DEFAULT);
String strRel = new String(base64Rel);
byte[] decodeBytes = Base64.decode(strRel, Base64.DEFAULT);
byte[] decodeRel = cipher.doFinal(decodeBytes);
String decodeStr = new String(decodeRel);
Log.d("TEST", decodeStr+"333");
cipher.init(Cipher.DECRYPT_MODE, privateKey1);
byte[] decodeBytes1 = Base64.decode(strRel, Base64.DEFAULT);
byte[] decodeRel1 = cipher.doFinal(decodeBytes1);
String decodeStr1 = new String(decodeRel1);
Log.d("TEST", decrypt(privateKey1,strRel)+"22222222");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 私钥解密
* @param content
* @return
*/
public String decrypt (PrivateKey privateKey,String content){
try {
Cipher cipher = Cipher.getInstance("RSA");
//3.使用私钥初始化密码器
cipher.init(Cipher.DECRYPT_MODE, privateKey);
//4.执行解密操作
byte[] bytes =Base64.decode(content,Base64.DEFAULT);
byte[] decodeRel = cipher.doFinal(bytes);
return new String(decodeRel);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* String转私钥PrivateKey
* @param key
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String key){
byte[] keyBytes;
keyBytes = Base64.decode(key.getBytes(),Base64.DEFAULT);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3.相关问题
加密数据过长超过密钥长度时需特殊处理,分段加密。实测有效...
package com.example.myapplication;
import android.util.Log;
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;
/**
*
* @author xxj
*/
public class RsaHelperTest {
/**
* 获取秘钥对
*
*/
@Test
public void getKeyPairTest() {
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024);
assertTrue(info!=null);
Log.d("test",String.format("公钥:%s", info.getPublicKey()));
Log.d("test",String.format("私钥:%s", info.getPrivateKey()));
}
/**
* rsa 不分段加密,使用莫值为1024 时y,明文不能超过 117
*
*/
@Test
public void encipherTest() {
RsaHelper rsa = new RsaHelper();
RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
assertTrue(info!=null);
Log.d("test",String.format("公钥:%s", info.getPublicKey()));
Log.d("test",String.format("私钥:%s", info.getPrivateKey()));
String content="rsa加密、解密测试";
Log.d("test",String.format("明文:%s", content));
String ciphertext = rsa.encipher(content, info.getPublicKey());
Log.d("test",String.format("密文:%s", ciphertext));
String deTxt = rsa.decipher(ciphertext, info.getPrivateKey());
Log.d("test",String.format("解密:%s", 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);
Log.d("test",String.format("公钥:%s", info.getPublicKey()));
Log.d("test",String.format("私钥:%s", 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";
Log.d("test",String.format("明文:%s", content));
int enSegmentSize=245;//keysize=1024时,分段不能大于117 ;keysize>=2048时,分段不能大于keySize/8+128;
String ciphertext = rsa.encipher(content, info.getPublicKey(),enSegmentSize);
Log.d("test",String.format("密文:%s", ciphertext));
int deSegmentSize=256;//等于keySize/8
String deTxt = rsa.decipher(ciphertext, info.getPrivateKey(),deSegmentSize);
Log.d("test",String.format("解密:%s", 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);
Log.d("test",String.format("公钥:%s", info.getPublicKey()));
Log.d("test",String.format("私钥:%s", info.getPrivateKey()));
String content="rsa加密、解密测试";
Log.d("test",String.format("明文:%s", content));
PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
String ciphertext = rsa.encipher(content, pubKey,0);
Log.d("test",String.format("密文:%s", ciphertext));
PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
String deTxt = rsa.decipher(ciphertext,privKey,0);
Log.d("test",String.format("解密:%s", 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);
Log.d("test",String.format("公钥:%s", info.getPublicKey()));
Log.d("test",String.format("私钥:%s", info.getPrivateKey()));
String content="rsa加密、解密测试";
Log.d("test",String.format("明文:%s", content));
PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
String ciphertext = rsa.encipher(content, privKey,0);
Log.d("test",String.format("密文:%s", ciphertext));
PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
String deTxt = rsa.decipher(ciphertext,pubKey,0);
Log.d("test",String.format("解密:%s", deTxt));
assertTrue(content.equals(deTxt));
}
}