different code's behavior in unit test and in runtime











up vote
0
down vote

favorite












The same code works in runtime and doesnt work in test



There is such code



private fun generatePrivateKeyFromText(key: String): Key {
val kf = KeyFactory.getInstance("RSA")
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


When I run or debug app it works ok, but this code fails on generatePrivate while testing



java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence




@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)
}




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))
}




Working function is in Fragment



 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"
}


I call it on onViewCreated





Updated:



I added BC provider (thanks, @JamesKPolk)



private fun generatePrivateKeyFromText(key: String): Key {
Security.addProvider(BouncyCastleProvider())
val kf = KeyFactory.getInstance(algorithm)
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


But it is still ok in runtime and not while testing



javax.crypto.BadPaddingException: Decryption error


So problem for different running code didnt go.



What the difference between runtime and test which crashes code?










share|improve this question
























  • ah, but that's a different error than the 1st one.
    – James K Polk
    Nov 22 at 17:15










  • And again only in unit test. I rewrote text and header so.
    – Kirill Matrosov
    Nov 22 at 17:16










  • I use org.apache.commons.codec.binary.Base64 . The case about it is described here
    – Kirill Matrosov
    Nov 22 at 17:22










  • ahhh, so the unit tests don't really run on Android.
    – James K Polk
    Nov 22 at 17:27






  • 1




    See my latest edits to my answer.
    – James K Polk
    Nov 22 at 17:53















up vote
0
down vote

favorite












The same code works in runtime and doesnt work in test



There is such code



private fun generatePrivateKeyFromText(key: String): Key {
val kf = KeyFactory.getInstance("RSA")
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


When I run or debug app it works ok, but this code fails on generatePrivate while testing



java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence




@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)
}




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))
}




Working function is in Fragment



 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"
}


I call it on onViewCreated





Updated:



I added BC provider (thanks, @JamesKPolk)



private fun generatePrivateKeyFromText(key: String): Key {
Security.addProvider(BouncyCastleProvider())
val kf = KeyFactory.getInstance(algorithm)
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


But it is still ok in runtime and not while testing



javax.crypto.BadPaddingException: Decryption error


So problem for different running code didnt go.



What the difference between runtime and test which crashes code?










share|improve this question
























  • ah, but that's a different error than the 1st one.
    – James K Polk
    Nov 22 at 17:15










  • And again only in unit test. I rewrote text and header so.
    – Kirill Matrosov
    Nov 22 at 17:16










  • I use org.apache.commons.codec.binary.Base64 . The case about it is described here
    – Kirill Matrosov
    Nov 22 at 17:22










  • ahhh, so the unit tests don't really run on Android.
    – James K Polk
    Nov 22 at 17:27






  • 1




    See my latest edits to my answer.
    – James K Polk
    Nov 22 at 17:53













up vote
0
down vote

favorite









up vote
0
down vote

favorite











The same code works in runtime and doesnt work in test



There is such code



private fun generatePrivateKeyFromText(key: String): Key {
val kf = KeyFactory.getInstance("RSA")
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


When I run or debug app it works ok, but this code fails on generatePrivate while testing



java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence




@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)
}




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))
}




Working function is in Fragment



 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"
}


I call it on onViewCreated





Updated:



I added BC provider (thanks, @JamesKPolk)



private fun generatePrivateKeyFromText(key: String): Key {
Security.addProvider(BouncyCastleProvider())
val kf = KeyFactory.getInstance(algorithm)
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


But it is still ok in runtime and not while testing



javax.crypto.BadPaddingException: Decryption error


So problem for different running code didnt go.



What the difference between runtime and test which crashes code?










share|improve this question















The same code works in runtime and doesnt work in test



There is such code



private fun generatePrivateKeyFromText(key: String): Key {
val kf = KeyFactory.getInstance("RSA")
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


When I run or debug app it works ok, but this code fails on generatePrivate while testing



java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence




@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)
}




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))
}




