首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不同代码在单元测试和运行时的行为

不同代码在单元测试和运行时的行为
EN

Stack Overflow用户
提问于 2018-11-22 16:26:32
回答 1查看 312关注 0票数 0

相同的代码在运行时工作,在测试中不工作。

有这样的代码

代码语言:javascript
复制
private fun generatePrivateKeyFromText(key: String): Key {
    val kf = KeyFactory.getInstance("RSA")
    val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
    return kf.generatePrivate(keySpecPKCS8)
}

当我运行或调试应用程序时,它工作正常,但这段代码在generatePrivate上失败,而测试

代码语言:javascript
复制
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
代码语言:javascript
复制
@Test
fun decrypt() {
    val encrypt = "MoRxCpLJNqxfXGVeU73zZFi+X2j2TLUTyIn1XRqCoEfeN8rNBR/YrEtumAz+8/0AaEsvx0+qTilfbw+edZd8Wfum4McWQ8oWXifvWLgoXybhxWUmCdi2fwA9Gw0parY6CSNYUDA2UuLrLLaDGMz/Jj4s4XmXKp5zuec1zXVdrPM="
    val prkey = "MIICXAIBAAKBgQCAaTCQOxAZPfTXfgel2MMPUCLAf32TxfsXu71/c3mVFGtDPB+7IpmxCmEvAv6nlq1ymX1zRR5gIzNt4DZoM0RhE58eoksUXcmFcRnMX5V4bnI8DitHLdB2EZzdvnPX0Umzs+tE7I1ouDIocNQRsEoQeDcNPfz5av2zMPsg0Xl/yQIDAQABAoGAV8UOX5cvQsGZZ+2J1q8ZbI8OodrCf83z+V3mgYXxVZe2VSd0XNmiiWMZ2CNI4k3YUhtdpvtYbsfAsFpvdbuNAXMW82Zwsd0oluPzzoLELGkFvaUJlh2YGmizrBnEwvF0usJYwjsjUbXw3o1xKX8ILk5FBfdr2+L65YIIZ0UhqoECQQD/B0P8iZhoOTx7myhwlFCuVeSadwaOMGy2CgXRLvTFAtstz8YVO+D+yPKsEpAvMlFgEnkTt7tl8DRxMpKnfmO5AkEAgOZudjUD72xWfSJpCEcX76WGSASWE+fLCZ8C/HumIZ+0trW5/bsmBrI/6SldEJcy4b2bHh2nOggC/6R5rEUkkQJAAg779IDj0wuLOnAxLl90G0QkOT72tZUce4evLlYTsbdpL4B619cI5OWYV906frcIQx9DDO6xu4vp0HQZDPMPOQJAOVbH8ntY2ctmmdmRwWXmpusJ1cV8gTROJGSArpHOcAycFd628sCqhLYMKgsFZBjuQG7YrsfgGLdxpgijO1eykQJBAOE8+BrQwFWyOcgnUShPHo8mDOBkeplGr9VZdnWktac2aBr1Biovy+pipUyjSCAaFgOsSU0FDcK0I5ulTOpgMRg="
    val decrypt = CryptoService.decrypt(encrypt, prkey)
    assertEquals("Pika-pika", decrypt)
}
代码语言:javascript
复制
fun decrypt(ciphertext: String, key: String): String {
    var decodedBytes: ByteArray? = null
    try {
        val c = Cipher.getInstance("RSA")
        c.init(Cipher.DECRYPT_MODE, generatePrivateKeyFromText(key))
        decodedBytes = c.doFinal(Base64.decodeBase64(ciphertext))

    } catch (e: Exception) {
        Log.e("Crypto", "RSA decryption error: $e")
    }
    return String(decodedBytes ?: ByteArray(0))
}

工作功能零碎

