c rsa java_25行代码实现完整的RSA算法Java版

25行代码实现完整的RSA算法Java版

我的上一篇博客《25行代码实现完整的RSA算法》自从上个月发表了以后,很多程序员给我打电话或者发短信说,终于看到了一篇能把RSA算法的代码写明白的,他们问我说能不能把代码写成Java版的,我说Java的会看着很费劲,Python代码的直观性在数字计算方面有很大的优势。

但是架不住他们非要我写,我一拍肩膀说,好吧,我答应你们的请求。花了一晚上的时间,就把代码从Python翻译成为Java,经过测试完美。如果写得不好,请大家轻轻拍砖。

至于RSA理论我就不再这里讲了,代码如果看不懂,请看我的上一篇博客《25行代码实现完整的RSA算法》。下面就主要把代码贴出来了。

1、计算最大公约数与扩展欧几里得算法

GCD.java文件,gcd方法用来计算两个整数的最大公约数。ext_gcd是扩展欧几里得方法的计算公式。

import java.math.BigInteger;

/**

* 求最大公约数

* @author 北门大官人

*

*/

public class GCD {

/**

*

辗转相除法求最大公约数

* @param a

* @param b

* @return

*/

public BigInteger gcd(BigInteger a, BigInteger b){

if(b.equals(BigInteger.ZERO)){

return a ;

}else{

return gcd(b, a.mod(b)) ;

}

}

/**

*

扩展欧几里得算法:

*

求ax + by = 1中的x与y的整数解(a,b互质)

* @param a

* @param b

* @return

*/

public BigInteger[] extGcd(BigInteger a, BigInteger b){

if(b.equals(BigInteger.ZERO)){

BigInteger x1 = BigInteger.ONE ;

BigInteger y1 = BigInteger.ZERO ;

BigInteger x = x1 ;

BigInteger y = y1 ;

BigInteger r = a ;

BigInteger[] result = {r, x, y} ;

return result ;

}else{

BigInteger[] temp = extGcd(b, a.mod(b)) ;

BigInteger r = temp[0] ;

BigInteger x1 = temp[1] ;

BigInteger y1 = temp[2] ;

BigInteger x = y1 ;

BigInteger y = x1.subtract(a.divide(b).multiply(y1)) ;

BigInteger[] result = {r, x, y} ;

return result ;

}

}

}

2、大整数幂取模算法

Exponentiation.java文件,主要用于计算超大整数超大次幂然后对超大的整数取模。我在网上查询到这个算法叫做“蒙哥马利算法”。

import java.math.BigInteger;

import java.util.ArrayList;

import java.util.List;

/**

* 主要用于计算超大整数超大次幂然后对超大的整数取模。

* 我在网上查询到这个算法叫做"蒙哥马利算法"。

* @author 北门大官人

*/

public class Exponentiation {

/**

* 超大整数超大次幂然后对超大的整数取模

(base ^ exponent) mod n

* @param base

* @param exponent

* @param n

* @return

*/

public BigInteger expMode(BigInteger base, BigInteger exponent, BigInteger n){

char[] binaryArray = new StringBuilder(exponent.toString(2)).reverse().toString().toCharArray() ;

int r = binaryArray.length ;

List baseArray = new ArrayList() ;

BigInteger preBase = base ;

baseArray.add(preBase);

for(int i = 0 ; i < r - 1 ; i ++){

BigInteger nextBase = preBase.multiply(preBase).mod(n) ;

baseArray.add(nextBase) ;

preBase = nextBase ;

}

BigInteger a_w_b = this.multi(baseArray.toArray(new BigInteger[baseArray.size()]), binaryArray) ;

return a_w_b.mod(n) ;

}

private BigInteger multi(BigInteger[] array, char[] bin_array){

BigInteger result = BigInteger.ONE ;

for(int index = 0 ; index < array.length ; index ++){

BigInteger a = array[index] ;

if(bin_array[index] == '0'){

continue ;

}

result = result.multiply(a) ;

}

return result ;

}

}

3、公钥私钥生成

RSA.java,生成公钥、私钥、并对信息加密解密。

import java.math.BigInteger;

/**

* RSA加密、解密、测试正确性

* @author 北门大官人

*

*/

public class RSA {

/**

*

 
 

def gen_key(p, q):

n = p * q

fy = (p - 1) * (q - 1)

e = 3889

# generate d

a = e

b = fy

r, x, y = ext_gcd(a, b)

print x

d = x

# 公钥 私钥

return (n, e), (n, d)

* @param p

* @param q

* @return

*/

public BigInteger[][] genKey(BigInteger p, BigInteger q){

BigInteger n = p.multiply(q) ;

BigInteger fy = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)) ;

BigInteger e = new BigInteger("3889") ;

// generate d

BigInteger a = e ;

BigInteger b = fy ;

BigInteger[] rxy = new GCD().extGcd(a, b) ;

BigInteger r = rxy[0] ;

BigInteger x = rxy[1] ;

BigInteger y = rxy[2] ;

BigInteger d = x ;

// 公钥 私钥

return new BigInteger[][]{{n , e}, {n , d}} ;

}

/**

* 加密

* @param m 被加密的信息转化成为大整数m

* @param pubkey 公钥

* @return

*/

public BigInteger encrypt(BigInteger m, BigInteger[] pubkey){

BigInteger n = pubkey[0] ;

BigInteger e = pubkey[1] ;

BigInteger c = new Exponentiation().expMode(m, e, n) ;

return c ;

}

/**

* 解密

* @param c

* @param selfkey 私钥

* @return

*/

