2

Java has a convinient class PBEKeySpec that lets you generate a secret key from a password using values of iteration count, key length and salt for decryption purposes. See the example below.

private static Key getPasswordBasedKey(String cipher, int keySize, char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] salt = new byte[100];
    SecureRandom random = new SecureRandom();
    random.nextBytes(salt);
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 1000, keySize);
    SecretKey pbeKey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(pbeKeySpec);
    return new SecretKeySpec(pbeKey.getEncoded(), cipher);
}

But what if salt is not a part of specific case of encryption? Then in order to get correct output I'll have to decrypt without salt as well. But in this case constructor of PBEKeySpec(char[] password, byte[] salt, int iterationCount, int keyLength) will throw an exception (NullPointerException if salt is null, IllegalArgumentException if it's an empty array). So my question is: is there any way available in Java to generate secret key from a password taking account of iterationCount and keyLength but skipping salt?

Why I need it:

  • Data was encrypted this way (no salt) on the other end. I can't change it.
  • So now i need a tool in Java that will let me decrypt it with no requirement to have a salt (but still with use of iteration count and key length).
  • I can't find such tool.
arturheath
  • 31
  • 3
  • 3
    The salt really needs to be there, it's part of what makes the encryption secure. Why don't you want to use a salt? – markspace Oct 10 '22 at 14:32
  • It's not my choice but rather a requirement from contractor's side. Can't really do anything about that. They encrypt with no salt, so that means that I'll have to decrypt with the same salt value (which is none here) if I'm not mistaken – arturheath Oct 10 '22 at 14:34
  • 1
    Some reference code and explanations: https://www.baeldung.com/java-password-hashing – markspace Oct 10 '22 at 14:34
  • 1
    @arturheath Please [edit] your question to include a more detailed description of your system or what you are trying to do. Explain where you want to encrypt/decrypt something. List the requirements you have from the contractor. If possible add more source code to make it clear what you are trying to do and provide the data you are getting from the contractor. – Progman Oct 10 '22 at 14:54
  • @arturheath Please [edit] your question to include the source code or a detailed description on how the data is actually encrypted. The "number of iterations" is unusual for encryption. – Progman Oct 10 '22 at 19:46
  • 1
    @Progman well, I can't include source code of encryption cause it's not on my end, but i mentioned all the details that i have. The code that i use for retrieving key from the password is pretty much the same as what i published here. I don't think that iteration count is smth unusual for encryption due to it's used in nearly every tutorial on the internet (consider https://www.baeldung.com/java-secure-aes-key as an example) and also it's one of the parameters of PBEKeySpec constructor. – arturheath Oct 11 '22 at 07:36
  • @arturheath Maybe using `PBEKeySpec` isn't the right thing to do here after all. Please [edit] your question to include all information in detail about the encryption process. "Number of iterations" is for the key generation, not for the encryption itself. You are missing crucial information in your post to answer your question. Also change the actual question you want to ask since it looks like you are looking for a different question than the one you wrote. Please see: [Why is “Is it possible to…” a poorly worded question?](https://softwareengineering.meta.stackexchange.com/q/7273). – Progman Oct 11 '22 at 13:50
  • 1
    @Progman In my question I mentioned two times that salt hasn't been used for encryption and so I need an implementation that would let me decrypt with no use of salt as well. I'll try to edit my question though to make it more clear. Regarding PBEKeySpec. I totally agree that it souldn'be used cause it just can't be used. And that's why after mentioning all the limtations of PBEKeySpec in my situation i asked 'is there any way to generate secret key from a password taking account of iterationCount and keyLength but skipping salt' meaning any other way available in Java. – arturheath Oct 11 '22 at 14:05
  • @arturheath Please speak with your contractor and then add all the necessary information about the encryption process to your question (like source code and/or documentations/specifications). It is not possible to answer the question on how to decrypt a ciphertext with the information/data you have when it is not defined how exactly the message has been encrypted. – Progman Oct 11 '22 at 16:08
  • @Progman It's symmetric encryption/decryption. Data has been encrypted using secret key which I need to derive. To do so i know the algorithm, key length and iteration count. I'm definitely not an expert but this seems to be enough for getting the key and following decryption. Please correct me if I'm wrong here. – arturheath Oct 11 '22 at 16:37
  • 2
    There are many possibilities for key derivation. Are you even sure that the other side used PBKDF2 with HMAC/SHA256 for key derivation? If yes, then you can use BouncyCastle's implementation for PBKDF2: `PKCS5S2ParametersGenerator`. This allows you to use *no* salt (i.e. accepts `null` for the salt parameter). The serious security vulnerability associated with this has already been mentioned. – Topaco Oct 13 '22 at 09:48
  • 1
    @Topaco that's exactly what I was looking for. My collegue gave me this solution the day before yesterday and it works as desired. If only you stumbled upon this question earlier it would save me a couple of days more. – arturheath Oct 14 '22 at 13:32

1 Answers1

0

To get the same secret key using the PBEKeySpec class, you need the same password, salt and iteration count (and key size). You cannot skip the salt part and expect to get the same password based secret key since there are 2^(salt-length) possible ways on how the key can be generated with only these provided data.

The salt doesn't need to be private for the password based key generation. See the quote from the answer Java 256-bit AES Password-Based Encryption:

Share the password (a char[]) and salt (a byte[]—8 bytes selected by a SecureRandom makes a good salt—which doesn't need to be kept secret) with the recipient out-of-band.

The answer also explain that the iteration and key size is fixed or known.

Also check the RFC2898 PKCS #5: Password-Based Cryptography Specification Version 2.0 - Page 5:

Salt and iteration count formed the basis for password-based
encryption in PKCS #5 v1.5, and adopted here as well for the various
cryptographic operations. Thus, password-based key derivation as
defined here is a function of a password, a salt, and an iteration
count, where the latter two quantities need not be kept secret.

with emphasis on "[...], where the latter two quantities need not be kept secret" (namely the salt and iteration).

To answer your question:

Is there any way to generate (the same)¹ secret key from a password taking account of iterationCount and keyLength but skipping salt?

¹ (added by me)

The answer is: No.

Progman
  • 16,827
  • 6
  • 33
  • 48
  • Thanks for your answer, I appreciate the time you spent but it seems that you address a different problem here. I know what salt is needed for and I understand that I have to use the same salt for decryption that was used for encryption or I'll get a different output. What I'm asking is what i should do in case **there was no salt involved in encryption at all**. They didn't use salt when encrypted data so neither should I when decrypting. So now i need a tool in Java that will let me decrypt it with no requirement to have a salt. And i can't find it. – arturheath Oct 11 '22 at 13:37