2017-02-01 3 views
3

Ich kann nicht verstehen, warum meine Chiffre länger ist als die erwartete Ausgabe basierend auf den folgenden Vektoren. Ich werde den Code nicht erklären, weil ich denke, dass er sehr sauber und klar ist.Was ist falsch an dieser AES 128-Verschlüsselung?

package mundo; 
import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 
import javax.xml.bind.DatatypeConverter; 

class AESTest { 
    public static void main(String[] args) throws Exception { 
    //each array is a vector case {key, plainText, expectedCipher} 
    String[][] cases = new String[][]{{"00000000000000000000000000000000", "f34481ec3cc627bacd5dc3fb08f273e6","0336763e966d92595a567cc9ce537f5e"}, 
             {"00000000000000000000000000000000", "9798c4640bad75c7c3227db910174e72", "a9a1631bf4996954ebc093957b234589"}, 
             {"2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"}, 
             {"2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"}}; 
    for(String[] kase : cases) 
    { 
     byte[] theKey = byte2hex(kase[0]); 
     byte[] theMsg = byte2hex(kase[1]); 
     byte[] theExp = byte2hex(kase[2]); 
     Cipher cipher = Cipher.getInstance("AES"); 
     SecretKeySpec keySpec = new SecretKeySpec(theKey, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, keySpec); 
     byte[] cryptMsg = cipher.doFinal(theMsg); 
     System.out.println("Key  : "+hex2byte(theKey)); 
     System.out.println("Message : "+hex2byte(theMsg)); 
     System.out.println("Cipher : "+hex2byte(cryptMsg)); 
     System.out.println("Expected: "+hex2byte(theExp) + "\n"); 
    } 
    } 
    public static String hex2byte(byte[] array) { 
     return DatatypeConverter.printHexBinary(array); 
    } 
    public static byte[] byte2hex(String s) { 
     return DatatypeConverter.parseHexBinary(s); 
    } 
} 

Dies ist die Ausgabe:

Key  : 00000000000000000000000000000000 
Message : F34481EC3CC627BACD5DC3FB08F273E6 
Cipher : 0336763E966D92595A567CC9CE537F5E0143DB63EE66B0CDFF9F69917680151E 
Expected: 0336763E966D92595A567CC9CE537F5E 

Key  : 00000000000000000000000000000000 
Message : 9798C4640BAD75C7C3227DB910174E72 
Cipher : A9A1631BF4996954EBC093957B2345890143DB63EE66B0CDFF9F69917680151E 
Expected: A9A1631BF4996954EBC093957B234589 

Key  : 2B7E151628AED2A6ABF7158809CF4F3C 
Message : 6BC1BEE22E409F96E93D7E117393172A 
Cipher : 3AD77BB40D7A3660A89ECAF32466EF97A254BE88E037DDD9D79FB6411C3F9DF8 
Expected: 3AD77BB40D7A3660A89ECAF32466EF97 

Key  : 2B7E151628AED2A6ABF7158809CF4F3C 
Message : AE2D8A571E03AC9C9EB76FAC45AF8E51 
Cipher : F5D3D58503B9699DE785895A96FDBAAFA254BE88E037DDD9D79FB6411C3F9DF8 
Expected: F5D3D58503B9699DE785895A96FDBAAF 

Warum ist das Cipher länger als erwartet. Dies sind vertraute 128-Bit-AES-Vektoren aus Referenzbüchern.

EDIT hinzugefügt Code:

cipher.init(Cipher.DECRYPT_MODE, keySpec); 
byte[] dcrypMsg = cipher.doFinal(cryptMsg); 
System.out.println("Decrypted: " + byte2hex(dcrypMsg) + "\n"); 

Decryption ist richtig, aber ich kann immer noch nicht verstehen ...

Key  : 2B7E151628AED2A6ABF7158809CF4F3C 
Message : AE2D8A571E03AC9C9EB76FAC45AF8E51 
Cipher : F5D3D58503B9699DE785895A96FDBAAFA254BE88E037DDD9D79FB6411C3F9DF8 
Expected: F5D3D58503B9699DE785895A96FDBAAF 
Decrypted: AE2D8A571E03AC9C9EB76FAC45AF8E51 

Antwort

4

benutzen Sie bitte Cipher.getInstance("AES/ECB/NoPadding"); sicher zu machen, Ihre Eingabe tut nicht gepolstert werden. Dann bekomme ich die erwartete Ausgabe für alle Ihre Testfälle.

Nach https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html:

Eine Transformation von der Form ist:

"-Algorithmus/mode/padding" oder "Algorithmus" (im letzteren Fall providerspezifischen Standardwerte für die Modus und Padding-Schema sind verwendet).

Sie wissen nicht, welche Art von Auffüllung verwendet wird, wenn Sie sie nicht angeben. Ich gehe davon aus, dass Ihre Eingabedaten gepolstert werden, was bedeutet, dass Ihrer Eingabe etwas hinzugefügt wird, um sie aufzufüllen, so dass Sie einen Satz voller Blöcke der Blockgröße Ihrer Chiffre haben. Ihre Eingabelänge ist bereits durch die Blockgröße teilbar. Daher wird ein vollständiger Block hinzugefügt, was zu der Nachricht führt und die doppelte erwartete Länge hat.

2

Wenn Sie den Cipherblock-Verkettungsmodus und den Auffüllalgorithmus nicht angeben, verwendet das JDK die Standardwerte. Die Krypto-Spezifikation rät sie nicht festgelegt wird:

Es wird empfohlen, eine Transformation zu verwenden, die vollständig die Algorithmus spezifiziert, Modus und Polsterung. Wenn Sie dies nicht tun, verwendet der Provider standardmäßig . Beispiel: Die SunJCE- und SunPKCS11-Anbieter verwenden ECB als als Standardmodus und PKCS5Padding als Standardauffüllung für viele symmetrische -Chiffren. http://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/CryptoSpec.html#trans

Um die gewünschte Ausgabe zu erhalten, müssen Sie den elektronischen Kochbuch-Modus (EZB) verwenden - also keinen Block Chaining - und kein padding:

Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); 
Verwandte Themen