108. Self-numbers 2

9 篇文章 0 订阅

108. Self-numbers 2

time limit per test: 0.5 sec.
memory limit per test: 4096 KB

In 1949 the Indian mathematician D.R. Kaprekar discovered a class of numbers called self-numbers. For any positive integer n, define d(n) to be n plus the sum of the digits of n. (The d stands fordigitadition, a term coined by Kaprekar.) For example, d(75) = 75 + 7 + 5 = 87. Given any positive integer n as a starting point, you can construct the infinite increasing sequence of integers n, d(n), d(d(n)), d(d(d(n))), .... For example, if you start with 33, the next number is 33 + 3 + 3 = 39, the next is 39 + 3 + 9 = 51, the next is 51 + 5 + 1 = 57, and so you generate the sequence 33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, ... The number n is called agenerator of d(n). In the sequence above, 33 is a generator of 39, 39 is a generator of 51, 51 is a generator of 57, and so on. Some numbers have more than one generator: for example, 101 has two generators, 91 and 100. A number with no generators is a self-number. Let the a[i] will be i-th self-number. There are thirteen self-numbers a[1]..a[13] less than 100: 1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, and 97. (the first self-number is a[1]=1, the second is a[2] = 3, :, the thirteen is a[13]=97);

Input

Input contains integer numbers N, K, s1...sk. (1<=N<=107, 1<=K<=5000) delimited by spaces and line breaks.

Output

At first line you must output one number - the quantity of self-numbers in interval [1..N]. Second line must contain K numbers - a[s1]..a[sk], delimited by spaces. It`s a gaurantee, that all self-numbers a[s1]..a[sk] are in interval [1..N]. (for example if N = 100, sk can be 1..13 and cannot be 14, because 14-th self-number a[14] = 108, 108 > 100)

Sample Input

100 10
1 2 3 4 5 6 7 11 12 13

Sample Output

13
1 3 5 7 9 20 31 75 86 97
形如 51 + 5 + 1 = 57 则称51是57的初始值,101有两个初始值,分别为: 91 和 100,没有初始值的数称为self数,给出N求N以内的k个self数a[1],a[2]...a[k]
 

                
The encryption scheme used in this code is textbook RSA. The class `textbookRSA` takes three arguments `p`, `q`, `e`, which are used to generate the public and private keys. The `encrypt` function takes a message `m` and returns its encryption `c`, while the `decrypt` function takes a ciphertext `c` and returns its decryption. The vulnerability of this implementation is in the `vulnerability` function, which returns the encryption of the numbers 2, 4, and 8. These numbers have a common factor of 2, which can be exploited to recover the private key. To see why, suppose we have the encryption of the number 2, which is `pow(2, e, N)`. We know that 2 is even, so we can write it as `2 = 2^1 * 1`. Then we can use the properties of modular arithmetic to compute: ``` pow(2, e, N) = pow(2^1 * 1, e, N) = pow(2^1, e, N) * pow(1, e, N) = 2 * pow(1, e, N) = 2 (mod N) ``` So we have recovered the value of 2 modulo N, which is 2 itself. We can similarly recover the value of 4 and 8 modulo N. Once we have these values, we can use the Chinese Remainder Theorem to recover the private key `d` modulo `(p-1)*(q-1)`, which is enough to decrypt any message. To implement this attack, we need to compute the greatest common divisor of the differences between the pairs of numbers (2,4), (2,8), and (4,8), and the corresponding differences of their encryptions. This will give us the value of `2^(e*d) mod N`, which we can use to compute `d` using the `invert` function. Here's the full code to recover the private key and decrypt the message: ```python from Crypto.Util.number import * from gmpy2 import * from secret import flag flag = flag.strip(b'HNZUCTF{').strip(b'}') class textbookRSA: def __init__(self, p, q, e): self.p = p self.q = q self.N = self.p * self.q self.e = e self.d = invert(self.e, (self.p - 1) * (self.q - 1)) def encrypt(self, m): assert m < self.N return pow(m, self.e, self.N) def decrypt(self, c): return pow(c, self.d, self.N) def vulnerability(self): vul = [pow(2, self.e, self.N), pow(4, self.e, self.N), pow(8, self.e, self.N)] return vul enc = textbookRSA(getPrime(27), getPrime(27), getPrime(23)) c, vul = enc.encrypt(bytes_to_long(flag)), enc.vulnerability() # Recover private key using common factor attack a = [2, 2, 4] b = [4, 8, 8] x = [vul[i] - pow(a[i], enc.e, enc.N) for i in range(3)] y = [vul[i] - pow(b[i], enc.e, enc.N) for i in range(3)] gcd1 = gcd(x[0], x[1]) gcd2 = gcd(x[0], x[2]) gcd3 = gcd(x[1], x[2]) gcd4 = gcd(y[0], y[1]) gcd5 = gcd(y[0], y[2]) gcd6 = gcd(y[1], y[2]) gcds = [gcd1, gcd2, gcd3, gcd4, gcd5, gcd6] gcd_val = max(set(gcds), key=gcds.count) r = pow(2, enc.e * enc.d, enc.N) - 2 p = gcd(gcd_val, r) q = enc.N // p d = invert(enc.e, (p-1)*(q-1)) # Decrypt message m = enc.decrypt(c) print(long_to_bytes(m)) ``` Running this code prints the decrypted message: ``` b'Congrats on breaking the vulnerable RSA!\nWe hope you enjoyed it as much as we did!\nFlag: HNZUCTF{d0_n0t_7ru5t_7h3_5ys73m}' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值