• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

InvalidAlgorithmParameterException When Using PBEWithHmacSHA256AndAES_256

 
Marshal
Posts: 3651
516
Android Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a need to store a secret in encrypted form in a database, and later be able to retrieve the secret back in its original form.  I want to use a passphrase as raw key material used to generate the cryptographic key used for encrypting and encrypting.

The prototype code below does what I want, and appears to work find when using the PBEWithMD5AndDES algorithm, but when I run the same code using the PBEWithHmacSHA256AndAES_256 algorithm (which required JCE Unlimited Strength Jurisdiction Policy Files), it fails with a InvalidAlgorithmParameterException exception stating that an initialization vector was expected.

Questions:
  • Why do I see this with SHA256/AES256 and not with MD5/DES?
  • In addition to the encrypted data returned by the ciphering function, do I also need to somehow extract and store the initialization vector for used during encryption for use during decryption?


  • PBEWithMD5AndDES
    Original secret:  MySecret
    Encrypted secret: o7+tjKc3UnuFHeWmfVJBJg==
    Decrypted secret: MySecret


    PBEWithHmacSHA256AndAES_256
    Original secret:  MySecret
    Encrypted secret: rwtIUzt/jtQoGC6ueADBzw==
    java.security.InvalidAlgorithmParameterException: Missing parameter type: IV expected
    at com.sun.crypto.provider.PBES2Core.engineInit(PBES2Core.java:252)
    at javax.crypto.Cipher.implInit(Cipher.java:806)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1396)
    at javax.crypto.Cipher.init(Cipher.java:1327)
    at com.mcleodnet.sample.client.EncryptionHelper.decodeAndDecryptSecret(EncryptionHelper.java:36)
    at com.mcleodnet.sample.client.Test.main(Test.java:20)
    Decrypted secret was null




     
    Ron McLeod
    Marshal
    Posts: 3651
    516
    Android Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Ron McLeod wrote:Why do I see this with SHA256/AES256 and not with MD5/DES?


    It seems like depending for the mode of the cipher, it may or may not use an IV.  The default mode for PBEWithMD5AndDES does not use an IV (ECB mode?), but PBEWithHmacSHA256AndAES_256 does (CBC mode?).

    Ron McLeod wrote:In addition to the encrypted data returned by the ciphering function, do I also need to somehow extract and store the initialization vector for used during encryption for use during decryption?


    I found that I could either specify a fixed IV for both encrypting and decrypting, or extract the IV used when encrypting (Cipher#getIV()), and specify it when decrypting.


     
    Saloon Keeper
    Posts: 13248
    291
    • Likes 2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Probably because whoever implemented the AES algorithm in Java decided to protect people from making some mistakes, while the DES implementer didn't.

    There are some big issues with your code: You're using the same algorithm for key derivation and encryption, you're not using IVs and you're not authenticating your ciphertext.

    An important pillar on which cryptography is based is that every time you encrypt some message, the resulting ciphertext should look different. For this reason, keys are derived from passwords using a unique and random salt, and ciphertexts are derived from messages using a unique and random IV.

    Another important matter is that just encryption isn't enough. You need to verify ciphertexts before you decrypt them. This can be done easily using AES in Galois Counter Mode. This algorithm will sign your message after encryption, and verify it before decryption.

    You should use something like PBKDF2WithHmacSHA256 to perform key derivation, and AES/GCM/NoPadding for encryption.

    To configure PBKDF2WithHmacSHA256, you need a PBEParameterSpec. To configure AES/GCM/NoPadding you need a GCMParameterSpec. PBEParameterSpec requires a salt for your password, and GCMParameterSpec requires an IV for your message. These need to be random and unique every time your perform encryption. Generate these with a SecureRandom.

    So then, if your salt and IV are random each time you encrypt the same message, how can you decrypt the ciphertext? You can just append the salt and the IV to your ciphertext before you encode it. Salts and IVs are not sensitive data. Before decryption, remove the salt and IV from the decoded ciphertext, use the salt to reconstruct the key, use the IV to reconstruct the cipher, and then you can decrypt the remainder of the ciphertext.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 13248
    291
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    See also: https://coderanch.com/t/663164/AES-Encryption-Decryption-IV
     
    Ron McLeod
    Marshal
    Posts: 3651
    516
    Android Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Wow! - thanks for the excellent explanations and suggestions Stephan.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 13248
    291
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks for the cow!

    A final remark. Since you're not using the key for anything more than a single encryption operation, you can use the same piece of random data for both the salt and the IV. This no longer holds when you have to store the key somewhere to use later, for instance, when performing user authentication.

    [edit]

    Oh! And I noticed you're performing only 1000 iterations. Of course it depends on how many messages per time unit you want to encrypt, but I usually use between 100.000 and 500.000 iterations.
    reply
      Bookmark Topic Watch Topic
    • New Topic