Use non-random initialization vector (IV)
Utilisation d'un vecteur d'initialisation (IV) non aléatoire
Description
L'utilisation d'un vecteur d'initialisation non aléatoire rend l'application vulnérable aux attaques par dictionnaire.
L'exemple suivant illustre la configuration incorrecte d'un IV statique codé en dur :
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;)))
}
}
Recommandation
Afin d'atténuer les failles cryptographiques liées aux IV, tenez compte des recommandations suivantes :
- IV unique pour chaque chiffrement : Il est essentiel d'utiliser un IV unique pour chaque opération de chiffrement. La réutilisation du même IV avec la même clé peut entraîner des vulnérabilités de sécurité, telles que l'exposition de motifs dans le texte chiffré ou la facilitation d'attaques telles que les attaques par rejeu.
- Caractère aléatoire : Les IV doivent être générés à l'aide d'un générateur de nombres pseudo-aléatoires cryptographiquement sûr (
SecureRandompour Java,SecRandomCopyBytespour Swift). Ce caractère aléatoire garantit que les attaquants ne peuvent pas prédire l'IV, ce qui affaiblirait la sécurité du chiffrement. - Longueur de l'IV : La longueur de l'IV dépend de l'algorithme de chiffrement utilisé. Par exemple, pour l'AES, la longueur de l'IV est généralement de 128 bits (16 octets) pour l'AES-128, 192 bits (24 octets) pour l'AES-192 et 256 bits (32 octets) pour l'AES-256. Il est important d'utiliser des IV de la longueur appropriée pour l'algorithme de chiffrement.
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();
}
Liens
Normes
- 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