Working function is in Fragment



 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"
}


I call it on onViewCreated





Updated:



I added BC provider (thanks, @JamesKPolk)



private fun generatePrivateKeyFromText(key: String): Key {
Security.addProvider(BouncyCastleProvider())
val kf = KeyFactory.getInstance(algorithm)
val keySpecPKCS8 = PKCS8EncodedKeySpec(Base64.decodeBase64(key))
return kf.generatePrivate(keySpecPKCS8)
}


But it is still ok in runtime and not while testing



javax.crypto.BadPaddingException: Decryption error


So problem for different running code didnt go.



What the difference between runtime and test which crashes code?







android kotlin






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 28 at 17:54









Jayson Minard

36.9k15106170




36.9k15106170










asked Nov 22 at 16:26









Kirill Matrosov

1,4991822




1,4991822












  • ah, but that's a different error than the 1st one.
    – James K Polk
    Nov 22 at 17:15










  • And again only in unit test. I rewrote text and header so.
    – Kirill Matrosov
    Nov 22 at 17:16










  • I use org.apache.commons.codec.binary.Base64 . The case about it is described here
    – Kirill Matrosov
    Nov 22 at 17:22










  • ahhh, so the unit tests don't really run on Android.
    – James K Polk
    Nov 22 at 17:27






  • 1




    See my latest edits to my answer.
    – James K Polk
    Nov 22 at 17:53


















  • ah, but that's a different error than the 1st one.
    – James K Polk
    Nov 22 at 17:15










  • And again only in unit test. I rewrote text and header so.
    – Kirill Matrosov
    Nov 22 at 17:16










  • I use org.apache.commons.codec.binary.Base64 . The case about it is described here
    – Kirill Matrosov
    Nov 22 at 17:22










  • ahhh, so the unit tests don't really run on Android.
    – James K Polk
    Nov 22 at 17:27






  • 1




    See my latest edits to my answer.
    – James K Polk
    Nov 22 at 17:53
















ah, but that's a different error than the 1st one.
– James K Polk
Nov 22 at 17:15




ah, but that's a different error than the 1st one.
– James K Polk
Nov 22 at 17:15












And again only in unit test. I rewrote text and header so.
– Kirill Matrosov
Nov 22 at 17:16




And again only in unit test. I rewrote text and header so.
– Kirill Matrosov
Nov 22 at 17:16












I use org.apache.commons.codec.binary.Base64 . The case about it is described here
– Kirill Matrosov
Nov 22 at 17:22




I use org.apache.commons.codec.binary.Base64 . The case about it is described here
– Kirill Matrosov
Nov 22 at 17:22












ahhh, so the unit tests don't really run on Android.
– James K Polk
Nov 22 at 17:27




ahhh, so the unit tests don't really run on Android.
– James K Polk
Nov 22 at 17:27




1




1




See my latest edits to my answer.
– James K Polk
Nov 22 at 17:53




See my latest edits to my answer.
– James K Polk
Nov 22 at 17:53












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










The issue is that the private key is not a PKCS8EncodedKeySpec, but rather an RSAPrivateKey object from PKCS#1. The BC provider, however, will still decode this mistake without complaint. However, other providers will rightfully complain. My guess is that the runtime is using an older version of Android where the default provider is BC, but your test is using a newer version where that isn't the case.



The fix is to make your private key a proper PKCS8EncodedKeySpec. Alternatively, you can explicitly request the "BC" provider. To do so, you need to specify "BC" in the getInstance() call: val keyFactory = KeyFactory.getInstance("RSA", "BC")



However, note that it appears that BC provider support is on its way out.



To convert a private key in the PKCS#1 format, either wrap a 'BEGIN RSA PRIVATE KEY'-style header and footer around the base64 blob or decode the base64 blob and place that in a file, then run:



openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A


or



openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A


A second issue comes from relying on defaults. Instead of doing



val c = Cipher.getInstance("RSA")


