RSA 算法流程及证明

RSA 算法流程及证明

需要的前置知识: 欧拉函数欧拉定理费马小定理同余式乘法性质互质数判断

  1. 算法描述
  2. 算法流程
  3. RSA 算法证明
  4. RSA 算法 C++ 实现
  5. 参考资料

算法描述

1977年,美国的罗纳德·李维斯特( R o n   R i v e s t Ron\ Rivest Ron Rivest)、阿迪·萨莫尔( A d i   S h a m i r Adi\ Shamir Adi Shamir)和伦纳德·阿德曼( L e o n a r d   A d l e m a n Leonard\ Adleman Leonard Adleman)三人共同提出了著名的非对称加密算法 —— R S A RSA RSA,这是目前安全性最高的加密算法之一。

R S A RSA RSA 是一种建立在大数因子分解基础上的算法,算法明文以分组为单位进行加密,每个分组的二进制值均小于 n n n,即分组大小必须小于或等于 l o g 2 n log_2^n log2n 位。

算法流程

在这里插入图片描述

设:明文 M M M,密文 C C C

加密: C = M e   m o d   n C = M^e\ mod\ n C=Me mod n

解密: M = C d   m o d   n M = C^d\ mod\ n M=Cd mod n


关于上述流程的几个关系的补充

  1. n = p ∗ q n = p*q n=pq p , q p,q p,q 是素数
  2. ϕ ( n )   = ϕ ( p ∗ q )   = ϕ ( p ) ∗ ϕ ( q ) = ( p − 1 ) ∗ ( q − 1 ) \phi(n)\ = \phi(p*q)\ = \phi(p)*\phi(q) = (p-1)*(q-1) ϕ(n) =ϕ(pq) =ϕ(p)ϕ(q)=(p1)(q1) (欧拉函数)
  3. e ∗ d    m o d    ϕ ( n ) = 1 e*d\ \ mod\ \ \phi(n) = 1 ed  mod  ϕ(n)=1,即 e d ≡ 1   ( m o d   ϕ ( n ) ) ed \equiv 1\ (mod\ \phi(n)) ed1 (mod ϕ(n)) d ≡ e − 1   ( m o d   ϕ ( n ) ) d \equiv e^{-1}\ (mod\ \phi(n)) de1 (mod ϕ(n)) 也就是说 d d d e e e 是模 ϕ ( n ) \phi(n) ϕ(n) 的乘法逆元
  4. 根据模算术的性质,仅当 d d d ϕ ( n ) \phi(n) ϕ(n) 互素, e e e 也与 ϕ ( n ) \phi(n) ϕ(n) 互素时, d d d e e e 是模 ϕ ( n ) \phi(n) ϕ(n) 的乘法逆元

RSA 算法证明

若想证明 R S A RSA RSA 加密算法的正确性,只需证明解密得到的结果与明文相同

M = C d   m o d   n = ( M e   m o d   n ) d   m o d   n = M e d   m o d   n M = C^d\ mod\ n = (M^e\ mod\ n)^d\ mod\ n = M^{ed}\ mod\ n M=Cd mod n=(Me mod n)d mod n=Med mod n

也就是说只需要证明 M e d ≡ M   ( m o d   n ) M^{ed} \equiv M \ (mod\ n) MedM (mod n) 成立即可

      e ∗ d    m o d    ϕ ( n ) = 1 \ \ \ \ \ e*d\ \ mod\ \ \phi(n) = 1      ed  mod  ϕ(n)=1

⇒ e ∗ d   =   k ∗ ϕ ( n ) + 1 \Rightarrow e*d\ = \ k * \phi(n) + 1 ed = kϕ(n)+1

带入原式    M k ∗ ϕ ( n ) + 1 ≡ M   ( m o d   n ) \ \ M^{k * \phi(n) + 1} \equiv M \ (mod\ n)   Mkϕ(n)+1M (mod n)

