2015-11-27 5 views
6

Ich habe einen folgenden Code in C#. Es kodiert ein Array von Bytes mit einem symmetrischen AES-Algorithmus. Ich muss Java-Äquivalent zu diesem Code schreiben.Java-Äquivalent von C# AES-Verschlüsselung

class Program 
{ 
    static void Main(string[] args) 
    { 
     string a = "ABCDEFGHIJKLMNOP"; 
     byte[] bytes = Encoding.ASCII.GetBytes(a); 
     byte[] cipher = encode(bytes, "1111111122222222111111112222222211111111222222221111111122222222", "66666666555555556666666655555555"); 
    } 

    private static byte[] encode(byte[] toEncrypt, string sKey, string sIV) 
    { 
     byte[] IV = new byte[16]; 
     byte[] key = new byte[32]; 
     byte[] array = new byte[toEncrypt.Length]; 
     string s; 

     for (int i = 0; i < IV.Length; ++i) 
     { 
      s = sIV.Substring(i * 2, 2); 
      IV[i] = Convert.ToByte(s, 16); 
     } 

     for (int i = 0; i < key.Length; ++i) 
     { 
      s = sKey.Substring(i * 2, 2); 
      key[i] = Convert.ToByte(s, 16); 
     } 

     MemoryStream filecrypt = new MemoryStream(array); 

     AesManaged encrypt = new AesManaged(); 
     encrypt.Mode = CipherMode.CBC; 
     encrypt.Padding = PaddingMode.None; 
     encrypt.BlockSize = 128; 
     encrypt.KeySize = 256; 

     CryptoStream cs = new CryptoStream(filecrypt, encrypt.CreateEncryptor(key, IV), CryptoStreamMode.Write); 
     cs.Write(toEncrypt, 0, toEncrypt.Length); 
     cs.Close(); 

     return array; 
    } 
} 

Dies ist mein Versuch, dies in Java zu schreiben. Der Code sieht gut aus, aber die Ausgabe ist anders, etwas muss falsch sein.

public class Main { 

    public static void main(String [] args) { 
     byte [] code = encode("ABCDEFGHIJKLMNOP".getBytes(), "1111111122222222111111112222222211111111222222221111111122222222", "66666666555555556666666655555555"); 
    } 

    private static byte[] toByteArray(String s) { 
     int len = s.length(); 
     byte[] data = new byte[len/2]; 
     int a; 
     int b; 
     for (int i = 0; i < len; i += 2) { 
      a = (Character.digit(s.charAt(i), 16) << 4); 
      b = Character.digit(s.charAt(i+1), 16); 
      int n = (Character.digit(s.charAt(i), 16) << 4) 
        + Character.digit(s.charAt(i+1), 16); 
       data[i/2] = (byte) (n); 
     } 
     return data; 
    } 

    private static byte[] encode(byte[] toEncrypt, String skey, String siv) 
    { 
     byte[] key = toByteArray(skey); 
     byte[] iv = toByteArray(siv); 

     byte[] array = new byte[toEncrypt.length]; 

     Cipher cipher; 

     try { 
      cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); 
      array = cipher.doFinal(array); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return array; 
    } 
} 

Alle Hinweise und Ideen werden sehr geschätzt.

+0

Wie sehen Sie die Ausgabe in jedem Fall? –

+0

In den Debuggern (ich beachte, dass Bytes in Java signiert sind). – Someone

+1

Es wäre viel einfacher, Ihnen zu helfen, wenn Sie ein kurzes, aber vollständiges Programm in jeder Sprache zur Verfügung stellen würden, so dass wir es für uns selbst sehen können - schließen Sie die Eingabe und Ausgabe in jedem Fall ein. Ich würde auch * dringend * empfehlen, dass Sie aussagekräftigere Namen als 'b' und' a' verwenden, um den Schlüssel und IV darzustellen ... –

Antwort

2

Sie initialisieren byte[] array = new byte[toEncrypt.length]; aus irgendeinem Grund, aber Sie schreiben nie den Inhalt von toEncrypt in es vor der Verschlüsselung.Sie könnten System.arraycopy(toEncrypt, 0, array, 0, array.length); verwenden, aber es wäre einfacher, nur sollte

byte[] array; 
... 
array = cipher.doFinal(toEncrypt); 
... 
return array; 
+0

dummer Fehler. Das war es, danke. Ich konnte es selbst nicht sehen. – Someone

+0

Der Fragesteller hat Ihnen vielleicht nicht die Anerkennung gegeben, die Sie verdient haben, indem Sie diese Antwort als endgültig markiert haben, aber ich werde es mit einer schönen Prämie machen. Genießen! –

+0