which gets you defaults for mode and padding and thus is non-portable, always specify the full "algorithm/mode/padding" transformation string to Cipher.getInstance(). In you case, it appears the data is not padded (an insecure mode) you'd need something like



val c = Cipher.getInstance("RSA/ECB/NoPadding")


However, you really should use proper randomized padding, and currently that is OAEP padding.



Summary



The runtime environment is Android, but I think the test environment is Oracle Java (or maybe openjdk). There are evidently two critical differences in those environments:




  1. Android uses the BC provider for KeyFactory which will handle private keys encoded in PKCS#1 RSAPrivateKey format. Oracle Java only supports PKCS8 encoded keys.

  2. In Android, Cipher.getInstance("RSA") defaults to Cipher.getInstance("RSA/ECB/NoPadding"), but Oracle Java defaults to Cipher.getInstance("RSA/ECB/PKCS1Padding")






share|improve this answer























  • I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
    – Kirill Matrosov
    Nov 22 at 16:49










  • I will try to experiment with your code but I'm not a Kotlin programmer.
    – James K Polk
    Nov 22 at 17:07










  • It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
    – Kirill Matrosov
    Nov 23 at 8:52






  • 1




    I'll add that info to the answer. Let me know if it still remains unclear.
    – James K Polk
    Nov 23 at 14:16











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435000%2fdifferent-codes-behavior-in-unit-test-and-in-runtime%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










The issue is that the private key is not a PKCS8EncodedKeySpec, but rather an RSAPrivateKey object from PKCS#1. The BC provider, however, will still decode this mistake without complaint. However, other providers will rightfully complain. My guess is that the runtime is using an older version of Android where the default provider is BC, but your test is using a newer version where that isn't the case.



The fix is to make your private key a proper PKCS8EncodedKeySpec. Alternatively, you can explicitly request the "BC" provider. To do so, you need to specify "BC" in the getInstance() call: val keyFactory = KeyFactory.getInstance("RSA", "BC")



However, note that it appears that BC provider support is on its way out.



To convert a private key in the PKCS#1 format, either wrap a 'BEGIN RSA PRIVATE KEY'-style header and footer around the base64 blob or decode the base64 blob and place that in a file, then run:



openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A


or



openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A


A second issue comes from relying on defaults. Instead of doing



val c = Cipher.getInstance("RSA")


which gets you defaults for mode and padding and thus is non-portable, always specify the full "algorithm/mode/padding" transformation string to Cipher.getInstance(). In you case, it appears the data is not padded (an insecure mode) you'd need something like



val c = Cipher.getInstance("RSA/ECB/NoPadding")


However, you really should use proper randomized padding, and currently that is OAEP padding.



Summary



The runtime environment is Android, but I think the test environment is Oracle Java (or maybe openjdk). There are evidently two critical differences in those environments:




  1. Android uses the BC provider for KeyFactory which will handle private keys encoded in PKCS#1 RSAPrivateKey format. Oracle Java only supports PKCS8 encoded keys.

  2. In Android, Cipher.getInstance("RSA") defaults to Cipher.getInstance("RSA/ECB/NoPadding"), but Oracle Java defaults to Cipher.getInstance("RSA/ECB/PKCS1Padding")






share|improve this answer























  • I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
    – Kirill Matrosov
    Nov 22 at 16:49










  • I will try to experiment with your code but I'm not a Kotlin programmer.
    – James K Polk
    Nov 22 at 17:07










  • It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
    – Kirill Matrosov
    Nov 23 at 8:52






  • 1




    I'll add that info to the answer. Let me know if it still remains unclear.
    – James K Polk
    Nov 23 at 14:16















up vote
1
down vote



accepted










The issue is that the private key is not a PKCS8EncodedKeySpec, but rather an RSAPrivateKey object from PKCS#1. The BC provider, however, will still decode this mistake without complaint. However, other providers will rightfully complain. My guess is that the runtime is using an older version of Android where the default provider is BC, but your test is using a newer version where that isn't the case.



