【发布时间】:2017-08-26 15:48:24
【问题描述】:
我正在反转一个android apk,它使用http作为协议,每个http请求都包含一个时间戳和一个签名,例如:
http://x/req?....×tamp=1501234567890&signature=....(256-byte rsa signature of timestamp '1501234567890')
参数签名是时间戳(1501234567890)的sha256WithRSA签名。我猜原因是它保证数据包只在一段时间内有效,并且用户不能修改时间戳,因为它不会通过签名验证。
但奇怪的是,apk 使用随机生成的 RSA KeyPair 对时间戳进行签名。 apk在第一次启动时会生成KeyPair,我知道RSA验证需要public_key,但是apk不会将public_key发送到服务器(服务器不会知道public_key)。服务器如何验证?
apk 生成 KeyPair 如下:
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
cal.add(Calendar.YEAR, 1);
Date end = cal.getTime();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext())
.setAlias(alias)
.setStartDate(now)
.setEndDate(end)
.setSerialNumber(BigInteger.valueOf(1))
.setSubject(new X500Principal("CN=test1"))
.build());
KeyPair kp = kpg.generateKeyPair();
服务器不知道public_key时如何验证时间戳?
还是我错过了什么?
【问题讨论】:
-
这个问题可能更适合crypto。几点观察。 1)你可能会因为你正在倒车而错过了一些东西。 2) RSA 公钥由模数和公共指数组成,默认为 65537,因此您只缺少模数。 3) 通过几到三个观察,可以在没有太多 CPU 的情况下恢复未知模数,但是没有理智的人会故意设计一个协议来要求在服务器端进行这么多的计算。
-
为了恢复模数,我们观察 t1^d = y1 mod n 和 t2^d = y2 mod n,我们不知道 d 或 n。我们确实知道 e,所以 y1^e = t1 mod n 和 y2^e = t2 mod n。所以 y1^e - t1 = 0 mod n 和 y2^e - t2 = 0 mod n,其中 y1^e 和 y2^e 的计算没有模归约,所以它们是大约每个 17 兆比特。由于 n 除以这两个量,它必须除以它们的 GCD(以非常高的概率)。所以计算 GCD(y1^e - t1, y2^e - t2) 和 n 将是一个因素,可能是唯一的大因素。如果去除其他因素太难,请使用另一个观测值并计算另一个 GCD。
标签: rsa signing rsa-sha256