我正在逆转一个android apk,它使用http作为协议,每个http请求包含一个时间戳和一个签名,例如:
http://x/req?....×tamp=1501234567890&signature=....(256-byte rsa signature of timestamp '1501234567890')
param 签名是时间戳(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时,服务器如何验证时间戳?
或者我错过了什么?
答案 0 :(得分:1)
如果公钥从未传送到服务器,则很可能不会验证时间戳。它的作用是将签名用作唯一编号。唯一编号的输入是构建和特定设备,因为设备链接到密钥对。
这个技巧依赖于PKCS#1填充签名是确定性的;如果您两次签署相同的消息,它将生成相同的签名。这一般不是签字方案的必要财产;例如,RSA-PSS产生随机签名。