c++实现Tonelli–Shanks算法

c++实现Tonelli–Shanks算法

算法思路:

输入:模p的一个二次剩余n,奇素数p(意味着勒让德符号L(n,p)=1).

输出:整数R,使得R^2≡n(mod p,以下默认)

①从p-1中除去所有因子2,设p-1=q*2^S,其中q是奇数(也就是除去所有因子2的结果)。

②选择一个z,使得勒让德符号L(z,p)= -1(即,z是p的二次非剩余(pow(z, (p - 1) // 2,p)==p-1 )

③令
c≡z^Q.
r≡n^((Q+1)/2 ),
t≡n^Q,
m=S.

④循环:

1.若t≡1,返回R,程序终止。

2.否则,找出最小的i,使得0≡1。可以重复做平方完成这一点。

3.令
b≡c^2 ^(m-i-1),
r≡rb,
t≡tb^2,
c≡b^2,
m=i.

代码:

#include<iostream>
#include<math.h>
using namespace std;
int ksm(int a,int b,int c){
    int ans = 1;
    while(b){
        if(b&1){
            ans = (ans*a)%c;
        }
        a = (a*a)%c;
        b >>= 1;
    }
    return ans;
}
int legendre(int n,int p){
    return ksm(n,(p-1)/2,p);
}
int tonelli(int n,int p){
    int q = p - 1;
    int s = 0;
    while(q % 2 == 0){
        q /= 2;
        s += 1;
    }
    if(s == 1)
        return (int)ksm(n, (p + 1) / 4,p);
    int flag;
    for(int i=2;i<p;i++){
        if(p - 1 == legendre(i, p)){
            flag = i;
            break;
        }
    }
    int c = (int)ksm(flag, q,p);
    int r = (int)ksm(n, (q + 1) / 2,p);
    int t = (int)ksm(n, q,p);
    int m = s;
    int t2 = 0;
    while((t - 1) % p != 0){
        t2 = (t * t) % p;
        int flag2;
        for(int i=1;i<m;i++){
            if((t2 - 1) % p == 0){
                flag2 = i;
                break;
            }
            t2 = (t2 * t2) % p;
        }
        int b = (int)ksm(c, 1 << (m - flag2 - 1),p);
        r = (r * b) % p;
        c = (b * b) % p;
        t = (t * c) % p;
        m = flag2;
    }
    return r;
}
int main(){
    int n=78,p=137;
    cout<<tonelli(n,p)<<endl;
}
//结果:30

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,由于缺少 `secret.py` 文件,我无法运行这段代码。但是,根据代码逻辑和命名,可以猜测这是一个 RSA 相关的加密程序,其中使用了 Pell 方程和 TonelliShanks 算法实现 RSA 的快速解密。具体来说,代码中的 `keygen()` 函数生成了两个大质数 $p$ 和 $q$,然后计算 $n=pq$。接下来,通过求解 Pell 方程 $x^2-Dy^2=1$ 找到一个解 $(x,y)$,其中 $D=1117$。然后,使用 TonelliShanks 算法分解 $n$,得到 $p$ 和 $q$。接着,计算 $u_1$ 和 $u_2$,然后使用 CRT 计算 $v=u_1qq^{-1} + u_2pp^{-1}$。最后,将明文分成两个部分,分别使用 RSA 加密,并输出密文。 具体的解密过程如下: 设密文为 $(c_1,c_2)$,其中 $c_1$ 和 $c_2$ 分别是原始明文的两个部分的 RSA 加密结果。根据 RSA 加密的公式,有: $$ c_1 \equiv m_1^{e_1} \pmod{p} \\ c_1 \equiv m_1^{e_1} \pmod{q} \\ c_2 \equiv m_2^{e_2} \pmod{p} \\ c_2 \equiv m_2^{e_2} \pmod{q} $$ 其中,$e_1$ 和 $e_2$ 分别是 $p$ 和 $q$ 的 RSA 加密指数。由于 $p$ 和 $q$ 都是奇素数,因此有 $p-1=2^{s_p}t_p$ 和 $q-1=2^{s_q}t_q$,其中 $t_p$ 和 $t_q$ 都是奇数。根据 TonelliShanks 算法,可以计算出 $m_2^{(p+1)/4}$ 和 $m_2^{(q+1)/4}$ 的平方根 $r_p$ 和 $r_q$,使得 $r_p^2 \equiv m_2^{(p+1)/4} \pmod{p}$,$r_q^2 \equiv m_2^{(q+1)/4} \pmod{q}$,然后使用 CRT 合并 $r_p$ 和 $r_q$ 得到 $r$,即: $$ r = (r_p q q^{-1} + r_q p p^{-1}) \pmod{n} $$ 然后,对于 $m_1$,可以使用扩展欧几里得算法求出 $p$ 的乘法逆元 $d_p$,使得 $d_p p \equiv 1 \pmod{t_p}$,然后计算 $m_1^{e_1} \equiv c_1^{d_p} \pmod{p}$。同理,对于 $m_2$,可以使用扩展欧几里得算法求出 $q$ 的乘法逆元 $d_q$,使得 $d_q q \equiv 1 \pmod{t_q}$,然后计算 $m_2^{e_2} \equiv c_2^{d_q} \pmod{q}$。最后,将 $m_1$ 和 $r$ 合并得到原始明文,即 $m=m_1 + r$。 根据以上步骤,可以编写以下代码实现解密过程:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值