公钥密码学,RSA算法

公钥密码学

1976年Diffie和Hellman针对上面的问题提出了单向函数加密方法,这种方法和之前数千年来密码学中的所有方法有根本的区别,即公钥密码体制。

非对称加密算法使用完全不同但又是完全匹配的一对钥匙: 公钥和私钥 公钥:公开的,任何人都知道

私钥:只有自己知道

算法:一对密钥中用公钥加密的结果可以用私钥解密,反过来用私钥加密的结果也可以用公钥解密。

公钥加密的使用方式

Alice和Bob互发(公布)各自的公钥,私钥只有自己知道

Alice用对称密钥加密信件,再用Bob的公钥加密对称密

Bob用自己的私钥解密对称密钥,再用对称密钥解密信

公钥密码学与对称密码学比较

对称密码学基于替换和置换(混淆和扩散),运算速度快

公钥密码学基于数学理论(单向函数),运算速度慢

对称密码学使用单密钥,需要额外秘密信道协商密钥

公钥密码学使用两个独立的密钥,不需要秘密信道协商密钥

RSA算法

RSA算法1977年由MIT三位密码学家Rivest - Shamirh和Adleman发明,是迄今为止最为成熟完善的公钥密码体制。

RSA算法能够抵抗到目前为止已知的绝大多数密码攻击,已被ISo推荐为公钥数据加密标准。

RSA原理

公钥和私钥的产生

任意选择两个大的质数(素数)p和q,p不等于q,计算N=pq

根据欧拉函数,不大于N且与N互质的整数个数为(p-1)(q-1)

选择一个整数e 与(p-1)(q-1)互质,并且e小于(p-1)(q-1)

用以下这个公式计算d: dxe = 1(mod(p-1)(q-1))

将p和q销毁后,(N,e)是公钥, (N,d)是私钥

加密消息

假设Bob想给Alice送一个消息,他知道Alice产生的公钥N和e

将原始信息分为多段,每一段(假定为n)分别用以下公式计算出c : n^e= c (mod N)

将多个n计算出的多个c串在一起,就是密文,发送即可。

解密消息

Alice得到Bob的消息c后就可以利用她的密钥( N,d)来解码。她可以用以下这个公式来将c转换为n : c=n (mod N)

得到n后,她可以将原来的信息m重新复原。

RSA应用

加密少量数据

比起DES和其它对称算法来说, RSA的运算速度要慢得多。

实际使用时,RSA算法不用来加密消息,而是用来加密传输密钥,加密消息用对称算法,如 DES 。

实现数字签名

将RSA 算法反向使用(私钥加密公钥解密),对消息摘要加密,可以实现数字签名的功能。

数字签名可以防止数据篡改﹑数据抵赖和数据伪造发生。

RSA算法源码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int prime[1305];//存放素数

