0

I have generated the following Public Key in Android.

 fun createCipher(): Cipher
    {
        val posKey = posPublicKey
        posKey.publicKey.modulus

        var spec = RSAPublicKeySpec(BigInteger(posPublicKey.publicKey.modulus), BigInteger(posPublicKey.publicKey.exponent))
        var fact = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)

        publicKey = fact.generatePublic(spec)
        var cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)
        return cipher
    }

The RSA key size that I have selected is 4096 bytes The exponent is 3 bytes and the modulus is 512 bytes

The Modulus Byte Array is as follows:

[-32, -28, -121, 32, 109, -82, 43, 115, 43, -117, 20, 35, 122, 33, -2, 23, 23, -22, 75, 0, 91, 10, -89, 48, 33, -89, 57, 1, 57, -13, 9, -127, 90, 121, -96, -94, 106, -16, -105, -112, -74, 30, -12, 74, -74, 104, -26, 15, 99, -22, -55, -75, 14, -45, 56, 20, 85, 90, 83, -50, 68, -114, 5, -10, -109, 79, 44, 81, 68, -98, -45, -51, -97, 71, 90, -13, -78, 118, -21, -47, 66, 104, -83, 56, -72, -27, 45, 16, 70, 32, -76, -125, -11, 108, 126, -61, -126, 16, 6, -49, -106, -114, 18, 49, 121, -39, -109, 115, 111, -128, 83, 8, -110, -10, -4, 51, -67, 49, 66, 103, -76, -88, -110, 122, 56, 29, -101, 22, 3, 117, -104, -54, -64, -71, 23, 58, 87, 37, 96, 25, -114, 38, 1, -126, 33, -91, -4, 89, -28, 10, 95, -104, -24, -38, 17, 47, -122, 24, -89, 123, 100, 12, -10, -57, -44, 45, 25, 39, -80, -101, -6, -99, -95, -5, 70, 32, 37, -57, -52, -47, -66, 85, 10, -48, 75, 4, -114, 104, -7, -112, -128, 4, 114, 77, -40, 96, 66, 83, -54, 10, 111, 102, -39, -63, 2, -75, 38, 36, 24, 13, -51, 96, 89, -60, -40, 99, 65, 123, 52, -114, 122, 75, 32, -121, 80, -76, -11, -1, -31, -118, -51, -21, 13, 109, 111, -102, 120, -56, 62, -19, -79, 86, -41, -81, 67, -80, -63, 37, 35, 47, 109, -32, 47, -128, 95, -48, -53, -1, -125, -19, -9, -10, 15, -116, -50, 53, -86, -102, -24, 107, 122, -43, -125, 51, 14, 101, 67, 57, 116, 97, -40, -98, -82, -118, -83, 120, -107, -14, 19, -49, -27, 10, 25, 40, 43, -27, 31, 59, -57, 58, 33, -98, 1, -45, -118, 76, -21, -13, -123, 67, 42, -37, -96, -32, 33, 124, 1, 44, -99, 74, 18, 32, 10, -107, -121, 86, -115, -70, -107, 109, 17, -92, 109, -47, 60, -49, -91, 7, -125, 47, 78, 86, 81, -2, -35, 17, 124, 94, -26, -80, -84, 120, 110, 38, -55, -90, -11, 107, 73, 71, 44, 69, -58, 56, -59, 2, 94, 27, 88, 29, -57, 95, -99, 5, 102, -66, 118, -82, 126, 20, -104, -95, 47, -2, 77, -33, 89, -66, -92, 121, -5, 78, 68, -1, -82, -95, -121, 117, -29, 70, 11, -72, 54, -99, -13, -87, 9, 77, -113, 51, -124, -56, -8, 126, -114, -31, 90, -125, -11, 41, -85, 74, 3, 90, -95, 85, 121, 61, 14, 116, 51, -40, -57, -124, -69, -51, -76, -119, -80, 95, 95, 17, -34, 80, -36, 66, -51, 14, -69, -113, 35, -109, -115, -16, -3, -118, 114, -20, -81, 57, -65, 40, -8, -67, -85, 110, 50, -128, 44, -78, 93, -44, -93, 89, -76, 13, 98, -38, -55, -120, 11, 127, 84, -2, 101, 57, -121, -111, 91, -102, -118, 85, -124, -90, 91, -84, 28, 120, -28, -105, 88, -73, 6, 89, 33, 8, 9, 30, 9, -6, 17, 25]

