RSA加密解密、签名算法 一、RSA加密解密、签名算法介绍 RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥。两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的(可能同时多人持有)。 签名就是在这份资料后面增加一段强而有力的证明,以此证明这段信息的发布者和这段信息的有效性完整性。RSA签名常用的就是将这份信息进行hash,得到一个hash值,再将hash值加密作为签名,后缀在信息的末尾。哈希的好处:更安全,签名更快,解除了签名长度的限制。 二、算法分析 加密解密算法分析: 1、选取两个大素数p和q,p和q保密。 利用Java语言的中的java.math.BigInteger类的方法中随机产生大数,并使用probablePrime()方法,获取两个BigInteger,其值为给定长度的正可能质数。 2、计算n=pq,f(n)=(p-1)(q-1)。n公开,f(n)保密。 BigInteger类对象的加减乘除等运算均使用该类自带的方法。 3、随机选取正整数1<e<f(n),满足gcd(e,f(n))=1。e是公开的加密密钥。 对e从2到f(n)进行循环,找到一个e满足gcd(e,f(n))=1。其中调用判断两数是否为素数的方法public static int getgcd(BigInteger n1,BigInteger n2)。 4、计算d,满足de(1modf(n))。d是保密的解密密钥。 其中d为e mod f(n)的逆元,调用求逆元的方法public static BigInteger getInverse(BigInteger u,BigInteger n),返回逆元。 5、加密变换:对明文m,密文为c = 。 调用方法public static BigInteger getgaomimou(BigInteger a,BigInteger b,BigInteger n),参数a=m,b=e,n=n,返回密文。 6、解密变换:对密文c,明文为m = 。 同样是调用方法public static BigInteger getgaomimou(BigInteger a,BigInteger b,BigInteger n),参数a=c,b=d,n=n,返回明文。 签名算法分析: A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。 A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。
B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。 三、源代码 - import java.math.BigInteger;
- import java.util.*;
- public class rsa {
- //判断两数是否互素
- public static int getgcd(BigInteger n1,BigInteger n2)
- {
- BigInteger q,r;
- do
- {
- q = n1.divide(n2);
- r = n1.subtract(q.multiply(n2));
- if(r.compareTo(BigInteger.ZERO)==0)
- {
- break;
- }
- else
- {
- n1 = n2;
- n2 = r;
- }
- }while(r.compareTo(BigInteger.ZERO)!=0);
-
- if(n2.compareTo(BigInteger.ONE) == 0)
- return 1;
- else
- return 0;
- }
- //求逆元
- public static BigInteger getInverse(BigInteger u,BigInteger n)
- {
- BigInteger q,r,n1 = n,n2 = u,t,b1=BigInteger.ZERO,b2=BigInteger.ONE;
- do
- {
- q = n1.divide(n2);
- r = n1.subtract(q.multiply(n2));
- if(r.compareTo(BigInteger.ZERO)!=0)
- {
- n1 = n2;
- n2 = r;
- t = b2;
- b2 = b1.subtract(q.multiply(b2));
- b1 = t;
- }
- }while(r.compareTo(BigInteger.ZERO)!=0);
- if(n2.compareTo(BigInteger.ONE)==0)
- return (b2.add(n)).mod(n);
- else
- return BigInteger.ZERO;
- }
- //求高幂模
- public static BigInteger getgaomimou(BigInteger a,BigInteger b,BigInteger n)
- {
- BigInteger c = BigInteger.ONE;
- while(b.compareTo(BigInteger.ZERO)!=0)
- {
- while((b.mod(new BigInteger("2"))).compareTo(BigInteger.ZERO)==0)
- {
- b = b.divide(new BigInteger("2"));
- a = a.multiply(a).mod(n);
- }
- if((b.mod(new BigInteger("2"))).compareTo(BigInteger.ZERO)!=0)
- {
- b = b.subtract(BigInteger.ONE);
- c= c.multiply(a).mod(n);
- }
- }
- return c;
- }
- //加解密
- public static void main(String[] args) {
- BigInteger e,d;
- //生成两个大素数
- BigInteger p = BigInteger.probablePrime(30, new Random());
- BigInteger q = BigInteger.probablePrime(30, new Random());
- BigInteger n = p.multiply(q);
- System.out.println("n="+n);
- BigInteger mn = (p.subtract(BigInteger.ONE))
- .multiply(q.subtract(BigInteger.ONE));
- //选取正整数e,作为公开的加密密钥
- for(e = new BigInteger("2");e.compareTo(mn)<0;e = e.add(BigInteger.ONE))
- {
- int t = getgcd(e,mn);
- if(t == 1)
- break;
- }
- System.out.println("加密密钥e="+e);
- //解密密钥
- d = getInverse(e,mn);
- System.out.print("请输入明文:");
- Scanner in=new Scanner(System.in);
- BigInteger ptext=in.nextBigInteger();
- BigInteger ctext = getgaomimou(ptext,e,n);
- System.out.println("加密结果为:"+ctext);
- ptext = getgaomimou(ctext,d,n);
- System.out.println("解密结果为:"+ptext);
- }
- }
复制代码
|