0

我正在反转一个android apk,它使用http作为协议,每个http请求都包含一个时间戳和一个签名,例如:

http://x/req?....&timestamp=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时如何验证时间戳?

还是我错过了什么?

4

1 回答 1

1

如果公钥从未与服务器通信,那么它很可能不会验证时间戳。它的作用是使用签名作为唯一编号。唯一编号的输入是构建和特定设备,因为设备链接到密钥对。

这个技巧依赖于 PKCS#1 填充签名是确定性的。如果您对同一条消息签名两次,它将生成相同的签名。这通常不是签名方案的必需属性;例如 RSA-PSS 产生一个随机签名。

于 2017-08-27T08:39:28.240 回答