@Flame_Phoenix Danke! Aber ich lehne die Frage ab, weil es mehr oder weniger ein Tippfehler ist und ich glaube nicht, dass ich die von Ihnen gebotene Prämie verdient habe. Übrigens, warum musstest du das Kopfgeld anbieten? –

0

Persönlich, wenn Ihr Ziel ist einfach AES-Verschlüsselung mit Java zu bekommen, sollten Sie nicht Ihren Code auf einer C# -Klasse basieren. Sicher mögen sie ähnlich sein, aber dafür hat Java bereits starke Bibliotheken.

Damit beiseite, ich wünschte, ich hier meine Verschlüsselung Buch hatte, es Ihnen zu erklären, aber leider ist das Beste, was ich jetzt tun kann, ist nur Sie mit einem guten Beispiele zu liefern, dass jemand anderes versucht:

Ich hoffe, dass diese Links Ihnen helfen, Ihr Ziel zu erreichen.

Auch in Bezug auf Ihre spezifischen C# -Code, sehe ich nicht, wo Sie den folgenden Code in Java angeben:

encrypt.BlockSize = 128; 
encrypt.KeySize = 256; 

Im zweiten Tutorial schlage ich Ihnen ein Beispiel, wo sie die Schlüsselgröße angeben. Ich hoffe, ich konnte helfen!

+0

Ich muss meinen Code auf C# basieren, der Java-Code muss genau gleich funktionieren. Ich muss BlockSize und KeySize nicht in Java angeben (das sind Standardwerte). – Someone

4

Ich weiß nicht, C# ziemlich gut, aber im Allgemeinen wollen Sie mehrere aufeinanderfolgende Verschlüsselungsergebnisse unterschiedlich sein. Aus diesem Grund geben Sie eine anfängliche IV für den AES-Algorithmus an.

public String encrypt(String stringToEncrypt, IvParameterSpec ivSpec) { 
    if (stringToEncrypt == null) { 
     return null; 
    } 
    try { 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 
     byte[] data = cipher.doFinal(stringToEncrypt.getBytes("UTF-8")); 
     return String.format("%s:%s", Base64.encode(ivSpec.getIV()), Base64.encode(data)); 
    } catch (Exception e) { 
     throw new RuntimeException("Unable to encrypt the string", e); 
    } 
    } 

Ihre Schlüssel und Ihr IV sollte mit Secure erzeugt werden, wie dies die beste Entropie in Java bietet: Eine Code-Verschlüsselung könnte wie folgt aussehen

byte[] iv = new byte[32]; 
random.nextBytes(iv); 
byte[] key = new byte[32]; 
random.nextBytes(key); 

Darüber hinaus möchten Sie vielleicht ein berechnen HMAC danach - Java unterstützt hier auch mehrere Lösungen. Wenn Sie den HMAC auf der Empfängerseite überprüfen, können Sie einen Padding-Orakel-Angriff verhindern.

Um verschiedene Verschlüsselungsergebnisse zu vergleichen, würde ich sie base64-codiert vergleichen.

Hinweis: Es ist in Ordnung, die IV neben dem Chiffretext zu speichern - sie dient nur dazu, vor Vorberechnungsattacken zu schützen.

0
public String notify(String message, String encryptionKey) { 
    Security.addProvider(new BouncyCastleProvider()); 
    // System.out.println(message); 
    byte[] key = Base64.decode(encryptionKey); 
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 
    byte[] data = Base64.decode(message); 
    String decryptedString = ""; 
    try { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
     byte[] decrypted = cipher.doFinal(data); 
     decryptedString = new String(decrypted); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    System.out.println(decryptedString); 
    return decryptedString; 
} 

Dieser Code verwenden, um die verschlüsselte Nachricht entschlüsseln, indem die erforderlichen Polsterung - Standard 128bit und Sie müssen jedoch Verschlüsselungsschlüssel zur Verfügung stellen müssen. Dies ist jedoch meine C# -Version des gleichen Codes

void DecryptMessage(string message) 
    { 
     var deserializedMessage = JsonConvert.DeserializeObject<List<string>>(message.ToString()); 
     byte[] decodedEncryptionKey = Convert.FromBase64String(encryptkey); 
     byte[] data = Convert.FromBase64String(deserializedMessage[0]); 
     byte[] iv = new byte[16]; 
     AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); 
     aes.BlockSize = 128; 
     aes.KeySize = 128; 
     aes.Mode = CipherMode.ECB; 
     aes.Padding = PaddingMode.PKCS7; 

     using (ICryptoTransform decrypt = aes.CreateDecryptor(decodedEncryptionKey, iv)) 
     { 
      byte[] dest = decrypt.TransformFinalBlock(data, 0, data.Length); 
      decrypt.Dispose(); 
      Console.WriteLine(Encoding.UTF8.GetString(dest)); 
     } 
    }