如何实现用javascript实现rsa加解密

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何实现用javascript实现rsa加解密相关的知识,希望对你有一定的参考价值。

javascript实现rsa加解密的实现方式是通过PKCS完成的。
1、整个定义的function

function pkcs1pad2(s,n)
if(n < s.length + 11) // TODO: fix for utf-8
alert("Message too long for RSA");
return null;

var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0)
var c = s.charCodeAt(i--);
//UTF-8编码为变长字节,使用实际的字节来记录
if(c < 128) // encode using utf-8
ba[--n] = c;

else if((c > 127) && (c < 2048))
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;

else
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;


//实际输入拼装结束,将下一位赋值为0标记结束
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
//拼接随机非0字节
while(n > 2) // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];

//这两位做简单的校验
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);

该方法中对UTF-8字符进行了兼容,并且在拼装完实际输入的字符后,还拼装了随机的字节,使用拼装后的字符串去加密。由于每次拼装的结果是随机的,这样每次加密后的密文都不同。
2、调用方法:;
function RSAEncrypt(text)
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
参考技术A 具体实现思路如下: 1。服务端生成公钥与私钥,保存。 2。客户端在请求到登录页面后,随机生成一字符串。 3。后此随机字符串作为密钥加密密码,再用从服务端获取到的公钥加密生成的随机字符串。 4。将此两段密文传入服务端,服务端用私钥解出随.

自己实现简单的RSA秘钥生成与加解密(Java )

  最近在学习PKI,顺便接触了一些加密算法。对RSA着重研究了一下,自己也写了一个简单的实现RSA算法的Demo,包括公、私钥生成,加解密的实现。虽然比较简单,但是也大概囊括了RSA加解密的核心思想与流程。这里写下来与大家分享一下。                                                                                                                                              

  RSA概述:

   RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 RSA的数学基础是大整数因子分解问题,其说明如下:

  • 给定两个素数p、q,计算乘积pq=n很容易
  • 给定整数n,求n的素因数p、q使得n=pq十分困难

 

  RSA的密码体制:

   设n=pq,其中p和q是大素数。设P=E=Zn,且定义K={(n,p,q,a,b):ab≡1(modΦ(n)) }其中 Φ(n)=(p-1)(q-1)。对于K={(n,p,q,a,b)} 定义加密 E(x)=xb mod n; 解密D(y)=ya mod n;(x,y∈Zn),值n,b组成了公钥,p、q和a组成了私钥

  •  RSA生成秘钥步骤   
  1. 随机生成两个大素数p、q,并计算他们的乘积n
  2. 计算k=(p-1)(q-1)
  3. 生成一个小于k且与k互质的数b,一般可使用65537
  4. 通过扩展欧几里得算法求出a关于k的反模a。

  代码如下:

首先,写出三个封装类,PrivateKey.java PublicKey.java RsaKeyPair.java (JDK中的实现高度抽象,这里我们就简单的封装一下)  

复制代码
 1 package com.khalid.pki;
 2 
 3 import java.math.BigInteger;
 4 
 5 public class PublicKey {
 6 
 7     private final BigInteger n;
 8     
 9     private final BigInteger b;
10     
11     public PublicKey(BigInteger n,BigInteger b){
12         this.n=n;
13         this.b=b;
14     }
15 
16     public BigInteger getN() {
17         return n;
18     }
19 
20     public BigInteger getB() {
21         return b;
22     }
23 }
复制代码
复制代码
 1 package com.khalid.pki;
 2 
 3 import java.math.BigInteger;
 4 
 5 public class PrivateKey {
 6 
 7     private final BigInteger n;
 8     
 9     private final BigInteger a;
10     
11     public PrivateKey(BigInteger n,BigInteger a){
12         this.n=n;
13         this.a=a;
14     }
15 
16     public BigInteger getN() {
17         return n;
18     }
19 
20     public BigInteger getA() {
21         return a;
22     }
23 }
复制代码
复制代码
 1 package com.khalid.pki;
 2 
 3 public class RsaKeyPair {
 4 
 5     private final PrivateKey privateKey;
 6     
 7     private final PublicKey publicKey;
 8     
 9     public RsaKeyPair(PublicKey publicKey,PrivateKey privateKey){
10         this.privateKey=privateKey;
11         this.publicKey=publicKey;
12     }
13 
14     public PrivateKey getPrivateKey() {
15         return privateKey;
16     }
17 
18     public PublicKey getPublicKey() {
19         return publicKey;
20     }
21 }
复制代码

 

 生成大素数的方法没有自己实现,借用了BigInteger类中的probablePrime(int bitlength,SecureRandom random)方法

 

