Bil*_*rey 2 .net c# java android rsacryptoserviceprovider
我正在编写一个Android应用程序,希望验证C#程序生成的字符串是否可信(即由我编写的另一个应用程序生成).为此,我正在签署字符串并将字符串和字符串的哈希值传输到Android设备.我可以在Android应用程序中包含用于创建散列字符串的公钥,因此我不必传输它.产生所有这些的C#代码类似于以下内容:
bytes = ASCIIEncoding.ASCII.GetBytes(someString);
provider = new RSACryptoServiceProvider();
signature = provider.SignData(bytes, new SHA1CryptoServiceProvider());
keyParameters = cryptoProvider.ExportParameters(false);
Run Code Online (Sandbox Code Playgroud)
为了传输数据,我使用以下命令将签名编码为base64:
signatureString = System.Convert.ToBase64String(signature);
我从关键参数手动提取模数和公共指数.它们似乎都是Base64编码.在android应用程序中,我试图验证签名如下:
String modulus = "<modulus string here...>";
String exponent = "<exponent string here...>";
BigInteger BIModulus = new BigInteger(1, Base64.decode(modulus));
BigInteger BIExponent = new BigInteger(1, Base64.decode(exponent));
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(BIModulus, BIExponent);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] decodedBytes = cipher.doFinal(Base64.decode(signature));
Run Code Online (Sandbox Code Playgroud)
当我与decodedBytes原始字符串的SHA1哈希进行比较时,它们是不同的.试图找出原因,我通过大量的记录声明来完成整个过程.似乎模数的BigInteger与C#代码使用的模数不同.指数也是如此.我怀疑这是因为Java的字节类型是无符号的?
那么,有两个问题:
1)我在做什么(或不做)错了?有没有办法手动将模数和指数从一个设备移动到另一个设备以验证签名?
2)有没有办法实现我的目标,那就是在更合适的抽象层次上工作?
问题#1:
您想要验证签名,因此您不应该使用Cipher类而是使用Signature类.
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initVerify(publicKey);
sign.update(someString.getBytes("ASCII"));
boolean ok = sign.verify(Base64.decode(signature));
Run Code Online (Sandbox Code Playgroud)
注意:SHA1withRSA算法使用RSA和SHA-1,如PKCS#1标准中所述.我不是.net专家,我不知道是否RSACryptoServiceProvider.SignData(...)使用此标准.
大多数时候签名密钥都被转移了证书,证书将公钥(RSA案例中的模数+指数)绑定到实体(密钥的所有者,可以是个人,计算机,公司......)
问题2:
当然这取决于你的用例:你为什么需要签名(身份验证,完整性)?你在签什么?
更新:
使用简单的RSA签名,只要使用适当的方案/协议(例如PKCS#1,在任何地方实现,至少1.5版本),都可以.另一种解决方案是使用消息验证代码(如HMAC),它提供身份验证和完整性服务,并使用对称密钥.
要携带公钥,您可以在验证应用程序中对密钥进行硬编码(或使用自签名证书).您必须知道,如果私钥被泄露,丢失或损坏,您将不得不更新所有客户端.第二种解决方案是使用签发签名证书的PKI ; 此解决方案支持密钥撤销和续订,但有一些缺点:设置和维护不那么容易,根据您的需求和环境可能是一种过度杀伤.
| 归档时间: |
|
| 查看次数: |
2764 次 |
| 最近记录: |