En mi aplicación vamos a enviar datos encriptados al servicio web. Estoy utilizando el siguiente código para cifrar y descifrar los datos -
public class DecEn {
private static final String password = "test";
private static String salt;
private static int pswdIterations = 65536;
private static int keySize = 256;
private byte[] ivBytes;
public String encrypt(String plainText) throws Exception {
//get salt
salt = generateSalt();
byte[] saltBytes = salt.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
return new Base64().encodeAsString(encryptedTextBytes);
// return Base64.encodeBase64String(encryptedTextBytes);
// return Hex.encodeHexString(encryptedTextBytes);
}
@SuppressWarnings("static-access")
public String decrypt(String encryptedText) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8");
byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
// byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText);
// byte[] encryptedTextBytes = Hex.decodeHex(encryptedText.toCharArray());
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Decrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try {
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return new String(decryptedTextBytes);
}
public String generateSalt() {
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String s = new String(bytes);
return s;
}
}
El código anterior almacena IV y sal después de que se generan y los reutiliza para descifrar los datos. Esto no será cierto en caso de colaboración entre la aplicación y el servicio web.
Lo que realmente me confunde es que la IV y la sal se generan de nuevo cada vez que se cifran los datos, que es el procedimiento recomendado por lo que pude ver en Google, pero a medida que estos datos se envían a un servicio web, la IV y la sal tiene que estar disponible allí, lo que significa que tendré que enviarlo junto con mis datos. ¿No derrota esto al propósito del cifrado? Como hace que la información esté disponible para el atacante.
O la otra forma parece ser el uso de IV estático y sal, lo que de nuevo hace que el cifrado sea susceptible de ataques. Que el cifrado se esté utilizando con éxito en todo el mundo indica que mi comprensión del tema no se encuentra en alguna parte.
Por favor ayúdame a aclarar mis dudas.