【密码学】RSA

【密码学】RSA

​ 下一个问题是容易想到的,“这能用普通的加密技术来做吗?我们能产生一个安全的加密信息,该信息不需要预先交换密钥就能被授权的接收方解读吗?”

image-20211016234710033

0x00 RSA 介绍

在这里插入图片描述

​ 在此可以看到,非对称加密是通过两个密钥对(公钥-私钥)来实现对数据的加密和解密的。公钥用于加密,私钥用于解密。对于非对称的加密和解密为什么可以使用不同的密钥来进行,这些都是数学上的问题了。不同的非对称加密算法也会应用到不同的数学知识。上面也对RSA中使用的数学问题做了一个小小的介绍。现在就来看看RSA算法是怎么来对数据进行加密的吧,如下是一幅RSA加密算法流程及加密过程图。

img

RSA算法基于的原理,基本上来说,加密和解密数据围绕着模幂运算

0x01 产生随机素数

1.1 随机数生成

rand( ) 函数用于生成一个 0~32767 (即一个15bit数);

srand( ) 函数用于为rand( ) 函数指定种子( 若未指定则默认为srand(1) );

通常使用时间作为随机数种子,但由于本程序执行时间过快(在1秒内),导致时间种子不变,使得产生的随机数相等,故为其乘上随机数rand() ;

// 4~8bit
ll randtonum8()
{
	srand((unsigned)time(NULL)*rand());
	ll randnum=(rand()&0xF)+1;
	randnum <<= 4;
	return randnum+(rand()&0xF);
}

1.2 素数检验(Miller-Rabin概率检测法)

现代密码学(第4版) 93页
x现代密码学(第4版) 94页

ll Quick_Multiply(ll a,ll b,ll c)  //快速积 
{
    ll ans=0,res=a;
    while(b){
        if(b&1)
          ans=(ans+res)%c;
        res=(res+res)%c;
        b>>=1;
    }
    return ans;
}
int maxhight(ll val)  // 求最高位数 
{
	int i=0;
    while(val){
        i++;
        val = val>>1;
    }
    return i;	
}

// 对上文伪代码的翻译
bool Miller_Rabin(ll n)     //判断素数 
{
	int prime[10]={2,3,5,7,11,13,17,19,23,29};  // 选10个不同的a,概率至少为1-2^(-10)
    if(!(n&1))  return false;     //如果x是偶数或者是0,1,那它不是素数
    int maxh=maxhight(n-1);
    ll tmp=0x01;
    tmp<<=(maxh-1);  // b的最高位
    for(int i=0;i<10;i++){
    	ll d=1;
    	ll x;
    	ll b=n-1;
    	while(tmp){
	    	x=d;
	    	d=Quick_Multiply(d,d,n);
	    	if(d==1 && x!=1 && x!=n-1) return false;
	    	if(b&tmp) d=Quick_Multiply(d,prime[i],n);
	    	tmp>>=1;  // 从高位到低位取出b的每一位
		}
		if(d!=1) return false;
	}
    return true;
}

0x02 快速幂

// 没什么好说的
ll Quick_Power(ll a,ll b,ll c)     //快速幂 
{
    ll ans=1,res=a;
    while(b)
    {
        if(b&1)
          ans=Quick_Multiply(ans,res,c);
        res=Quick_Multiply(res,res,c);
        b>>=1;
    }
    return ans;
}

0x03 求最大公因数

// 辗转相除法
ll gcd(ll a,ll b)
{
	ll mod=a%b;
	while(mod){
		a=b;
		b=mod;
		mod=a%b;
	}
	return b;
} 

附代码

/*
     _/_/_/      _/_/_/    _/_/    
    _/    _/  _/        _/    _/   
   _/_/_/      _/_/    _/_/_/_/    
  _/    _/        _/  _/    _/     
 _/    _/  _/_/_/    _/    _/        
                                      */
#include <iostream>
#include <string>
#include <cstdlib>
#include <stdio.h>
#include <time.h>
#define ll unsigned long long int
using namespace std;

ll Quick_Multiply(ll a,ll b,ll c)  //快速积 
{
    ll ans=0,res=a;
    while(b)
    {
        if(b&1)
          ans=(ans+res)%c;
        res=(res+res)%c;
        b>>=1;
    }
    return ans;
}

ll Quick_Power(ll a,ll b,ll c)     //快速幂 
{
    ll ans=1,res=a;
    while(b)
    {
        if(b&1)
          ans=Quick_Multiply(ans,res,c);
        res=Quick_Multiply(res,res,c);
        b>>=1;
    }
    return ans;
}

int maxhight(ll val)  // 求最高位数 
{
	int i=0;
    while(val)
    {
        i++;
        val = val>>1;
    }
    return i;	
}

bool Miller_Rabin(ll n)     //判断素数 
{
	int prime[10]={2,3,5,7,11,13,17,19,23,29};
    if(!(n&1))  return false;     //如果x是偶数或者是0,1,那它不是素数
    int maxh=maxhight(n-1);
    ll tmp=0x01;
    tmp<<=(maxh-1);
    for(int i=0;i<10;i++){
    	ll d=1;
    	ll x;
    	ll b=n-1;
    	while(tmp){
	    	x=d;
	    	d=Quick_Multiply(d,d,n);
	    	if(d==1 && x!=1 && x!=n-1) return false;
	    	if(b&tmp) d=Quick_Multiply(d,prime[i],n);
	    	tmp>>=1;
		}
		if(d!=1) return false;
	}
    return true;
}

ll randtonum8()
{
	srand((unsigned)time(NULL)*rand());
	ll randnum=(rand()&0xF)+1;
	randnum <<= 4;
	return randnum+(rand()&0xF);
}

ll toprime()
{
	while(1){
		ll randnum=randtonum8();
		if( Miller_Rabin(randnum) ) return randnum;  
	}
}

ll gcd(ll a,ll b)
{
	ll mod=a%b;
	while(mod){
		a=b;
		b=mod;
		mod=a%b;
	}
	return b;
} 

void rsa2key(ll key[3])
{
	ll p,q,E,D,N,L; 
	while(1){
		p=toprime();
		q=toprime();
		printf("p: %d, q: %d\n",p,q);
		N=p*q;
		L=(p-1)*(q-1); 
		while(1){
			E=rand()%L;
			if(gcd(L,E)==1) break;
		}
		while(1){
			D=rand()%L;
			if(E*D%L==1) break;
		}
		if(E!=1 && D!=1) break;
	}
	key[0]=E;
	key[1]=N;
	key[2]=D;
}

int main()
{
	ll key[3];
	
	rsa2key(key);
	printf("密钥:0x%X 0x%X 0x%X\n",key[0],key[1],key[2]);
	
	ll plain=randtonum8();
	printf("明文: 0x%X\n",plain);

	ll encrypt=Quick_Power(plain,key[0],key[1]);
	printf("密文: 0x%X\n",encrypt);  

	ll decrypt=Quick_Power(encrypt,key[2],key[1]);
	printf("解密文: 0x%X\n",decrypt);  
	
	return 0;
}

参考文章:

RSA 非对称加密原理(小白也能看懂哦~)_jijianshuai的专栏-CSDN博客

RSA原理介绍_yhc166188的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤城封雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值