L'API de cryptographie Android ne génère pas de sécurité IV pour AES

j'utilise javax.crypto faire quelques opérations cryptographiques dans mon application. J'utilise AES pour le cryptage / décryptage comme ceci:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] cipherText = cipher.doFinal(plaintext);
byte[] iv = cipher.getIV();   //The problematic IV

l'IV généré est prépendé au texte chiffré après l'enncryption.

la spécification Java indique clairement que la IV doit être générée automatiquement si elle n'est pas fournie à cipher.init() :

si ce chiffre nécessite des paramètres d'algorithme qui ne peut pas être dérivé de la clé donnée, l'implémentation de chiffrement sous-jacente est censée générer les paramètres requis elle-même (en utilisant des valeurs par défaut spécifiques au fournisseur ou des valeurs aléatoires)

mais parfois je me retrouve avec des textes codés qui ne semblent pas très aléatoires, comme celui-ci (en base64):

    AAAAAAAAAAAAAAAAAAAAAOmI9Qh1fMiG6HV3tKZK3q5sCruaPdYqYnoUOM00rs6YZY3EvecYfR6vTHzZqk7ugknR9ZMipedYWJB1YOLmSYg=

Le tas de A personnages à l'avant est de la IV. Le IV est en fait 16 zéro octets.

la plupart des le temps, la bibliothèque génère des IVs aléatoires, mais parfois, il sort juste des zéros. Pourquoi est-ce arrivé?

1
demandé sur nidzo732 2015-06-24 23:50:13

2 réponses

certains (la plupart? par défaut, les fournisseurs utilisent simplement une IV remplie de zéro octet. Je souligne de votre citation:

si ce code nécessite des paramètres d'algorithme qui ne peuvent pas être dérivés de la clé donnée, l'implémentation sous-jacente du code est supposée générer les paramètres requis elle-même (en utilisant par défaut spécifique au fournisseur ou des valeurs aléatoires)

Quand vous regardez à l'avant de votre ciphertext, vous voyez que ça commence avec un tas de caractères "A". C'est la base 64 pour 0x00 octets.

si vous voulez vous assurer que vous avez une IV aléatoire, vous devez la Générer vous-même:

SecureRandom r = new SecureRandom();
byte[] ivBytes = new byte[16];
r.nextBytes(ivBytes);

cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));
2
répondu Artjom B. 2015-06-24 21:11:56

L'IV n'est pas sécurisé. Il est préprogrammé sur le cryptogramme, de sorte que tout attaquant n'a qu'à lire le cryptogramme et à regarder les 16 premiers octets pour voir ce qu'il est.

ce n'est pas une bonne idée d'utiliser toujours le même IV-il transforme effectivement le premier bloc de votre cryptogramme réel en mode BCE, qui est peu sûr.

je vous recommande de générer votre propre IV aléatoire. Vous n'avez pas besoin d'utiliser un RNG cryptographiquement sécurisé, car un attaquant peut voir de toute façon. Vous avez juste besoin d'éviter d'utiliser la même IV pour des messages différents. Même quelque chose de simple comme 8 octets de random avec un compteur de 8 octets (64 bits) sera suffisant pour éviter l'effet BCE. Changez la clé avant que le compteur ne se renverse, et réinitialisez le compteur à 0 lorsque vous changez la clé.

-2
répondu rossum 2015-06-24 22:09:36