计算机开多位数立方根原理,开立方

本文介绍了计算机开多位数立方根的原理和历史,包括古代的开立方方法和现代的计算方法。通过详细步骤解析了如何进行开立方运算,以及历史上《九章算术》中对开立方的记载。文章还讨论了开立方的数学原理和现代求解技巧,适用于理解立方根的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求一个数的立方根的运算方法,叫做开立方。它是立方的逆运算,最早在我国的九章算术中有对开立方的记载。

由于任何实数均有唯一的立方与之对应且不存在两个实数的立方相等,故任何实数都存在且仅存在唯一的立方根。

中文名

开立方

外文名

extraction of cubic root

出    自意    义

求一个数的立方根的运算方法

领    域

数学

相关概念

立方运算

开立方笔算方法

编辑

语音

开立方方法一

1.将被开立方数的整数部分从个位起向左每三位分为一组;

2.根据最左边一组,求得立方根的最高位数;

3.用第一组数减去立方根最高位数的立方,在其右边写上第二组数;

4.用求得的最高位数的平方的300倍试除上述余数,得出试商;并把求得的最高位数的平方的300倍与试商的积、求得的最高位数的30倍与试商的平方的积和试商的立方写在竖式左边,观察其和是否大于余数,若大于,就减小试商再试,若不大于,试商就是立方根的第二位数;

5.用同样方法继续进行下去。

开立方方法二

第1、2步同上。

第三步,商完后,落下余数和后面紧跟着的三位,如果后面没有就把余数后面添上三个0;

第四步,将要试商的数代入式子“已商数×要试商数×(10×已商数+要试商数)×30+要商数的立方”,最接近但不超过第三步得到的数者,即为这一位要商的数。

然后重复第3、4步,直到除尽。

开立方历史记载

编辑

语音

开立方九章算术

《九章算术》中讲了开平方、开立方的方法[1]

,所不同的是古代用筹算进行演算,现以少广章第12题为例,说明古代开平方演算的步骤,“今有积五万五千二百二十五步,问为方几。”答曰:“二百三十五步。”这里所说的步是我国古代的长度单位。

开立方开立方原文

开立方[1]

〔立方适等,求其一面也。〕

术曰:置积为实。借一算,步之,超二等。

〔言千之面十,言百万之面百。〕

议所得,以再乘所借一算为法,而除之。

〔再乘者,亦求为方幂。以上议命而除之,则立方等也。〕

除已,三之为定法。

〔为当复除,故豫张三面,以定方幂为定法也。〕

复除,折而下。

〔复除者,三面方幂以皆自乘之数,须得折、议,定其厚薄尔。开平幂者,

方百之面十࿱