复制代码
SecureRandom random=new SecureRandom();
random.setSeed(new Date().getTime());
BigInteger bigPrimep,bigPrimeq;
while(!(bigPrimep=BigInteger.probablePrime(bitlength,random)).isProbablePrime(1)){
            continue;
        }//生成大素数p
        
while(!(bigPrimeq=BigInteger.probablePrime(bitlength,random)).isProbablePrime(1)){
            continue;
        }//生成大素数q
复制代码

 

计算k、n、b的值

1 BigInteger n=bigPrimep.multiply(bigPrimeq);//生成n
2         //生成k
3 BigInteger k=bigPrimep.subtract(BigInteger.ONE).multiply(bigPrimeq.subtract(BigInteger.ONE));
4         //生成一个比k小的b,或者使用65537
5 BigInteger b=BigInteger.probablePrime(bitlength-1, random);

 

核心计算a的值,扩展欧几里得算法如下

  注意第二个方法 cal 其实还可以传递第三个参数,模的值,但是我们这里省略了这个参数,因为在RSA中模是1

复制代码
 1     private static BigInteger x; //存储临时的位置变量x,y 用于递归
 2     
 3     private static BigInteger y;
 4     
 5     
 6     //欧几里得扩展算法
 7     public static BigInteger ex_gcd(BigInteger a,BigInteger b){
 8         if(b.intValue()==0){
 9             x=new BigInteger("1");
10             y=new BigInteger("0");
11             return a;
12         }
13         BigInteger ans=ex_gcd(b,a.mod(b));
14         BigInteger temp=x;
15         x=y;
16         y=temp.subtract(a.divide(b).multiply(y));
17         return ans;
18         
19     }
20     
21     //求反模 
22     public static BigInteger cal(BigInteger a,BigInteger k){
23         BigInteger gcd=ex_gcd(a,k);
24         if(BigInteger.ONE.mod(gcd).intValue()!=0){
25             return new BigInteger("-1");
26         }
27         //由于我们只求乘法逆元 所以这里使用BigInteger.One,实际中如果需要更灵活可以多传递一个参数,表示模的值来代替这里
28         x=x.multiply(BigInteger.ONE.divide(gcd));
29         k=k.abs();
30         BigInteger ans=x.mod(k);
31         if(ans.compareTo(BigInteger.ZERO)<0) ans=ans.add(k);
32         return ans;
33         
34     }
复制代码

 我们在生成中只需要

  1 BigInteger a=cal(b,k); 

就可以在Log级别的时间内计算出a的值

将以上代码结合包装成的 RSAGeneratorKey.java

复制代码
 1 package com.khalid.pki;
 2 
 3 import java.math.BigInteger;
 4 import java.security.SecureRandom;
 5 import java.util.Date;
 6 
 7 public class RSAGeneratorKey {
 8     
 9     private static BigInteger x; //存储临时的位置变量x,y 用于递归
10     
11     private static BigInteger y;
12     
13     
14     //欧几里得扩展算法
15     public static BigInteger ex_gcd(BigInteger a,BigInteger b){
16         if(b.intValue()==0){
17             x=new BigInteger("1");
18             y=new BigInteger("0");
19             return a;
20         }
21         BigInteger ans=ex_gcd(b,a.mod(b));
22         BigInteger temp=x;
23         x=如何实现用javascript实现rsa加解密

用Java实现RSA加解密及签名和验签——.pfx文件格式秘钥

JavaScript实现RSA加解密

RSA 加解密(Java 实现)

PHP如何实现AES加解密

用Java实现RSA加解密及签名和验签——.pem文件格式秘钥