Why does the following code throws a java.security.InvalidKeyException: Wrong key size
exception (during encryption)? I have a String encryptPassword(String password, String masterpassword)
and a String decryptPassword(String password, String masterpassword)
method? Both call the byte[] DES(byte[] inputBytes, String masterpassword, int mode)
method. I would like to pass a masterpassword with an arbitrary length.
package com.example.passwordsafe.data;
import com.example.passwordsafe.core.usecases.EncryptionModuleInterface;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
public class DESEncryption implements EncryptionModuleInterface {
private static final String PBKDF_ALGORITHM = "DES";
private static final String TRANSFORMATION = "DES/ECB/NoPadding";
@Override
public String encryptPassword(String password, String masterpassword) {
byte[] inputBytes;
byte[] outputBytes;
inputBytes = password.getBytes();
outputBytes = DES(inputBytes, masterpassword, Cipher.ENCRYPT_MODE);
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(outputBytes);
}
@Override
public String decryptPassword(String password, String masterpassword) {
byte[] inputBytes;
byte[] outputBytes;
Base64.Decoder decoder = Base64.getDecoder();
inputBytes = decoder.decode(password);
outputBytes = DES(inputBytes, masterpassword, Cipher.DECRYPT_MODE);
return new String(outputBytes);
}
public byte[] DES(byte[] inputBytes, String masterpassword, int mode) {
byte[] outputBytes;
SecretKey key;
Cipher cipher;
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF_ALGORITHM);
DESKeySpec keySpec = new DESKeySpec(masterpassword.getBytes());
key = factory.generateSecret(keySpec);
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException e) {
throw new RuntimeException(e);
}
try {
cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(mode, key);
outputBytes = cipher.doFinal(inputBytes);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
BadPaddingException e) {
throw new RuntimeException(e);
}
return outputBytes;
}
}
Edit: It is necessary to hash the masterpassword, so that is 8 bytes long
// Derive an 8-byte key using SHA-1 (or another hash function)
MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hashedPassword = digest.digest(masterpassword.getBytes());
then pass it to
DESKeySpec keySpec = new DESKeySpec(hashedPassword);
and use:
private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding";