2015-11-27 25 views
6

Aşağıdaki kod C# 'de var. AES simetrik algoritmasına sahip bir bayt dizisini kodlar. Bu kodun Java eşdeğerini yazmalıyım.C# AES şifreleme için Java eşdeğeri

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; 
    } 
} 

Bu, Java'da yazmayı denemem. Kod iyi görünüyor, ancak çıktı farklı, bir şey yanlış olmalı.

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; 
    } 
} 

Herhangi bir ipucu ve fikir çok takdir edilecektir.

+0

benim C# versiyonudur? –

+0

Hata ayıklayıcılarda (Java'daki baytların imzalandığını unutmayın). – Someone

+1

Her dilde kısa ama eksiksiz bir program sağlamanız durumunda size yardımcı olmak çok daha kolay olurdu, böylece kendimiz için görebilelim - her durumda girdi ve çıktıyı dahil edin. Ben de * şiddetle * b 've' a 'anahtarını ve IV ... –

cevap

2

Herhangi bir nedenle byte[] array = new byte[toEncrypt.length];'u başlatıyorsunuz, ancak şifrelemeden önce hiçbir zaman toEncrypt içeriğini yazmıyorsunuz.Sen System.arraycopy(toEncrypt, 0, array, 0, array.length); kullanabilirsiniz, ama sadece gerekli dolgu ekleyerek şifreli mesajın şifresini gerektiğini

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

aptalca hata. Öyleydi, teşekkürler. Onu kendim göremedim. – Someone

+0

Sorgucu, cevabını final olarak işaretleyerek size hak ettiğiniz kuduzlara vermemiş olabilir, ancak bunu güzel bir ödülle yapacağım. Keyfini çıkarın! –

+0

@Flame_Phoenix Teşekkürler! Ama soruyu kapatmak için sabırsızlanıyorum, çünkü az ya da çok yazım hatası yazıyor ve ben size teklif ettiğim ödülün * olduğunu düşünmüyorum. Btw, niçin lütuf teklifine ihtiyacın var? –

0

Amacınız Java ile AES şifrelemesi almaksa, kodunuzu C# sınıfına dayandırmamalısınız. Tabi ki benzer olabilirler, ancak Java'nın zaten bunun için güçlü kütüphaneleri var. kenara ile

, ben size açıklamak için burada şifreleme kitap olsaydı ama maalesef şimdi yapabileceği en iyi başkası çalıştı bu iyi örneklerle sunmak için sadece geçerli:

Umarım bu bağlantılar hedefinize ulaşmanıza yardımcı olur.

Ayrıca, belirli C# kodu ile ilgili, sana Java aşağıdaki kodu belirterek nerede görmek için başarısız:

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

Ben onlar anahtar boyutu belirtmek bir örnek var önermek ikinci eğitimde. Umarım yardımcı olmuşumdur!

+0

Kodumu C# temel almam gerekiyor, Java kodu tam olarak aynı şekilde çalışmalıdır. Java'da BlockSize ve KeySize belirtmem gerekmiyor (bunlar varsayılan). – Someone

4

C# yi çok iyi bilmiyorum ama genelde birbirini izleyen çoklu şifreleme sonuçlarının farklı olmasını istiyorsunuz. Bu nedenle AES algoritması için bir başlangıç ​​IV belirtin.

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); 
    } 
    } 
Anahtar ve IV bu java en iyi entropi sağladığından SecureRandom kullanılarak oluşturulan gerektiğini

: Ayrıca

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

, sen hesaplamak isteyebilirsiniz bir bir şifreleme kodunu aşağıdaki gibi görünebilir Bundan sonra HMAC - java da burada çoklu çözümleri desteklemektedir. Alıcı tarafındaki HMAC'yi kontrol ederek bir yastıklama hücumu saldırısını önleyebilirsiniz.

Farklı şifreleme sonuçlarını karşılaştırmak için bunları base64 kodlu olarak karşılaştırırdım.

Not: İkincil şifrenin yanında bulunan IV işaretini kaydetmeniz yeterlidir - ön hesaplama saldırılarına karşı korumak için sadece oradadır.

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; 
} 

Bu kod kullanmak daha kolay olurdu - Varsayılan 128bit ve olsa şifreleme anahtarını sağlamanız gerekir edecektir. Ancak bu her durumda çıkışta arıyoruz nasıl aynı kod

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)); 
     } 
    }