public BigInteger decrypt(BigInteger c, BigInteger[] selfkey){

BigInteger n = selfkey[0] ;

BigInteger d = selfkey[1] ;

BigInteger m = new Exponentiation().expMode(c, d, n) ;

return m ;

}

public static void main(String[] args) {

// 公钥私钥中用到的两个大质数p,q'''

BigInteger p = new BigInteger("106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169") ;

BigInteger q = new BigInteger("144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209") ;

RSA rsa = new RSA() ;

// 生成公钥私钥'''

// pubkey, selfkey = gen_key(p, q)

BigInteger[][] keys = rsa.genKey(p, q) ;

BigInteger[] pubkey = keys[0] ;

BigInteger[] selfkey = keys[1] ;

// 需要被加密的信息转化成数字,长度小于秘钥n的长度,如果信息长度大于n的长度,那么分段进行加密,分段解密即可。'''

BigInteger m = new BigInteger("1356205320457610288745198967657644166379972189839804389074591563666634066646564410685955217825048626066190866536592405966964024022236587593447122392540038493893121248948780525117822889230574978651418075403357439692743398250207060920929117606033490559159560987768768324823011579283223392964454439904542675637683985296529882973798752471233683249209762843835985174607047556306705224118165162905676610067022517682197138138621344578050034245933990790845007906416093198845798901781830868021761765904777531676765131379495584915533823288125255520904108500256867069512326595285549579378834222350197662163243932424184772115345") ;

System.out.println("被加密信息:" + m);

// 信息加密'''

BigInteger c = rsa.encrypt(m, pubkey) ;

System.out.println("密文:" + c);

// 信息解密'''

BigInteger d = rsa.decrypt(c, selfkey) ;

System.out.println("被解密后信息:" + d);

}

}

用Java写出来的数值运算就是没有Python的直观。大整数运算只能用BigInteger,确实看得人眼睛疼。如果哪里不懂可以对照上一篇《25行代码实现完整的RSA算法》一起看,祝大家晚安。

代码经过运行以后,发现加密的速度很快,但是解密的速度有点惨不忍睹。23.587秒,比Python版的慢六倍多。python只用4秒左右。由此说明,Java语言不适合做数值运算,而Python语言在这方面有着很大的优势。

最后,觉得代码写得好的,请给我打赏,支付宝微信:18201637201。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以提供一段Java与C-share通用的RSA2加解密的C语言程序示例: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <openssl/rsa.h> #include <openssl/pem.h>//加密 int public_encrypt(unsigned char *data,int data_len,unsigned char *key,unsigned char *encrypted) { RSA * rsa = NULL; FILE * fp = NULL; int flen; int rsa_len; //从文件中读取公钥 fp=fopen(key,"rb"); if(fp==NULL){ perror("open key file error"); return -1; } rsa=PEM_read_RSA_PUBKEY(fp,NULL,NULL,NULL); if(rsa==NULL){ perror("read key file error"); return -2; } fclose(fp); //获取RSA长度 flen=RSA_size(rsa); rsa_len=RSA_public_encrypt(data_len,data,encrypted,rsa,RSA_NO_PADDING); if(rsa_len==-1){ perror("RSA_public_encrypt error"); return -3; } RSA_free(rsa); return 0; }//解密 int private_decrypt(unsigned char *enc_data,int data_len,unsigned char *key,unsigned char *decrypted) { RSA * rsa = NULL; FILE * fp = NULL; int rsa_len; //从文件中读取私钥 fp=fopen(key,"rb"); if(fp==NULL){ perror("open key file error"); return -1; } rsa=PEM_read_RSAPrivateKey(fp,NULL,NULL,NULL); if(rsa==NULL){ perror("read key file error"); return -2; } fclose(fp); //获取RSA长度 rsa_len=RSA_private_decrypt(data_len,enc_data,decrypted,rsa,RSA_NO_PADDING); if(rsa_len==-1){ perror("RSA_private_decrypt error"); return -3; } RSA_free(rsa); return 0; } ### 回答2: RSA2是一种非对称加密算法,常用于保护通信数据的安全性。JAVA和C#都提供了RSA2算法的库和工具包,因此我们可以使用这两种编程语言来实现RSA2加解密。 首先,我们需要生成一对RSA2密钥,包括公钥和私钥。在JAVA中,可以使用"KeyPairGenerator"类生成密钥对;在C#中,可以使用"RSACryptoServiceProvider"类生成密钥对。生成密钥对后,将公钥保存在一个地方,供加密方使用,私钥则保密,供解密方使用。 在JAVA中,使用公钥对数据进加密的步骤如下: 1. 从存储的公钥文件中读取公钥。 2. 使用读取到的公钥初始化"Cipher"类的实例。 3. 将待加密数据传入"update"方法中,并得到加密后的字节数据。 4. 将加密后的字节数据换为Base64编码字符串,以保证数据的可读性。 在C#中,使用公钥对数据进加密的步骤如下: 1. 从存储的公钥文件中读取公钥。 2. 使用读取到的公钥初始化"RSACryptoServiceProvider"类的实例。 3. 将待加密数据换为字节数组。 4. 调用"Encrypt"方法,传入待加密的字节数组,并得到加密后的字节数组。 解密的步骤在两种语言中是类似的,都是使用私钥对加密后的数据进解密。首先,要从存储的私钥文件中读取私钥,然后使用私钥对加密后的数据进解密。解密后的数据就是原始数据。 总结一下,JAVA与C#都可以实现RSA2加解密通用。在JAVA中,使用"KeyPairGenerator"和"Cipher"类实现;在C#中,可以使用"RSACryptoServiceProvider"类实现。关键是要确保公钥和私钥的生成和存储方式一致,以及解密方正确使用私钥解密加密后的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值