POJ2447 RSA【公匙密码】

题目链接:

http://poj.org/problem?id=2447

题目大意:

RSA是个有名的公匙密码系统。在这个系统中,每个参与者有一个只能自己知道的私匙和一个每个人都

知道的公匙。为了安全地把信息传递给对方,应该用公匙对信息进行加密,对方用自己的私匙进行解密。

对RSA系统的描述如下:

首先,选择两个大素数P、Q,计算N = P * Q。

然后,选择一个正整数E作为加密密匙,令T = (p-1)*(q-1),且gcd(E,T) = 1。

最后,计算解密密匙D,使得(E * D) mod T = 1,这里D是E模T的逆元。

公匙表示为{E,N},私匙表示为{D,N},P和Q被舍弃。

加密数据的过程为

C = M^E mod N

解密数据的过程为

M = C^D mod N

M是一个比N小的非负整数成为明文,C是密文。

现在问题来了:给你密文C和公匙{E,N},能找到明文M吗?

思路:

因为N是一个大整数,先用PollardRho对N做大整数的数分解,得到一个素因子P,那么另一个素因子

Q = N/Q,这样得到了两个素数p和q。再求出T = (P-1)*(Q-1)。然后用扩展欧几里得的方法求出E关于

模T的逆元D。根据公匙M = C^D mod N,从而得到明文。

AC代码:

#include<iostream>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;

LL mod_mul(LL x,LL y,LL mo)
{
    LL t;
    x %= mo;
    for(t = 0; y; x = (x<<1)%mo,y>>=1)
        if(y & 1)
            t = (t+x) %mo;

    return t;
}
//LL mod_mul(LL x,LL y,LL mo)
//{
//    LL t,T,a,b,c,d,e,f,g,h,v,ans;
//    T = (LL)(sqrt(double(mo)+0.5));
//    t = T*T - mo;
//    a = x / T;
//    b = x % T;
//    c = y / T;
//    d = y % T;
//    e = a*c / T;
//    f = a*c % T;
//    v = ((a*d+b*c)%mo + e*t) % mo;
//    g = v / T;
//    h = v % T;
//    ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo;
//    while(ans < 0)
//        ans += mo;
//    return ans;
//}
LL mod_exp(LL num,LL t,LL mo)
{
    LL ret = 1, temp = num % mo;
    for(; t; t >>=1,temp=mod_mul(temp,temp,mo))
        if(t & 1)
            ret = mod_mul(ret,temp,mo);

    return ret;
}

//PollarRho大整数因子分解
LL gcd(LL a,LL b)
{
    if(b == 0)
        return a;
    return gcd(b, a % b);
}

LL PollarRho(LL n, int c)
{
    int i = 1;
    srand(time(NULL));
    LL x = rand() % (n-1) + 1;
    LL y = x;
    int k = 2;
    while(true)
    {
        i++;
        x = (mod_exp(x,2,n) + c) % n;
        LL d = gcd(n+y-x,n);
        if(1 < d && d < n)
            return d;
        if(y == x)
            return n;
        if(i == k)
        {
            y = x;
            k *= 2;
        }
    }
}

void ExGCD(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        d = a;
    }
    else
    {
        ExGCD(b,a%b,d,y,x);
        y -= x*(a/b);
    }
}

int main()
{
    LL p,q,t,c,e,n;
    while(cin >> c >> e >> n)
    {
        p = PollarRho(n,10007);
        q = n/p;
        t = (p-1)*(q-1);
        LL d,x0,y0;
        ExGCD(e,t,d,x0,y0);
        x0 = (x0%t + t) % t;
        cout << mod_exp(c,x0,n) << endl;
    }
    return 0;
}
时间: 2024-08-05 05:41:40

POJ2447 RSA【公匙密码】的相关文章

