Search code examples
scalaencryptionbouncycastlejce

CMSEncryptedData decryption with Bouncy Castle throws BadPaddingException: pad block corrupted


I have CMS encrypted data using Bouncy Castle and I would like to decrypt it's content. However, I am running into a problem of getting javax.crypto.BadPaddingException: pad block corrupted. I believe, there is something wrong with the secrete key

val provider = new BouncyCastleProvider()

// output encoder
val gen = new CMSEncryptedDataGenerator()
val encoder = new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BouncyCastleProvider.PROVIDER_NAME).build()

// secrete key
val spec = new DESedeKeySpec(encoder.getKey.getRepresentation.asInstanceOf[Array[Byte]])
val keyFactory = SecretKeyFactory.getInstance("DESEDE", provider)
val secretKey = keyFactory.generateSecret(spec)

// Encryption
val cmsEncryptedData: CMSEncryptedData = gen.generate(new CMSProcessableByteArray("Hello World!".getBytes()), encoder)

// Decryption
val decryptedContententBinary: Array[Byte] = {
  cmsEncryptedData.getContent(new InputDecryptorProvider {
    override def get(algorithm: AlgorithmIdentifier): InputDecryptor = new InputDecryptor {

      override def getAlgorithmIdentifier: AlgorithmIdentifier = algorithm

      override def getInputStream(encIn: InputStream): InputStream = {
        val parameters = new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(algorithm)
        val cipher = Cipher.getInstance(parameters.getAlgorithm, provider)
        cipher.init(Cipher.DECRYPT_MODE, secretKey, parameters) // throws javax.crypto.BadPaddingException: pad block corrupted
        new CipherInputStream(encIn, cipher)
      }
    }
  })
}

Solution

  • I have just fixed the problem I had. Here is the working code:

    // output encoder
    val gen = new CMSEncryptedDataGenerator()
    val random = new SecureRandom()
    val encoder = new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BouncyCastleProvider.PROVIDER_NAME).setSecureRandom(random).build()
    
    
    // secrete key
    val key = new SecretKeySpec(encoder.getKey.getRepresentation.asInstanceOf[Array[Byte]], "DESede")
    
    // Encryption
    val cmsEncryptedData: CMSEncryptedData = gen.generate(new CMSProcessableByteArray("Hello World!".getBytes()), encoder)
    
    
    // Decryption
    val decryptedContententBinary: Array[Byte] = {
      cmsEncryptedData.getContent(new InputDecryptorProvider {
        override def get(algorithm: AlgorithmIdentifier): InputDecryptor = new InputDecryptor {
    
          override def getAlgorithmIdentifier: AlgorithmIdentifier = algorithm
    
          override def getInputStream(encIn: InputStream): InputStream = {
    
            val parameters = new JceAlgorithmIdentifierConverter().setProvider(provider).getAlgorithmParameters(encoder.getAlgorithmIdentifier)
            val cipher = Cipher.getInstance(algorithm.getAlgorithm.getId, provider)
            cipher.init(Cipher.DECRYPT_MODE, key, parameters)
            new CipherInputStream(encIn, cipher)
          }
        }
      })
    }