The Exponent Byte Array is as Follows:

[1, 0, 1]

The test Key is as follows:

val stringKey = "8D-F7-5B-15-0F-2A-E5-3E-FD-44-5A-63-50-AC-62-D6-06-2D-59-5C-F1-C3-9A-DB-45-25-0D-7A-72-AE-DF-87"
val stringIV = "FA-94-FD-74-2E-AC-2C-90-79-98-AF-A3-D7-12-5D-A2"

 var aeskey = AesKeyBuilder()
            val key = (stringKey.replace("-", "")).toByteArray(Charsets.US_ASCII)

            val iv = (stringIV.replace("-", "")).toByteArray(Charsets.US_ASCII)
            aeskey.key = key
            aeskey.iv = iv

val encryptedKey = cipher.doFinal(aesKey.Key)

The item that I am trying to encrypt is 64 bytes. Using this public key.

However, I get the following error:

Process: com.touchsides.rewards.debug, PID: 19470
com.android.org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
    at com.android.org.bouncycastle.crypto.engines.RSACoreEngine.convertInput(RSACoreEngine.java:115)
    at com.android.org.bouncycastle.crypto.engines.RSABlindedEngine.processBlock(RSABlindedEngine.java:95)
    at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.encodeBlock(OAEPEncoding.java:199)
    at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.processBlock(OAEPEncoding.java:131)

I believe the modulus size is large enough to allow for the encryption of this byte array.

George
  • 2,865
  • 6
  • 35
  • 59
  • What approach are you taking to the conversion rate of divided bytes? ``convertInput(RSACoreEngine.java:115)`` Looks like a good line to look into – Treewallie Jul 30 '19 at 13:11
  • There is not enough information in your question to test this but, yes, a 4096-bit RSA modulus is more than enough to encrypt a 64-byte key. I have to be somewhat skeptical about one or more of your claims that 1) the modulus is 4096 bits and 2) the data to be encrypted is 64 bytes. Additionally, the fact that the thing you're encrypting is called `aesKeyBuilder.key` and the *largest* AES key is 32 bytes enhances my skepticism. – President James K. Polk Jul 30 '19 at 15:38
  • @JamesKPolk the modulus is a byte array of size 512 and the AES key is byte array of size 64. – George Jul 30 '19 at 15:47
  • So you say, but you haven't provided an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example) to actually verify your claims. – President James K. Polk Jul 30 '19 at 15:49
  • @JamesKPolk I have updated the question with sample keys – George Jul 30 '19 at 16:07
  • An *actual* MCVE would take even less space. – President James K. Polk Jul 31 '19 at 00:02
  • @JamesKPolk I have linked the test app to the following link: https://stackoverflow.com/questions/57288592/cross-platform-rsa-encryption-c-sharp-to-java-and-java-to-c-sharp – George Jul 31 '19 at 11:05

1 Answers1

1

You get the com.android.org.bouncycastle.crypto.DataLengthException error because RSA key was created with negative Modulus. So it can't be used to encrypt even one byte.

BigInteger default constructor uses the most significant bit of provided byte array payload as sign bit for the number. So you have to explicitly specify that you want a positive number using another constructor where the first argument is a sign indicator:

BigInteger(1, posPublicKey.publicKey.modulus), BigInteger(1, posPublicKey.publicKey.exponent)

There's also a C# approach to add a zero-byte in front of the byte array (so the sign bit will be always zero):

BigInteger(byteArrayOf(0) + posPublicKey.publicKey.modulus), BigInteger(byteArrayOf(0) + posPublicKey.publicKey.exponent)

And finally, if you already have your BigInteger created the wrong way, it's possible to convert it:

var modulus = BigInteger(posPublicKey.publicKey.modulus)
if (modulus.compareTo(BigInteger.ZERO) < 0)
    modulus = modulus.add(BigInteger.ONE.shiftLeft(4096))

Please also look at this answer and answers of this question.

tifssoft
  • 216
  • 2
  • 4