某些字符串的RSA算法失败

如何解决某些字符串的RSA算法失败

艾伦·B·唐尼(Allen B. Downey)在Chapter 11 of Think Python进行的练习11.7提示:

大整数的求幂是公用密钥加密的通用算法的基础。阅读RSA算法3的Wikipedia页面,并编写函数以对消息进行编码和解码。

我翻译了Key Generation section of the Wikipedia article中的简单英语算法。函数RSA接受一个字符串并将其编码为ASCII整数,创建用于解密的公共密钥和私有密钥,使用公共密钥加密编码的整数,使用私有密钥解密,然后将整数解码回字符串:

import math

def encode(s):

    m = ''
    for c in s:

        # each character in the message is converted to a ascii decimal value
        m += str(ord(c))

    return int(m)

def decode(i):
    # convert decrypted int back to string
    temp = str(i)
    decoded = ''
    while len(temp):
        if temp[:1] == '1':
            letter = chr(int(temp[:3]))
            temp = temp[3:]
        else:
            letter = chr(int(temp[0:2]))
            temp = temp[2:]
        decoded += letter
    
    return decoded

def generate_keys(m):

    # requires an int m that is an int representation (in ascii) of our message

    # 1. Choose two distinct prime numbers p and q.

    ##### TEST WIKIPEDIA EXAMPLE #####
    # p,q = 61,53

    # find two prime numbers whose product n will be greater than m
    i = math.ceil(math.sqrt(m))
    primes = []
    while len(primes) < 2:
        if isPrime(i):
            primes += [i]
        i += 1
    p,q = primes[0],primes[1]

    # 2. Compute n = pq.
    n = p * q
    in_range = int(m) < n
    if not in_range:
        print('m must be less than n')
        exit()

    # 3. Compute λ(n),where λ is Carmichael's totient function. Since n = pq,λ(n) = lcm(λ(p),λ(q)),and since p and q are prime,λ(p) = φ(p) = p − 1 and likewise λ(q) = q − 1. Hence λ(n) = lcm(p − 1,q − 1).
    # The lcm may be calculated through the Euclidean algorithm,since lcm(a,b) = |ab|/gcd(a,b).
    a,b = (p - 1),(q - 1)
    lam = int(abs(a * b) / math.gcd(a,b))
    # print('lam:',lam)

    # 4. Choose an integer e such that 1 < e < λ(n) and gcd(e,λ(n)) = 1; that is,e and λ(n) are coprime.

    ##### TEST WIKIPEDIA EXAMPLE #####
    # e = 17

    # accordng to wikipedia,the smallest (and fastest) possible value for e is 3: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Key_generation
    i = 3

    while i < lam:
        if math.gcd(i,int(lam)) == 1:
            e = i
            break
        i += 1

    # 5. compute d where d * e ≡ 1 (mod lam)
    d = int(modInverse(e,lam))

    return {'public': [n,e],'private': d}

def encrypt_message(m,public):

    n,e = public[0],public[1]

    # generate ciphertext
    return pow(m,e,n)

def decrypt_message(cipher,n,d):

    # decrypt ciphertext
    return pow(cipher,d,n)

def RSA(s):
    m = encode(s)
    keys = generate_keys(m)
    cipher = encrypt_message(m,keys['public'])
    message = decrypt_message(cipher,keys['public'][0],keys['private'])

    messages_match = message == m
    if not messages_match:
        print('the decoded integer does not equal the encoded integer')
        exit()

    return decode(message)

# taken from https://www.geeksforgeeks.org/python-program-to-check-whether-a-number-is-prime-or-not/
def isPrime(n) : 
  
    # Corner cases 
    if (n <= 1) : 
        return False
    if (n <= 3) : 
        return True
  
    # This is checked so that we can skip  
    # middle five numbers in below loop 
    if (n % 2 == 0 or n % 3 == 0) : 
        return False
  
    i = 5
    while(i * i <= n) : 
        if (n % i == 0 or n % (i + 2) == 0) : 
            return False
        i = i + 6
  
    return True

# modInverse(a,m) taken from https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
def modInverse(a,m) : 
    m0 = m 
    y = 0
    x = 1
  
    if (m == 1) : 
        return 0
  
    while (a > 1) : 
  
        # q is quotient 
        q = a // m 
  
        t = m 
  
        # m is remainder now,process 
        # same as Euclid's algo 
        m = a % m 
        a = t 
        t = y 
  
        # Update x and y 
        y = x - q * y 
        x = t 
  
  
    # Make x positive 
    if (x < 0) : 
        x = x + m0 
  
    return x 

if __name__ == "__main__":
    print(RSA('python')) # encrypts and decrypts message 'python'
    print(RSA('cat')) # encrypts and decrypts message 'cat'
    print(RSA('dog')) # encrypts and decrypts message 'dog'
    print(RSA('a 1')) # (to rule out spaces as the culprit) encrypts and decrypts message 'a 1'
    print(RSA('pythons')) # FAILS - 7 characters in string seems to be the limit
    print(RSA('hello world')) # FAILS - encoded string does not equal decoded string

在脚本结尾,我用几个字符串测试RSA。输出等于“ python”,“ cat”,“ dog”和“ a 1”(预期行为)的输入。但是'pythons'和'hello world'的编码和解码整数是不同的。

我怀疑是导致问题的原因是输入字符串的长度,但是我不确定在哪里导致故障。我的猜测是,如果pow(cipher,n)的长度太大,函数decrypt_message中的cipher将返回意外结果。

RSA为什么对某些字符串有效而对其他字符串无效?是输入字符串的长度还是其他?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res