我需要使用 Java/Android 和在 .Net 环境中创建的 ATEC108A 芯片验证签名。(使用 SunEC 和 AndroidOpenSSL)
签名使用 BCrypt 在 .Net 中创建,密钥也使用 BCrypt 创建并存储在 Microsoft 密钥库中。签名和公钥可以发送到 AT 芯片并进行验证,但它不适用于 Android。
密钥/签名过程:
公钥以 x.509 密钥格式从 BCrypt 导出,其中包括 SHA256-ECDSA 的标识符和曲线 prime256v1,导致:
3059301306072A8648CE3D020106082A 8648CE3D03010703420004368711132B BDB4C6D03F7DF4F4688F5F4F21A3B30B EB1016648555A25B27C915CAB5C26B98 0FF792A0090BF1E131C175D9C66C8D79 3476489770869E09273816
BCrypt 的签名是 64 字节格式,但 android 需要序列和长度标识符,从而导致签名如下:
304502201 BD91B39A7447724223A4B3E9070A6FD5 33360F96B072998058AA73E572F48D80 22100 ED0BDC731080CFC82C8B8FB37D74CC18 3820343C2756671F0E1D813E469DD3D7
用于签名和验证的消息是“Hello World”,其散列为:
A591A6D40BF420404A011733CFB7B190 D62C65BF0BCDA32B57B277D9AD9F146E
安卓进程:
从上述密钥字节数组创建 X509 密钥规范和公钥:
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); KeyFactory kf = KeyFactory.getInstance("EC", "AndroidOpenSSL"); pubKey = kf.generatePublic(keySpec);
使用 AndroidOpenSSL 提供程序创建签名:
签名签名; 签名 = Signature.getInstance("SHA256withECDSA", "AndroidOpenSSL"); 签名.initVerify(pubKey);
加载上面的哈希数组:
签名.更新(哈希);
验证上述签名:
签名。验证(签名);
上面的签名和密钥在 AT 芯片上签出(也在运行 JavaScript-OpenSSL 的 ECDSA 示例上验证),但未通过 AndroidOpenSSL 验证。我错过了一些简单的东西还是问题出在哪里?
公钥结构在 ASN.1 解码器上检查并在代码中成功加载(从公钥中提取和检查),签名采用 Java 的预期格式,并且两侧的哈希值相同。