The fix is to make your private key a proper PKCS8EncodedKeySpec. Alternatively, you can explicitly request the "BC" provider. To do so, you need to specify "BC" in the getInstance() call: val keyFactory = KeyFactory.getInstance("RSA", "BC")



However, note that it appears that BC provider support is on its way out.



To convert a private key in the PKCS#1 format, either wrap a 'BEGIN RSA PRIVATE KEY'-style header and footer around the base64 blob or decode the base64 blob and place that in a file, then run:



openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A


or



openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A


A second issue comes from relying on defaults. Instead of doing



val c = Cipher.getInstance("RSA")


which gets you defaults for mode and padding and thus is non-portable, always specify the full "algorithm/mode/padding" transformation string to Cipher.getInstance(). In you case, it appears the data is not padded (an insecure mode) you'd need something like



val c = Cipher.getInstance("RSA/ECB/NoPadding")


However, you really should use proper randomized padding, and currently that is OAEP padding.



Summary



The runtime environment is Android, but I think the test environment is Oracle Java (or maybe openjdk). There are evidently two critical differences in those environments:




  1. Android uses the BC provider for KeyFactory which will handle private keys encoded in PKCS#1 RSAPrivateKey format. Oracle Java only supports PKCS8 encoded keys.

  2. In Android, Cipher.getInstance("RSA") defaults to Cipher.getInstance("RSA/ECB/NoPadding"), but Oracle Java defaults to Cipher.getInstance("RSA/ECB/PKCS1Padding")






share|improve this answer























  • I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
    – Kirill Matrosov
    Nov 22 at 16:49










  • I will try to experiment with your code but I'm not a Kotlin programmer.
    – James K Polk
    Nov 22 at 17:07










  • It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
    – Kirill Matrosov
    Nov 23 at 8:52






  • 1




    I'll add that info to the answer. Let me know if it still remains unclear.
    – James K Polk
    Nov 23 at 14:16













up vote
1
down vote



accepted







up vote
1
down vote



accepted






The issue is that the private key is not a PKCS8EncodedKeySpec, but rather an RSAPrivateKey object from PKCS#1. The BC provider, however, will still decode this mistake without complaint. However, other providers will rightfully complain. My guess is that the runtime is using an older version of Android where the default provider is BC, but your test is using a newer version where that isn't the case.



The fix is to make your private key a proper PKCS8EncodedKeySpec. Alternatively, you can explicitly request the "BC" provider. To do so, you need to specify "BC" in the getInstance() call: val keyFactory = KeyFactory.getInstance("RSA", "BC")



However, note that it appears that BC provider support is on its way out.



To convert a private key in the PKCS#1 format, either wrap a 'BEGIN RSA PRIVATE KEY'-style header and footer around the base64 blob or decode the base64 blob and place that in a file, then run:



openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A


or



openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A


A second issue comes from relying on defaults. Instead of doing



val c = Cipher.getInstance("RSA")


which gets you defaults for mode and padding and thus is non-portable, always specify the full "algorithm/mode/padding" transformation string to Cipher.getInstance(). In you case, it appears the data is not padded (an insecure mode) you'd need something like



val c = Cipher.getInstance("RSA/ECB/NoPadding")


However, you really should use proper randomized padding, and currently that is OAEP padding.



Summary



The runtime environment is Android, but I think the test environment is Oracle Java (or maybe openjdk). There are evidently two critical differences in those environments:




  1. Android uses the BC provider for KeyFactory which will handle private keys encoded in PKCS#1 RSAPrivateKey format. Oracle Java only supports PKCS8 encoded keys.

  2. In Android, Cipher.getInstance("RSA") defaults to Cipher.getInstance("RSA/ECB/NoPadding"), but Oracle Java defaults to Cipher.getInstance("RSA/ECB/PKCS1Padding")






share|improve this answer