<think>好的,我现在需要解决这个密码题。首先,我得仔细看看题目给出的代码和输出。题目中使用了RSA加密,公钥指数e是0x3,也就是3。然后生成了三个不同的模数n1、n2、n3,分别对同一个明文m进行加密,得到三个密文c1、c2、c3。输出的n和c都是这三个值的列表。 首先,我想到这可能涉及到低加密指数攻击,特别是当e较小且同一明文被多个不同的模数加密的时候。例如,当e=3时,如果三个不同的模数n1、n2、n3互素的话,可能可以使用中国剩余定理(CRT)来恢复m^3,然后直接三次方得到m。 接下来,我需要验证这三个n是否两两互素。也就是说,检查n1和n2的最大公约数是否为1,n1和n3,n2和n3是否也是1。如果它们都互素,那么就可以应用CRT的方法。 假设三个模数互素,那么根据中国剩余定理,可以找到一个数C ≡ c1 mod n1,C ≡ c2 mod n2,C ≡ c3 mod n3。因为加密过程是c_i ≡ m^3 mod n_i,所以根据CRT,存在一个C = m^3 + k*(n1*n2*n3),其中k是一个整数。如果m^3 < n1*n2*n3,那么C其实就是m^3,这时候只需要对C三次方就能得到m。 所以步骤应该是这样的: 1. 使用中国剩余定理将三个同余式合并,求出C ≡ m^3 mod (n1*n2*n3) 2. 计算C的实际值,这里因为n1、n2、n3都是256位的素数乘积,所以m作为flag的字节转换应该比较小,可能满足m^3 < n1*n2*n3。这时候C就是m^3,直接取立方根就能得到m。 3. 将m转换为字节形式,得到flag。 现在需要确认的是这三个n是否两两互素。我需要用Python计算它们的gcd。如果发现其中任意两个n有公因数,那么可能直接分解模数,从而解密。但根据题目代码,n1、n2、n3都是不同的随机生成的256位素数相乘的结果,所以它们应该互素,但需要验证。 接下来,我需要编写Python脚本来实现这个过程。首先,计算三个n之间的gcd。例如,用gmpy2.gcd(n1, n2)看看是否为1。假设它们都是互素的,那么继续使用CRT。 中国剩余定理的实现可以用gmpy2库中的函数,或者自己实现。这里可能需要处理三个同余式。通常,CRT可以分步处理,先合并前两个,再将结果与第三个合并。 具体来说,首先解x ≡ c1 mod n1 和 x ≡ c2 mod n2,得到x ≡ a mod N,其中N = n1*n2。然后再解这个结果与x ≡ c3 mod n3,得到最终的C ≡ m^3 mod (n1*n2*n3)。 在Python中,可以用gmpy2的gcdext函数来求模逆元,或者使用sympy库的crt函数,或者自己实现。这里可能需要手动实现,因为三个模数的情况可能需要分步骤处理。 假设现在三个n是互素的,那么合并后的模数就是n1*n2*n3,此时使用CRT得到C的值,然后对C三次方。这里需要注意,当m^3 < N时,C就是准确的m^3,否则需要更多的信息。但题目中每个n都是两个256位素数的乘积,所以每个n是512位左右,三个n相乘就是约1536位。而m是flag的bytes_to_long,假设flag长度在30字符左右,那么m的位数大概是30*8=240位,m^3是720位左右,远小于1536位,所以可以直接三次方。 所以步骤总结: 1. 验证n1, n2, n3是否两两互素。如果是,继续。 2. 使用中国剩余定理求出C = m^3 mod (n1*n2*n3),此时C = m^3。 3. 对C三次方,得到m。 4. 将m转为字节得到flag。 现在编写代码: 首先检查n之间的gcd: 比如,n1=5567000486226353254524673454357147076118077122275789480555238584552332526459181641567858429587222587683345901310468140782420858931709570476562698953112801 n2=6982887363645354856540867035629441781549999700006363403940951376485517460506822033812812263179663875843737953430050436453298336104404304183964162702612863 计算gcd(n1, n2)是否为1。同样的,检查其他组合。如果都是1,则继续。 然后,用CRT求解三个同余式: x ≡ c1 mod n1 x ≡ c2 mod n2 x ≡ c3 mod n3 合并这三个方程。可以使用递归的方法,先合并前两个,得到x ≡ a mod n1*n2,然后再合并第三个。 假设已经合并前两个得到x ≡ a mod N(N =n1*n2),那么现在需要解: x ≡ a mod N x ≡ c3 mod n3 解法是寻找k,使得 a +k*N ≡ c3 mod n3 →k ≡ (c3 -a)/N mod n3 ? 或者更准确地说,解k ≡ (c3 -a) * inv(N, n3) mod n3。然后解出k的最小非负解,那么x =a +k*N。这个x就是满足前三个条件的解。 这个过程可能需要用到扩展欧几里得算法。或者直接使用gmpy2的crt函数,如果支持的话。 不过,Python的gmpy2库中的crt函数可能只能处理两个同余式,所以需要分步骤处理。例如,首先合并前两个,得到一个新的同余式,然后再与第三个合并。 具体步骤: 合并c1, c2: 设x ≡ c1 mod n1 x ≡ c2 mod n2 根据CRT,解为x ≡ a mod (n1*n2),其中a = c1 + k*n1。代入第二个方程: c1 +k*n1 ≡ c2 mod n2 →k ≡ (c2 -c1) * inv(n1, n2) mod n2 所以k = (c2 -c1) * inv(n1, n2) mod n2 然后a = c1 + k*n1 此时合并后的模数是n1*n2。 然后将这个结果与c3合并: x ≡ a mod n1*n2 x ≡ c3 mod n3 同样的方法,解k': a +k'*n1*n2 ≡ c3 mod n3 →k' ≡ (c3 -a) * inv(n1*n2, n3) mod n3 然后x = a +k'*n1*n2 此时x ≡ m^3 mod (n1*n2*n3) 然后计算x的三次根即可得到m。 现在编写Python代码: 首先,导入必要的库: from gmpy2 import gmpy2 或者import gmpy2 然后,定义n和c的列表: n = [n1, n2, n3] c = [c1, c2, c3] 然后,检查所有n之间是否互素: 比如: import math for i in range(3): for j in range(i+1,3): gcd = math.gcd(n[i],n[j]) if gcd !=1: print(f"n[{i}]和n[{j}]有公因数{gcd}") 这里需要注意到,如果n之间的gcd不为1,那么可以分解n,从而得到私钥解密。但题目中的情况可能三个n都是互素的,所以需要处理这种情况。 假设这里检查后发现gcd都是1,那么继续。 接下来,应用CRT合并三个同余式。可以用sympy的crt函数,或者自己实现。 例如,使用sympy: from sympy.ntheory.modular import crt 但sympy的crt函数可以处理多个模数的情况。例如: C, N = crt([n1, n2, n3], [c1, c2, c3]) 这里的N就是n1*n2*n3,而C是满足所有同余条件的解。 但需要确认是否正确,因为crt的参数是模数列表和余数列表,顺序是否正确。假设参数是moduli和remainders,那么是的。 例如: from sympy.ntheory.modular import crt moduli = [n1, n2, n3] remainders = [c1, c2, c3] C, N = crt(moduli, remainders) 如果成功,那么C就是m^3,然后对C三次方。 但需要注意,sympy的crt函数返回的是解C和模数N,即解为C mod N。这里如果m^3 < N,那么C就是m^3本身。 然后,使用gmpy2的iroot函数来三次方: m_cubed = C m, is_exact = gmpy2.iroot(m_cubed, 3) if is_exact: print(bytes.fromhex(hex(m)[2:]).decode()) 或者将m转换为字节: m_bytes = long_to_bytes(m) print(m_bytes.decode()) 不过,有时候可能需要处理大整数的转换,所以用Crypto.Util.number中的long_to_bytes更方便。 所以,整个脚本的大致流程是: 1. 导入必要的库:gmpy2、sympy的crt函数,以及Crypto.Util.number中的long_to_bytes。 2. 定义n和c的列表。 3. 检查n之间的gcd是否为1,确保互素。 4. 使用sympy的crt函数合并三个同余式,得到C和N。 5. 对C三次方,得到m。 6. 将m转换为字符串。 但需要确认是否安装了sympy库。如果没有,可能需要手动实现CRT。 如果手动实现,合并三个同余式的方法: 合并前两个: def crt2(a1, m1, a2, m2): # 解x ≡ a1 mod m1 # x ≡ a2 mod m2 g, x, y = gmpy2.gcdext(m1, m2) if g !=1: return (None, None) # 不互素,无法合并 lcm = m1 // g * m2 x0 = (a1 + (a2 - a1) * x % (m2//g) * m1) % lcm return (x0, lcm) 然后,合并第三个: a12, m12 = crt2(c1, n1, c2, n2) 然后,再合并a12和c3: a, M = crt2(a12, m12, c3, n3) 这时候,a就是C,即m^3 mod M =n1*n2*n3. 然后计算三次根。 但可能需要注意大整数运算的问题。比如,当n1、n2、n3很大时,合并后的结果可能非常大,但Python可以处理。 现在,假设用sympy的crt函数处理,可能更简单。 不过,我可能需要安装sympy。或者手动分步合并。 现在编写具体代码: 比如,在Python中: from Crypto.Util.number import long_to_bytes import gmpy2 n = [5567000486226353254524673454357147076118077122275789480555238584552332526459181641567858429587222587683345901310468140782420858931709570476562698953112801, 6982887363645354856540867035629441781549999700006363403940951376485517460506822033812812263179663875843737953430050436453298336104404304183964162702612863, 5569628780521526092136759047774448808289588145127191213956593902336353172559905282602383716258500935021056393917971164303539941268395159953652768614304911] c = [4112523544883480830903403452517516825703078902670926405984774762024235980767805538947466914193950835488469608756778569692190967901730207690525300247682815, 4181292472036270897593568708931413787888488621274030741130549434467976405476555130890722346319549396800183827305452019796119873044279138566837264814627098, 3857434270788621361517349247277347831953021241414984430770586220424214110700999615785879462771584952744049357875753754209006439028080870626012342467148773] # 检查n之间是否互素 from math import gcd for i in range(len(n)): for j in range(i+1, len(n)): g = gcd(n[i], n[j]) if g != 1: print(f"n[{i}]和n[{j}]有公因数{g}") # 如果有公因数,可以分解n,但这里假设没有 # 使用中国剩余定理合并三个同余式 def crt(remainders, moduli): # 分步合并 x = remainders[0] m = moduli[0] for i in range(1, len(moduli)): a = remainders[i] n = moduli[i] # 合并x ≡ a mod n # 使用扩展欧几里得算法 g, p, q = gmpy2.gcdext(m, n) if g != 1: raise ValueError("模数不互素") # 新的解为 x + k*m ≡ a mod n →k = (a -x)/g * inv(m/g, n/g) # 但这里g=1,所以k ≡ (a -x) * inv(m) mod n lcm = m // g * n tmp = ( (a - x) * p ) % (n // g) x = x + tmp * m m = lcm return x % m, m # 调用这个函数 remainders = c moduli = n C, N = crt(remainders, moduli) # 现在C是m^3 mod N,其中N =n1*n2*n3 # 计算三次根 m = gmpy2.iroot(C, 3) if m[1]: # 是否精确 print("找到m:", long_to_bytes(int(m[0]))) else: print("未找到精确解") 这样可能可以得到结果。需要注意的是,合并三个同余式的函数是否正确。或者是否应该使用sympy的crt函数。 但手动实现的分步合并是否正确? 例如,对于三个同余式x ≡ c1 mod n1,x≡c2 mod n2,x≡c3 mod n3,首先合并前两个得到x≡a mod n1n2,然后再合并第三个得到x≡C mod n1n2n3。手动实现的函数应该正确。 测试这个函数是否正确: 比如,测试案例,比如三个小模数: n = [3,5,7] c = [2,3,2] 则x=23,因为23 mod3=2, mod5=3, mod7=2. 23^3=12167,三次根是23。 所以,用这个函数的话,合并后的C=23^3,三次根得到23。 所以函数是否在此时正确? 可能,让我们看: 调用crt([2,3,2], [3,5,7]) 第一次循环i=0,初始x=2,m=3. 然后i=1,合并x=2 mod3 与 a=3 mod5: g, p, q = gcdext(3,5) →g=1, p=2, q=-1. 因为 3*2 +5*(-1)=1. 新的解x = x + (a -x)*p *m →也就是2 + (3-2)*2 *3 = 2 +6=8. 然后模lcm=15. 所以x=8 mod15. 然后i=2,合并x=8 mod15 与 a=2 mod7: g=gcdext(15,7) →g=1, p=1, q=-2. 因为15*1 +7*(-2)=1. 所以新的解是x + (a -x)*p *15 →8 + (2-8)*1 *15 →8 + (-6)*15=8-90=-82. mod lcm=105. -82 mod105=23. 所以最终x=23 mod105. 所以C=23,三次根得到23. 正确。 所以这个函数是正确的。 因此,使用这个函数应该能正确合并三个同余式。 然后,当应用到题目中的n和c时,合并得到C=m^3,三次方得到m。 最后,将m转换为字节即可得到flag。 所以,最终的Python脚本大致如下: (需要导入gmpy2和Crypto.Util.number) 不过,可能需要注意数据类型的转换。例如,gmpy2的iroot函数需要输入为mpz类型。 现在,编写完整的代码: from Crypto.Util.number import long_to_bytes import gmpy2 n = [5567000486226353254524673454357147076118077122275789480555238584552332526459181641567858429587222587683345901310468140782420858931709570476562698953112801, 6982887363645354856540867035629441781549999700006363403940951376485517460506822033812812263179663875843737953430050436453298336104404304183964162702612863, 5569628780521526092136759047774448808289588145127191213956593902336353172559905282602383716258500935021056393917971164303539941268395159953652768614304911] c = [4112523544883480830903403452517516825703078902670926405984774762024235980767805538947466914193950835488469608756778569692190967901730207690525300247682815, 4181292472036270897593568708931413787888488621274030741130549434467976405476555130890722346319549396800183827305452019796119873044279138566837264814627098, 3857434270788621361517349247277347831953021241414984430770586220424214110700999615785879462771584952744049357875753754209006439028080870626012342467148773] # 检查n之间的gcd def check_gcd(n_list): for i in range(len(n_list)): for j in range(i+1, len(n_list)): g = gmpy2.gcd(n_list[i], n_list[j]) if g != 1: print(f"n[{i}]和n[{j}]不互素,公因数为{g}") return False return True if not check_gcd(n): print("存在不互素的n,可能使用其他方法解密") else: print("所有n两两互素,继续使用CRT方法") # 定义CRT合并函数 def crt(remainders, moduli): x = remainders[0] m = moduli[0] for i in range(1, len(moduli)): a = remainders[i] n = moduli[i] g, p, q = gmpy2.gcdext(m, n) if g != 1: raise ValueError("Moduli are not coprime") # 计算新的解 lcm = m // g * n tmp = ( (a - x) * p ) % (n // g) x += tmp * m m = lcm x %= m return x, m # 应用CRT try: C, N = crt(c, n) print("成功合并,计算三次根...") # 计算三次根 m, is_cube = gmpy2.iroot(C, 3) if is_cube: print("找到明文m:", m) flag = long_to_bytes(int(m)) print("flag为:", flag.decode()) else: print("C不是完全立方数,可能需要其他方法") except ValueError as e: print(e) 运行这个脚本应该能得到flag。 现在,测试这个脚本。假设所有n互素,CRT合并后的C正确,三次根存在,得到m的字节形式。</think>该题目使用了低加密指数(e=3)和多次加密同一明文的不同模数,可通过中国剩余定理(CRT)结合立方根求解。以下是解题思路和Python脚本: --- ### 解题思路 1. **低加密指数攻击**:由于`e=3`且明文`m`被三个不同的模数`n1, n2, n3`加密,若`m^3 < n1*n2*n3`,则可通过CRT求出`m^3`后直接开立方。 2. **验证互素性**:确保`n1, n2, n3`两两互素(GCD均为1)。 3. **中国剩余定理**:合并三个同余方程,得到`C ≡ m^3 mod (n1*n2*n3)`。 4. **立方根求解**:对`C`三次方得到`m`,转换为字符串即flag。 --- ### Python脚本 ```python from Crypto.Util.number import long_to_bytes import gmpy2 n = [5567000486226353254524673454357147076118077122275789480555238584552332526459181641567858429587222587683345901310468140782420858931709570476562698953112801, 6982887363645354856540867035629441781549999700006363403940951376485517460506822033812812263179663875843737953430050436453298336104404304183964162702612863, 5569628780521526092136759047774448808289588145127191213956593902336353172559905282602383716258500935021056393917971164303539941268395159953652768614304911] c = [4112523544883480830903403452517516825703078902670926405984774762024235980767805538947466914193950835488469608756778569692190967901730207690525300247682815, 4181292472036270897593568708931413787888488621274030741130549434467976405476555130890722346319549396800183827305452019796119873044279138566837264814627098, 3857434270788621361517349247277347831953021241414984430770586220424214110700999615785879462771584952744049357875753754209006439028080870626012342467148773] # 检查n之间的互素性 def check_gcd(n_list): for i in range(len(n_list)): for j in range(i+1, len(n_list)): if gmpy2.gcd(n_list[i], n_list[j]) != 1: return False return True if not check_gcd(n): print("存在不互素的n,无法使用CRT") else: # 合并同余式 def crt(remainders, moduli): x, m = remainders[0], moduli[0] for i in range(1, len(moduli)): a, n = remainders[i], moduli[i] g, p, q = gmpy2.gcdext(m, n) x += (a - x) * p % (n // g) * m m = m // g * n x %= m return x, m C, N = crt(c, n) # 计算立方根 m, is_cube = gmpy2.iroot(C, 3) if is_cube: flag = long_to_bytes(int(m)) print("Flag:", flag.decode()) else: print("无法找到精确立方根") ``` --- ### 执行结果 运行脚本将输出flag。该脚本通过CRT合并密文并求解立方根,最终还原明文。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值