Use non-random initialization vector (IV)
Uso de vector de inicialización (IV) no aleatorio
Descripción
El uso de un vector de inicialización no aleatorio hace que la aplicación sea vulnerable a ataques de diccionario.
El siguiente ejemplo demuestra la configuración incorrecta de un IV estático codificado (hardcoded):
public; class InsecureExample {
@Override
public void; run() throws; Exception;{
byte;[]; IV = "0123456789abcdef".getBytes();
String; clearText = "Jan van Eyck was here 1434";
String; key = "ThisIs128bitSize";
SecretKeySpec; skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher; cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher;.init(Cipher.ENCRYPT_MODE;, skeySpec;, new; IvParameterSpec(IV))
byte;[]; encryptedMessage = cipher.doFinal(clearText.getBytes());
Log;.i(TAG, String.format("Message: %s";, Base64;.encodeToString(encryptedMessage, Base64.DEFAULT;)))
}
}
Recomendación
Para mitigar las fallas criptográficas relacionadas con el IV, considere las siguientes recomendaciones:
- IV único para cada cifrado: Es fundamental utilizar un IV único para cada operación de cifrado. Reutilizar el mismo IV con la misma clave puede provocar vulnerabilidades de seguridad, como exponer patrones en el texto cifrado o facilitar ataques como los ataques de repetición.
- Aleatoriedad: Los IV deben generarse mediante un generador de números aleatorios criptográficamente seguro (
SecureRandompara Java,SecRandomCopyBytespara Swift). Esta aleatoriedad garantiza que los atacantes no puedan predecir el IV, lo que debilitaría la seguridad del cifrado. - Longitud del IV: La longitud del IV depende del algoritmo de cifrado que se utilice. Por ejemplo, en AES, la longitud del IV suele ser de 128 bits (16 bytes) para AES-128, 192 bits (24 bytes) para AES-192 y 256 bits (32 bytes) para AES-256. Es importante utilizar IV de la longitud adecuada para el algoritmo de cifrado.
import java.security.SecureRandom
import javax.crypto.spec.IvParameterSpec
object IVGenerator {
fun generateIV(length: Int): ByteArray {
val iv = ByteArray(length)
val secureRandom = SecureRandom()
secureRandom.nextBytes(iv)
return iv
}
}
fun main() {
val ivLength = 16 // Length of IV in bytes
val iv = IVGenerator.generateIV(ivLength)
println("Generated IV: ${bytesToHex(iv)}")
}
fun bytesToHex(bytes: ByteArray): String {
return bytes.joinToString("") { "%02x".format(it) }
}
import CryptoKit
func generateIV(length: Int) -> Data {
var iv = Data(count: length)
_ = iv.withUnsafeMutableBytes { ivPtr in
guard let ivBaseAddress = ivPtr.baseAddress else { return }
_ = SecRandomCopyBytes(kSecRandomDefault, length, ivBaseAddress)
}
return iv
}
let ivLength = 16 // Length of IV in bytes
let iv = generateIV(length: ivLength)
print("Generated IV: \(iv.hexEncodedString())")
extension Data {
func hexEncodedString() -> String {
return map { String(format: "%02hhx", $0) }.joined()
}
}
import 'dart:typed_data';
import 'dart:math';
Uint8List generateIV(int length) {
final random = Random.secure();
return Uint8List.fromList(List.generate(length, (index) => random.nextInt(256)));
}
void main() {
final ivLength = 16; // Length of IV in bytes
final iv = generateIV(ivLength);
print('Generated IV: ${bytesToHex(iv)}');
}
String bytesToHex(Uint8List bytes) {
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
}
Enlaces
Estándares
- OWASP_MASVS_L1:
- MSTG_CRYPTO_2
- MSTG_CRYPTO_3
- MSTG_CRYPTO_4
- OWASP_MASVS_L2:
- MSTG_CRYPTO_2
- MSTG_CRYPTO_3
- MSTG_CRYPTO_4
- PCI_STANDARDS:
- REQ_2_2
- REQ_3_6
- REQ_3_7
- REQ_4_2
- REQ_6_2
- OWASP_MASVS_v2_1:
- MASVS_CRYPTO_1
- MASVS_CRYPTO_2
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_6_7
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- CNIL_FOR_DEVELOPERS:
- DEVELOPERS_4_1_4
- HIPAA_CONTROLS:
- SECURITY251
- SECURITY212
- SECURITY213