分情况讨论

  1. M , n M, n M,n 互质

    根据欧拉定理有 M ϕ ( n ) ≡ 1   ( m o d   n ) M^{\phi(n)} \equiv 1 \ (mod\ n) Mϕ(n)1 (mod n)

    根据同余式乘法性质可得 M k ∗ ϕ ( n ) ≡ 1   ( m o d   n ) M^{k * \phi(n)} \equiv 1 \ (mod\ n) Mkϕ(n)1 (mod n)

    又有 M ≡ M   ( m o d   n ) M \equiv M \ (mod\ n) MM (mod n)

    ⇒ M k ∗ ϕ ( n ) + 1 ≡ M   ( m o d   n ) \Rightarrow M^{k * \phi(n) + 1} \equiv M \ (mod\ n) Mkϕ(n)+1M (mod n)

  2. M , n M, n M,n 不互质

    ∵ M , n 不 互 质 \because M,n 不互质 Mn

       且   n = p ∗ q \ \ 且\ n = p*q    n=pq

       且   p , q 均 为 质 数 \ \ 且\ p,q均为质数    pq

       且   M &lt; n \ \ 且\ M &lt; n    M<n

    ∴ M = k ∗ p   或 者   M = k ∗ q \therefore M = k*p\ 或者\ M = k*q M=kp  M=kq (就是说 M M M 只能是 p p p 的倍数或者 q q q 的倍数, M M M 不能是 p ∗ q p*q pq 的倍数是因为 M &lt; n M &lt; n M<n

    M = k ∗ p   ( 1 &lt; k &lt; q ) M = k*p\ (1 &lt; k &lt; q) M=kp (1<k<q)

    ∵ k &lt; q , 且   q   是 质 数 \because k &lt; q,且\ q\ 是质数 k<q q 

    ∴ k , q   互 质 \therefore k, q\ 互质 kq (互质数判断)

    根据费马小定理: ( k ∗ p ) q − 1 ≡ 1   ( m o d   q ) (k*p)^{q-1} \equiv 1\ (mod\ q) (kp)q11 (mod q) (费马小定理这个形式的条件是 k ∗ p k*p kp 不能整除 q q q,所以需要 k , q   互 质 k,q\ 互质 kq 

    ⇒ ( k ∗ p ) ( q − 1 ) ∗ ( p − 1 ) ∗ k ∗ ( k ∗ p ) ≡ ( k ∗ p )   ( m o d   q ) \Rightarrow (k*p)^{(q-1)*(p-1)*k}*(k*p) \equiv (k*p)\ (mod\ q) (kp)(q1)(p1)k(kp)(kp) (mod q) (同余式乘法性质)

    ∵ ϕ ( n )   = ( p − 1 ) ∗ ( q − 1 ) ,   e ∗ d   =   k ∗ ϕ ( n ) + 1 \because \phi(n)\ = (p-1)*(q-1),\ e*d\ = \ k * \phi(n) + 1 ϕ(n) =(p1)(q1) ed = kϕ(n)+1

    ∴ ( k ∗ p ) e d ≡ ( k ∗ p )   ( m o d   q ) \therefore (k*p)^{ed} \equiv (k*p)\ (mod\ q) (kp)ed(kp) (mod q)

    ⇒ ( k ∗ p ) e d = t ∗ q + k ∗ p \Rightarrow (k*p)^{ed} = t*q + k*p (kp)ed=tq+kp

    将它的形式转换一下 ⇒ ( k ∗ p ) ∗ ( ( k ∗ p ) e d − 1 − 1 ) = t ∗ q \Rightarrow (k*p)*((k*p)^{ed-1}-1) = t*q (kp)((kp)ed11)=tq

    可见 t ∗ q t*q tq 能整除 k ∗ p k*p kp,又 q q q 是质数,所以 t t t 能整除 p p p

    t = t ‘ ∗ p t = t^`*p t=tp

    代回原式 ( k ∗ p ) e d = t ∗ q + k ∗ p (k*p)^{ed} = t*q + k*p (kp)ed=tq+kp 得: ⇒ ( k ∗ p ) e d = t ‘ ∗ p ∗ q + k ∗ p \Rightarrow(k*p)^{ed} = t^`*p*q + k*p (kp)ed=tpq+kp

    ∵ M = k ∗ p , n = p ∗ q \because M = k*p,n = p*q M=kpn=pq

    ∴ M e d = t ‘ ∗ n + M \therefore M^{ed} = t^`*n + M Med=tn+M

    ⇒ M e d ≡ M   ( m o d   n ) \Rightarrow M^{ed} \equiv M \ (mod\ n) MedM (mod n)

综上 ①,②,等式得证

RSA 算法 C++ 实现

#include <bits/stdc++.h>
using namespace std;

// RSA算法所需参数
typedef struct RSA_PARAM_Tag {
    unsigned __int64 p, q;   // 两个素数,不参与加密解密运算
    unsigned __int64 f;      // f = (p-1)*(q-1),不参与加密解密运算
    unsigned __int64 n, e;   // 公匙PU,n = p*q,gcd(e,f) = 1
    unsigned __int64 d;      // 私匙PR,e*d = 1 (mod f),gcd(n,d) = 1
    unsigned __int64 s;      // 块长,满足^s<=n的最大的s,即log2(n)
} RSA_PARAM; // 小素数表

const static long g_PrimeTable[] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
const static long g_PrimeCount = sizeof(g_PrimeTable) / sizeof(long);
const unsigned __int64 multiplier = 12747293821;
const unsigned __int64 adder = 1343545677842234541; // 随机数类

class RandNumber {
private:
    unsigned __int64 randSeed;
public:
    RandNumber(unsigned __int64 s=0);
    unsigned __int64 Random(unsigned __int64 n);
};

RandNumber::RandNumber(unsigned __int64 s) {
    if(!s) {
        randSeed = (unsigned __int64)time(NULL);
    }
    else {
        randSeed = s;
    }
}

unsigned __int64 RandNumber::Random(unsigned __int64 n) {
    randSeed = multiplier * randSeed + adder;
    return randSeed % n;
}

static RandNumber g_Rnd; /* 模乘运算,返回值x=a*b mod n  */

inline unsigned __int64 MulMod(unsigned __int64 a, unsigned __int64 b, unsigned __int64 n) {
     return a * b % n;
}

/* 模幂运算,返回值 x = base^pow mod n */
unsigned __int64 PowMod(unsigned __int64 &base, unsigned __int64 &pow, unsigned __int64 &n) {
    unsigned __int64 a = base, b = pow, c = 1;
    while(b) {
        while(!(b & 1)) {
            b >>= 1;  //a=a * a % n;    //函数看起来可以处理位的整数,但由于这里a*a在a>=2^32时已经造成了溢出,因此实际处理范围没有位
            a=MulMod(a, a, n);
        }
        b--;        //c=a * c % n;        //这里也会溢出,若把位整数拆为两个位整数不知是否可以解决这个问题。
        c=MulMod(a, c, n);
    }
    return c;
}

/*  Rabin-Miller素数测试,通过测试返回,否则返回。n是待测素数。注意:通过测试并不一定就是素数,非素数通过测试的概率是/4  */
long RabinMillerKnl(unsigned __int64 &n) {
    unsigned __int64 b, m, j, v, i;
    m = n-1;
    j=0;
    // 0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数
    while(!(m & 1)) {
        ++j;
        m>>=1;
    }
    // 1、随机取一个b,<=b<n-1
    b = 2 + g_Rnd.Random(n - 3);
    // 2、计算v=b^m mod n
    v = PowMod(b, m, n);
    // 3、如果v==1,通过测试
    if(v == 1) {
        return 1;
    }
    // 4、令i=1
    i=1;
    b=2;
    // 5、如果v=n-1,通过测试
    while(v != n - 1) {
    // 6、如果i==l,非素数,结束
        if(i == j) {
            return 0;
        }
    // 7、v=v^2 mod n,i=i+1
        v = PowMod(v, b, n);
        ++i;
    // 8、循环到
    }
    return 1;
}

/*   Rabin-Miller素数测试,循环调用核心loop次全部通过返回,否则返回   */
long RabinMiller(unsigned __int64 &n, long loop) {
    //先用小素数筛选一次,提高效率
    for(long i=0; i < g_PrimeCount; i++) {
        if(n % g_PrimeTable[i] == 0) {
            return 0;
        }
    }
    //循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop
    for(long i=0; i < loop; i++) {
        if(!RabinMillerKnl(n)) {
            return 0;
        }
    }
    return 1;
}

/* 随机生成一个bits位(二进制位)的素数,最多位*/
unsigned __int64 RandomPrime(char bits) {
    unsigned __int64    base;
    do {
        base = (unsigned long)1 << (bits - 1);   //保证最高位是
        base += g_Rnd.Random(base);               //再加上一个随机数
        base |= 1;    //保证最低位是,即保证是奇数
    }
    while(!RabinMiller(base, 30));    //进行拉宾-米勒测试次
    return base;    //全部通过认为是素数
}

  /*欧几里得法求最大公约数*/
unsigned __int64 EuclidGcd(unsigned __int64 &p, unsigned __int64 &q) {
    unsigned __int64 a = p > q ? p : q;
    unsigned __int64 b = p < q ? p : q;
    unsigned __int64 t;
    if(p == q) {
        return p;   //两数相等,最大公约数就是本身
    }
    else {
        //辗转相除法,gcd(a,b)=gcd(b,a-qb)
        while(b) {
            a = a % b;
            t=a;
            a=b;
            b=t;
        }
        return a;
    }
}

 /*  Stein法求最大公约数 */
unsigned __int64 SteinGcd(unsigned __int64 &p, unsigned __int64 &q) {
    unsigned __int64 a = p > q ? p : q;
    unsigned __int64 b = p < q ? p : q;
    unsigned __int64 t, r=1;
    if(p == q) {
        return p;           //两数相等,最大公约数就是本身
    }
    else {
        while((!(a & 1)) && (!(b & 1))) {
            r<<=1;          //a、b均为偶数时,gcd(a,b)=2*gcd(a/2,b/2)
            a>>=1;
            b>>=1;
        }
        if(!(a & 1)){
            t=a;            //如果a为偶数,交换a,b
            a=b;
            b=t;
        }
        do {
            while(!(b & 1)) {
                b>>=1; //b为偶数,a为奇数时,gcd(b,a)=gcd(b/2,a)
            }
            if(b < a) {
                t=a;        //如果b小于a,交换a,b
                a=b;
                b=t;
            }
            b = (b - a) >> 1; //b、a都是奇数,gcd(b,a)=gcd((b-a)/2,a)
        } while(b);
        return r * a;
    }
}

/*  已知a、b,求x,满足a*x =1 (mod b)相当于求解a*x-b*y=1的最小整数解  */
unsigned __int64 Euclid(unsigned __int64 &a, unsigned __int64 &b) {
    unsigned __int64 m, e, i, j, x, y;
    long xx, yy;
    m = b;
    e = a;
    x = 0;
    y = 1;
    xx=1;
    yy=1;
    while(e) {
        i=m / e;
        j=m % e;
        m=e;
        e=j;
        j=y;
        y*=i;
        if(xx == yy) {
            if(x > y) {
                y=x - y;
            }
            else {
                y -= x;
                yy = 0;
            }
        }
        else {
            y += x;
            xx = 1 - xx;
            yy = 1 - yy;
        }
        x = j;
    }
    if(xx == 0) {
        x = b - x;
    }
    return x;
}

/* 随机产生一个RSA加密参数*/
RSA_PARAM RsaGetParam(void) {
    RSA_PARAM           Rsa={ 0 };
    unsigned __int64    t;
    Rsa.p=RandomPrime(16);          //随机生成两个素数
    Rsa.q=RandomPrime(16);
    Rsa.n=Rsa.p * Rsa.q;
    Rsa.f=(Rsa.p - 1) * (Rsa.q - 1);
    do {
        Rsa.e=g_Rnd.Random(65536);  //小于^16,=2^16
        Rsa.e|=1;   //保证最低位是,即保证是奇数,因f一定是偶数,要互素,只能是奇数
    } while(SteinGcd(Rsa.e, Rsa.f) != 1);
    Rsa.d=Euclid(Rsa.e, Rsa.f);
    Rsa.s=0;   t=Rsa.n >> 1;
    while(t) {
        Rsa.s++;   //s=log2(n)
        t>>=1;
    }
    return Rsa;
}

/* 拉宾-米勒测试 */
void TestRM(void) {
    unsigned long k=0;
    cout << " - Rabin-Miller prime check.\n" << endl;
    for(unsigned __int64 i = 4197900001ULL; i < 4198000000ULL; i+=2) {
        if(RabinMiller(i, 30)) {
            k++;
            cout << i << endl;
        }
    }
    cout << "Total: " << k << endl;
}

/*  RSA加密解密 */
void TestRSA(void) {
    RSA_PARAM r;
    char pSrc[]="Hello RSA!";
    const unsigned long n=sizeof(pSrc);
    unsigned char *q, pDec[n];
    unsigned __int64    pEnc[n];
    r = RsaGetParam();
    cout << "p=" << r.p << endl;
    cout << "q=" << r.q << endl;
    cout << "f=(p-1)*(q-1)=" << r.f << endl;
    cout << "n=p*q=" << r.n << endl;
    cout << "e=" << r.e << endl;
    cout << "d=" << r.d << endl;
    cout << "s=" << r.s << endl;
    cout << "Source:" << pSrc << endl;
    q= (unsigned char *)pSrc;
    cout << "Encode:";
    for(unsigned long i=0; i < n; i++) {
        unsigned __int64 temp = (unsigned __int64)q[i];
        pEnc[i]=PowMod(temp, r.e, r.n);
        cout << hex << pEnc[i] << " ";
    }
    cout << endl;
    cout << "Decode:";
    for(unsigned long i=0; i < n; i++) {
        pDec[i]=PowMod(pEnc[i], r.d, r.n);
        cout << hex << (unsigned long)pDec[i] << " ";
    }
    cout << endl;
    cout << (char *)pDec << endl;
}


int main(void) {
    TestRSA();
    return 0;
}


参考资料

王晓峰老师《信息安全技术2018》

RSA算法证明-RSA算法证明参考资料

RSA算法原理-私钥解密的证明

RSA的证明

RSA加密算法中解密步骤的证明

RSA算法基础详解

合天网安实验室 RSA实验

  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值