The issue is that the private key is not a PKCS8EncodedKeySpec, but rather an RSAPrivateKey object from PKCS#1. The BC provider, however, will still decode this mistake without complaint. However, other providers will rightfully complain. My guess is that the runtime is using an older version of Android where the default provider is BC, but your test is using a newer version where that isn't the case.



The fix is to make your private key a proper PKCS8EncodedKeySpec. Alternatively, you can explicitly request the "BC" provider. To do so, you need to specify "BC" in the getInstance() call: val keyFactory = KeyFactory.getInstance("RSA", "BC")



However, note that it appears that BC provider support is on its way out.



To convert a private key in the PKCS#1 format, either wrap a 'BEGIN RSA PRIVATE KEY'-style header and footer around the base64 blob or decode the base64 blob and place that in a file, then run:



openssl pkcs8 -topk8 -in privkey.pem  -outform der -nocrypt | openssl base64 -A


or



openssl pkcs8 -topk8 -in privkey.der -inform der -nocrypt  | openssl base64 -A


A second issue comes from relying on defaults. Instead of doing



val c = Cipher.getInstance("RSA")


which gets you defaults for mode and padding and thus is non-portable, always specify the full "algorithm/mode/padding" transformation string to Cipher.getInstance(). In you case, it appears the data is not padded (an insecure mode) you'd need something like



val c = Cipher.getInstance("RSA/ECB/NoPadding")


However, you really should use proper randomized padding, and currently that is OAEP padding.



Summary



The runtime environment is Android, but I think the test environment is Oracle Java (or maybe openjdk). There are evidently two critical differences in those environments:




  1. Android uses the BC provider for KeyFactory which will handle private keys encoded in PKCS#1 RSAPrivateKey format. Oracle Java only supports PKCS8 encoded keys.

  2. In Android, Cipher.getInstance("RSA") defaults to Cipher.getInstance("RSA/ECB/NoPadding"), but Oracle Java defaults to Cipher.getInstance("RSA/ECB/PKCS1Padding")







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 23 at 14:26

























answered Nov 22 at 16:44









James K Polk

29.5k106694




29.5k106694












  • I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
    – Kirill Matrosov
    Nov 22 at 16:49










  • I will try to experiment with your code but I'm not a Kotlin programmer.
    – James K Polk
    Nov 22 at 17:07










  • It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
    – Kirill Matrosov
    Nov 23 at 8:52






  • 1




    I'll add that info to the answer. Let me know if it still remains unclear.
    – James K Polk
    Nov 23 at 14:16


















  • I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
    – Kirill Matrosov
    Nov 22 at 16:49










  • I will try to experiment with your code but I'm not a Kotlin programmer.
    – James K Polk
    Nov 22 at 17:07










  • It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
    – Kirill Matrosov
    Nov 23 at 8:52






  • 1




    I'll add that info to the answer. Let me know if it still remains unclear.
    – James K Polk
    Nov 23 at 14:16
















I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
– Kirill Matrosov
Nov 22 at 16:49




I have just checked on 4th Android and the last. Runtime is still working. So I dont think that the reason in versions
– Kirill Matrosov
Nov 22 at 16:49












I will try to experiment with your code but I'm not a Kotlin programmer.
– James K Polk
Nov 22 at 17:07




I will try to experiment with your code but I'm not a Kotlin programmer.
– James K Polk
Nov 22 at 17:07












It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
– Kirill Matrosov
Nov 23 at 8:52




It helped. But I still dont understand why the same code works in runtime and doesnt work while testing
– Kirill Matrosov
Nov 23 at 8:52




1




1




I'll add that info to the answer. Let me know if it still remains unclear.
– James K Polk
Nov 23 at 14:16




I'll add that info to the answer. Let me know if it still remains unclear.
– James K Polk
Nov 23 at 14:16


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435000%2fdifferent-codes-behavior-in-unit-test-and-in-runtime%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

What visual should I use to simply compare current year value vs last year in Power BI desktop

How to ignore python UserWarning in pytest?

Alexandru Averescu