代码语言:javascript
复制
 private fun testCrypto() {
        val encrypt = "MoRxCpLJNqxfXGVeU73zZFi+X2j2TLUTyIn1XRqCoEfeN8rNBR/YrEtumAz+8/0AaEsvx0+qTilfbw+edZd8Wfum4McWQ8oWXifvWLgoXybhxWUmCdi2fwA9Gw0parY6CSNYUDA2UuLrLLaDGMz/Jj4s4XmXKp5zuec1zXVdrPM="
        val prkey = "MIICXAIBAAKBgQCAaTCQOxAZPfTXfgel2MMPUCLAf32TxfsXu71/c3mVFGtDPB+7IpmxCmEvAv6nlq1ymX1zRR5gIzNt4DZoM0RhE58eoksUXcmFcRnMX5V4bnI8DitHLdB2EZzdvnPX0Umzs+tE7I1ouDIocNQRsEoQeDcNPfz5av2zMPsg0Xl/yQIDAQABAoGAV8UOX5cvQsGZZ+2J1q8ZbI8OodrCf83z+V3mgYXxVZe2VSd0XNmiiWMZ2CNI4k3YUhtdpvtYbsfAsFpvdbuNAXMW82Zwsd0oluPzzoLELGkFvaUJlh2YGmizrBnEwvF0usJYwjsjUbXw3o1xKX8ILk5FBfdr2+L65YIIZ0UhqoECQQD/B0P8iZhoOTx7myhwlFCuVeSadwaOMGy2CgXRLvTFAtstz8YVO+D+yPKsEpAvMlFgEnkTt7tl8DRxMpKnfmO5AkEAgOZudjUD72xWfSJpCEcX76WGSASWE+fLCZ8C/HumIZ+0trW5/bsmBrI/6SldEJcy4b2bHh2nOggC/6R5rEUkkQJAAg779IDj0wuLOnAxLl90G0QkOT72tZUce4evLlYTsbdpL4B619cI5OWYV906frcIQx9DDO6xu4vp0HQZDPMPOQJAOVbH8ntY2ctmmdmRwWXmpusJ1cV8gTROJGSArpHOcAycFd628sCqhLYMKgsFZBjuQG7YrsfgGLdxpgijO1eykQJBAOE8+BrQwFWyOcgnUShPHo8mDOBkeplGr9VZdnWktac2aBr1Biovy+pipUyjSCAaFgOsSU0FDcK0I5ulTOpgMRg="
        val decrypt = CryptoService.decrypt(encrypt, prkey)
        println(decrypt) // "Pika-pika"
    }

我在onViewCreated上叫它

更新:

我添加了BC提供者(谢谢,@JamesKPolk)

代码语言:javascript
复制
private fun generatePrivateKeyFromText(key: String): Key {
    Security.addProvider(BouncyCastleProvider())
    val kf = KeyFactory.getInstance(algorithm)
    val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
    return kf.generatePrivate(keySpecPKCS8)
}

但在运行时和中仍然是ok,而不是在测试时。

代码语言:javascript
复制
javax.crypto.BadPaddingException: Decryption error

因此,不同运行代码的问题没有解决。

运行时和测试哪个崩溃的代码有什么区别?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-22 16:44:25

问题是私钥不是a PKCS8EncodedKeySpec,而是来自PKCS#1的RSAPrivateKey对象。然而,BC提供程序仍然会毫无怨言地对此错误进行解码。然而,其他供应商也有理由抱怨。我的猜测是运行时使用的是旧版本的Android,默认提供程序是BC,但是您的测试使用的是新版本,而不是这种情况。

解决方法是使您的私钥成为适当的PKCS8EncodedKeySpec。或者,您可以显式地请求"BC“提供程序。为此,需要在getInstance()调用:val keyFactory = KeyFactory.getInstance("RSA", "BC")中指定"BC“

但是,请注意,它似乎是BC提供程序支持即将结束。

要将私钥转换成PKCS#1格式,可以将‘BEGINRSA私有密钥’-样式的页眉和页脚环绕在base64 blob周围,或者解码base64 blob并将其放入文件中,然后运行:

代码语言:javascript
复制
openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A

代码语言:javascript
复制
openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A

第二个问题来自于依赖默认值。而不是做

代码语言:javascript
复制
val c = Cipher.getInstance("RSA")

这将获得模式和填充的默认值,因此是不可移植的,因此始终指定完整的“算法/模式/填充”转换字符串到Cipher.getInstance()。在这种情况下,数据似乎没有填充(一种不安全的模式),您需要类似的内容

代码语言:javascript
复制
val c = Cipher.getInstance("RSA/ECB/NoPadding")

然而,您确实应该使用适当的随机填充,目前这是OAEP填充。

摘要

运行时环境是Android,但我认为测试环境是Oracle Java (或者openjdk)。显然,在这些环境中有两个关键的区别:

  1. 安卓使用BC提供者的KeyFactory,它将处理私钥编码的PKCS#1 RSAPrivateKey格式。Oracle只支持PKCS8编码的密钥。
  2. 在Android中,Cipher.getInstance("RSA")默认为Cipher.getInstance("RSA/ECB/NoPadding"),但Oracle默认为Cipher.getInstance("RSA/ECB/PKCS1Padding")
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53435000

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档