好久不见各位,最近事情有点多,没来得及更新博客,这两天抽空把RSA算法初步实现了一下,下面和大家分享一下经验。
非对称加密是相对于对称加密而言的,它具有加解密密钥不一致(不重复使用加密的密钥来进行解密)、安全性能高的特点,一般而言非对称加密的算法有RSA, SM2等。而对称加密的算法则主要有DES、3DES、AES、SM1等。
分组加密是将明文分成按照字节或字符进行分组,从而提高加解密效率的一种处理方式。大家可以查看我之前的博客去了解一下。
https://blog.csdn.net/qq_31236027/article/details/128003587?spm=1001.2014.3001.5501
优点:RSA算法安全性能好
缺点:执行效率较低,没有对称加密效率高。
/**
* 测试类
* @param args
*/
public static void main(String[] args) {
String send = "lalalala";
StringBuffer sb = new StringBuffer();
BigInteger b1,b2;
//获取两个大素数
b1 = RNG.getPrime(300);
b2 = RNG.getPrime(300);
for(char ch: send.toString().toCharArray()) {
int i = (ch - '0' + 48);
BigInteger s = BigInteger.valueOf(i);
//求大素数的乘积
BigInteger n = b1.multiply(b2);
//求f(n) 欧拉函数 = (b1-1) * (b2-1) => 表示与n互质的数的个数
BigInteger fn = (b1.subtract(BigInteger.ONE)).multiply((b2.subtract(BigInteger.ONE)));
BigInteger e = fn.subtract(BigInteger.valueOf(2));
//从后面出发出错概率会小
while(e.compareTo(BigInteger.valueOf(2)) > 0) {
if (EucleidesUtils.gcd(e, fn).compareTo(BigInteger.ONE) == 0) {
break;
}
e = e.subtract(BigInteger.ONE);
}
// System.out.println("e = " + e.toString());
//求e-1,利用欧几里得扩展公式
// System.out.println("fn = " + fn.toString());
BigInteger d = EucleidesUtils.eucleides(e, fn)[0];
// System.out.println("d = " + d.toString());
s = s.modPow(e,n);
// System.out.println("s' = " + s.toString());
s = s.compareTo(BigInteger.ZERO) == 0 ? BigInteger.ZERO :s.modPow(d, n);
// System.out.println("s mod = " + s.toString());
sb.append((char)((s.intValue() - 48) + '0'));
}
System.out.println("result = " + sb.toString());
}
欧几里得扩展公式
/**
* 欧几里得扩展公式(numb1 numb2分别是)
* @param numb1 numb1
* @param numb2 numb2
* @return
*/
public static BigInteger[] eucleides(BigInteger numb1,BigInteger numb2) {
BigInteger s0 = BigInteger.ONE,t0 =BigInteger.ZERO,s1 = BigInteger.ZERO
,t1 = BigInteger.ONE,sn = BigInteger.ZERO,tn = BigInteger.ZERO; //i-轮数
int i = 0;
BigInteger r0,r1,r2,q1;
if (numb1.compareTo(numb2) < 0) {
r0 = numb2;
r1 = numb1;
} else {
r0 = numb1;
r1 = numb2;
}
do{
if (r1.compareTo(BigInteger.ZERO) == 0) {
return new BigInteger[]{tn,sn};
}
r2 = r0.remainder(r1); //step1. 求numb1与numb2的余数
q1 = (r0.subtract(r2)).divide(r1); //step2. 求numb1与numb2的除数
sn = s0.subtract(q1.multiply(s1)); //step3. 根据数学归纳法 rn = snr0 + tnr1=> sn = sn-2r0 + tn-2r1
tn = t0.subtract(q1.multiply(t1)); //step4. 根据数学归纳法 rn = snr0 + tnr1=> tn = sn-1r0 + tn-1r
//获取新的数据
//第一轮
if(i == 0) {
BigInteger temp = sn.multiply(r0).add(tn.multiply(r1)); //gcd(r0,r1) = s*r0 + t*r1;
r0 = r1;
r1 = temp;
} else {
//后续几轮
r0 = r1;
r1 = r2;
if (r1.compareTo(BigInteger.ZERO) == 0) {
return new BigInteger[]{tn,sn};
}
r2 = r0.remainder(r1);
}
//获取新数据
s0 = s1;
s1 = sn;
t0 = t1;
t1 = tn;
i++;
} while(r2.compareTo(BigInteger.ZERO) != 0);
return new BigInteger[]{tn,sn};
}
------------------------------------------------ 2023.11.15 --------------------------------------------------------------------
优化了一下,支持任意字符的加解密
/**
* b1,b2
*/
public static BigInteger b1= null, b2 = null;
public static BigInteger fn = null, d = null, n = null, e = null;
static {
//获取两个大素数
b1 = RNG.getPrime(300);
b2 = RNG.getPrime(300);
//求f(n) 欧拉函数 = (b1-1) * (b2-1) => 表示与n互质的数的个数
fn = (b1.subtract(BigInteger.ONE)).multiply((b2.subtract(BigInteger.ONE)));
//求大素数的乘积
n = b1.multiply(b2);
e = fn.subtract(BigInteger.valueOf(2));
//从后面出发出错概率会小
while(e.compareTo(BigInteger.valueOf(2)) > 0) {
if (EucleidesUtils.gcd(e, fn).compareTo(BigInteger.ONE) == 0) {
break;
}
e = e.subtract(BigInteger.ONE);
}
//求e-1,利用欧几里得扩展公式
d = EucleidesUtils.eucleides(e, fn)[0];
}
/**
* 测试类
* @param args
*/
public static void main(String[] args) {
String send = "{\"code\":200,\"message\":\"成功!\",\"data\":{\"id\":\"2103813902831\",\"name\":\"章鱼哥是我啊\",\"gender\":\"男\"}}";
RsaUtil rsa = new RsaUtil();
String encryptedText = rsa.encrypt(send, null, null);
System.out.println(rsa.decrypt(encryptedText, null, null));
}
/**
* 加密
*/
@Override
public String encrypt(String text, String iv, EncryptMode mode) {
StringBuffer encryptedText = new StringBuffer();
List<String> list = new ArrayList<>();
for(char ch: text.toString().toCharArray()) {
int i = (ch - '0' + 48);
BigInteger s = BigInteger.valueOf(i);
s = s.modPow(e,n);
list.add(EncodeUtil.toBinary(s.toString(),EncodeRadix.DEC, true));
encryptedText.append(
EncodeUtil.binaryToHexStr(
EncodeUtil.toBinary(s.toString(),EncodeRadix.DEC, true
),false)
).append("-");
}
System.out.println("encryptedText = " + encryptedText.toString());
return encryptedText.toString();
}
/**
* 解密
*/
@Override
public String decrypt(String encrytedText, String iv, EncryptMode mode) {
StringBuffer sb = new StringBuffer();
String encyptedText = encrytedText.toString();
for(String str: encyptedText.split("\\-+")) {
String tmp = EncodeUtil.toBinary(str, EncodeRadix.HEX, true);
tmp = new BigInteger(tmp).toString();
BigInteger s = new BigInteger(EncodeUtil.binaryToDec(tmp));
s = s.compareTo(BigInteger.ZERO) == 0 ? BigInteger.ZERO: s.modPow(d,n);
sb.append((char)((s.intValue() - 48) + '0'));
}
System.out.println("result = " + sb.toString());
return sb.toString();
}
其中,EncodeUtil详见前面的文章介绍。
https://blog.csdn.net/qq_31236027/article/details/128579451?spm=1001.2014.3001.5501