HDU1211 RSA【公匙密码】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1211 题目大意: RSA是个很强大的加密数据的工具,对RSA系统的描述如下: 选择两个大素数p.q,计算n = p * q,F(n) = (p-1)*(q-1),选择一个整数e,使得gcd(e,F(n)) = 1, e是公匙,计算d使得d * e mod F(n) = 1 mod F(n),d是私匙.加密数据的方法为 C = E(m) = m^e mod n 解密数据的方法为 M = D(c) =

SSH 原理和公匙私匙

先主要介绍了Telnet.SSH 的通信原理,分析了其通信时的工作流程. Telnet 无论Telnet协议连接的是什么类型终端,都会转换为NVT(Net Virtual Terminal)格式进行通信.网络虚拟终端NVT是Telnet异构跨平台的基础. Telnet 的工作进程是这样的 本地与远程主机建立连接,该过程实际上是建立一个TCP 连接,用户必须知道远程主机的 IP 地址或域名 将本地终端上输入的用户名和口令及以后输入的任何命令或字符以NVT格式传送到远程主机.该过程实际上是从本地主机

java生成RSA公私钥字符串,简单易懂

java生成RSA公私钥字符串,简单易懂 解决方法: 1.下载bcprov-jdk16-140.jar包,参考:http://www.yayihouse.com/yayishuwu/chapter/1537 2.java代码 KeyPairGenerator keyPairGenerator = KeyPairGenerator .getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPa

Java中使用OpenSSL生成的RSA公私钥进行数据加解密

RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够 抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准.目前该加密方式广泛用于网上银行.数字签名等场合.RSA算法基于一个十分简单的 数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥. OpenSSL是什

Python rsa公私钥生成 rsa公钥加密(分段加密)私钥加签实战

一般现在的SAAS服务提供现在的sdk或api对接服务都涉及到一个身份验证和数据加密的问题.一般现在普遍的做法就是配置使用非对称加密的方式来解决这个问题,你持有SAAS公司的公钥,SAAS公司持有你的公钥,你们就可以进行加密和签名的验证了. 先来看下两种在linux或者mac下面生成key pair的方法: 使用openssl 生成一把2048bit长度的钥匙对,首先我们生成一把.pem格式的私钥: openssl genrsa -out private_key.pem 2048 然后通过这把私

Java中使用OpenSSL生成的RSA公私钥

RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准.目前该加密方式广泛用于网上银行.数字签名等场合.RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥. OpenSSL是什么:众

RSA 公私钥 互换问题

关于 RSA,我的理解是: 按定义的话,公私钥是可以互换的 问题是常见的实现里面,保存“私钥”的那个数据结构或者文件,里面除了私钥所必需的那一对数之外,还有额外的信息(足以算出公钥来),所以绝对不能把这个“私钥”数据给其他人…… n=pq φ(n)=(p-1)(q-1) m^φ(n) ≡ 1 mod n 令 ed ≡ 1 mod φ(n) cipher=m^e mod n plain = cipher ^ d mod n ≡ m^ed mod n = m 理论上e与d是可以互换的,但是一般公钥指

rsa公私钥加密原理

假设爱丽丝的公钥是(3233, 17):加入发送65,公钥加密后的结果是2790 私钥(3233, 2753) 收到公钥加密的数据2790后,进行2790^2753次方后,得出结果再mod 3233就会得到65,恢复出原来的数据据结果 公钥(n,e) 私钥(n,d) 总共有2个密钥的数据加密数据的过程,m的e次方,(m^e) mod 3233,那么结果就是2790,就是得出的结果

JAVA JS 中的 modulus exponent 生成 C# 公匙

C#用的是xml,里面是base64编码的.你上面的就是hex格式,只要把上面hex格式转成byte数组,然后在base64编码就可以了. public static byte[] Hex2Byte(string byteStr) { try { byteStr = byteStr.ToUpper().Replace(" ", ""); int len = byteStr.Length / 2; byte[] data = new byte[len]; for (i