int p[10005];//用筛选法求素数 
void PRIME(){
	int i,i2,k;
    for(i=0;i<=10000;i+=2)
   		p[i]=0; 
    for(i=1;i<=10000;i+=2)
   		p[i]=1; 
    p[2]=1;p[1]=0;
    for(i=3;i<=100;i+=2){ 
    	if(p[i]==1){
     		i2=i+i; 
     		k=i2+i;
            while(k<=10000){
      		p[k]=0;
      		k+=i2;
     		}	
    	}
	}
	prime[0]=1;
	prime[1]=2;
	for(i=3;i<=10000;i+=2)
   		if(p[i])
    		prime[++prime[0]]=i;

}
// 计算逆元素
__int64 mod(__int64 a,__int64 n){
	return (a%n+n)%n;
}
void gcd(__int64 a,__int64 b,__int64 &d,__int64 &x,__int64 &y){
	if(b==0)
	{	
   		d=a;
   		x=1;
   		y=0;
   		return;
	}
    gcd(b,a%b,d,y,x);
    y-=x*(a/b);
}
//a-1 mod n
__int64 Inv(__int64 a,__int64 n){ // 计算逆元素
	__int64 d,x,y;
	gcd(a,n,d,x,y);
    if(d==1)
   		return mod(x,n);
	else 
   		return -1;
}
//求两个数的最大公约数
__int64 GCD(__int64 n,__int64 m){
	__int64 t,r;
	if(n<m){
   		t=n;
   		n=m;
   		m=t;
	}
	while((r=n%m)!=0){
   		n=m;
   		m=r;
	}
	return m;
}
//x=a^b(mod n)
__int64 ModPow(__int64 a,__int64 b,__int64 n){
	__int64 d=1,i=0;
	while(b>=(1<<i)) i++;
	for(--i;i>=0;--i){
   		d=d*d%n;
   		if(b&(1<<i))
    		d=d*a%n;
	}
	return d;
}
int main(){
	__int64 i,e,d,n,st,ed,eula;
	__int64 m,c,ans;
	PRIME();
	printf("素数的个数:%d\n",prime[0]);
	printf("选择两个不同的素数(输入编号,空格隔开):\n");//47和71分别是第15个和20个 
	while(scanf("%I64d%I64d",&st,&ed)!=EOF){
		printf("你选择的两个素数分别是:%d和%d\n",prime[st],prime[ed]);
   		n=prime[st]*prime[ed];
   		printf("计算得到N是%I64d\n",n);
   		//N的Eula数
   		eula=(prime[st]-1)*(prime[ed]-1);
   		//找一个与eula互质的数
   		for(i=2;i<eula;i++)
    		if(GCD(eula,i)==1){
     			e=i;
     			break;
    		}
    	//e=79; 
   		//上面找到了公开密钥n--e
   		d=Inv(e,eula);
		//上面找到了私密钥n--d
   		printf("生成公钥:(%I64d %I64d)\n",e,n);
   		//输出密钥
  		printf("生成私钥:(%I64d %I64d)\n",d,n);
   		//切忌加密的数要比n小
   		printf("请输入要加密的数(<N)\n");
   		scanf("%I64d",&m);
   		c=ModPow(m,e,n);
   		printf("通过计算%I64d^%I64d(mod %I64d)得到密文=%I64d\n",m,e,n,c);
   		ans=ModPow(c,d,n);
  		printf("通过计算%I64d^%I64d(mod %I64d)得到明文=%I64d\n",c,d,n,ans);
  		printf("素数的个数:%d\n",prime[0]);
		printf("选择两个不同的素数(输入编号,空格隔开):\n");//47和71分别是第15个和20个 
	}
	return 0;
}

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java实现RSA算法的示例代码: ```java import java.math.BigInteger; import java.security.SecureRandom; public class RSA { private BigInteger modulus; private BigInteger privateKey; private BigInteger publicKey; // 初始化RSA算法 public RSA(int bitLength) { SecureRandom random = new SecureRandom(); BigInteger p = BigInteger.probablePrime(bitLength / 2, random); BigInteger q = BigInteger.probablePrime(bitLength / 2, random); BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE)); this.modulus = p.multiply(q); this.publicKey = new BigInteger("65537"); // 一般取65537 this.privateKey = this.publicKey.modInverse(phi); } // 加密明文 public BigInteger encrypt(BigInteger plaintext) { return plaintext.modPow(publicKey, modulus); } // 解密密文 public BigInteger decrypt(BigInteger ciphertext) { return ciphertext.modPow(privateKey, modulus); } public static void main(String[] args) { RSA rsa = new RSA(1024); BigInteger plaintext = new BigInteger("123456"); System.out.println("明文:" + plaintext); BigInteger ciphertext = rsa.encrypt(plaintext); System.out.println("密文:" + ciphertext); BigInteger decryptedText = rsa.decrypt(ciphertext); System.out.println("解密后的明文:" + decryptedText); } } ``` 在上述代码中,我们首先生成了一个RSA对象,并指定了密钥长度为1024位。接着,我们可以使用encrypt方法对明文进行加密,使用decrypt方法对密文进行解密。最后,我们在main方法中对一个简单的明文进行加密、解密并输出结果。 需要注意的是,RSA算法是一种公钥加密算法,因此我们只需要保护好私钥即可,公钥可以公开,不需要保密。在实际应用中,我们可以将公钥告知通信对方,让对方使用公钥对数据进行加密,然后再使用私钥进行解密。这样可以保证数据的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值