2015-11-27 2 views
6

私はC#で次のコードを書いています。これは、AES対称アルゴリズムでバイト配列をエンコードします。私はこのコードに相当するJavaを書く必要があります。C#AES暗号化に相当するJava

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

これはJavaでこれを書きます。コードは正常に見えますが、出力が異なりますが、何かが間違っている必要があります。

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

手がかりとアイデアは非常に高く評価されます。

+0

どのように出力を見ていますか? –

+0

デバッガでは(Javaのバイトが署名されていることに注意してください)。 – Someone

+1

各言語で短くて完全なプログラムを提供すれば、それぞれの場合に入力と出力を含めることができます。また、キーとIVを表現するために、「b」や「a」よりもわかりやすい名前を使用することを強くお勧めします。 –

答えて

2

何らかの理由でbyte[] array = new byte[toEncrypt.length];を初期化しようとしていますが、暗号化する前にtoEncryptの内容を決して書き込まないでください。あなたはSystem.arraycopy(toEncrypt, 0, array, 0, array.length);使用することができ、それだけで必要なパディングを追加する暗号化されたメッセージ解読する必要があります

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

愚かな間違い。それだった、ありがとう。私はそれを自分で見ることができませんでした。 – Someone

+0

質問者は、あなたがその答えを最終的なものとしてマークしておけば賞賛を得ていないかもしれませんが、私は素晴らしい賞金でそれを行います。楽しい! –

+0

@Flame_Phoenixありがとう!しかし、それは多かれ少なかれタイプミスであり、私があなたが提供した賞金を私が獲得したとは思わないので、質問を閉じるように傾いています。 Btw、なぜあなたは恩恵を申し出る必要がありましたか? –

0

個人的には、あなたの目的がJavaでAES暗号化を取得するだけであれば、コードをC#クラスに基づいて作成すべきではありません。確かに彼らは似ているかもしれませんが、Javaはすでにそれのための強力なライブラリを持っています。それと

さておき、私はあなたにそれを説明するためにここに私の暗号化の本を持っていたいが、残念ながら私は今できる最善のが唯一の他の誰かが試したことの良い例を提供することです:

私はこれらのリンクがあなたの目的を達成するのに役立つことを願っています。

また、特定のC#のコードについては、私はあなたがJavaで次のコードを指定している場所を確認するために失敗します。

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

を私はあなたが彼らがキーサイズを指定する例を持ってお勧め秒チュートリアルでは。私は助けてくれることを願っています!

+0

私はC#で自分のコードを基にする必要がありますが、Javaコードはまったく同じに動作する必要があります。 JavaでBlockSizeとKeySizeを指定する必要はありません(これらはデフォルトです)。 – Someone

4

私はC#をよく理解していませんが、一般的には、複数の連続した暗号化結果が異なる必要があります。これが、AESアルゴリズムの初期IVを指定する理由です。暗号化コードは、次のようになります。

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

さらに、あなたはANを計算する場合があります。これはJavaで最高のエントロピーを提供して

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

あなたのキーとIVはのSecureRandomを使用して生成する必要がありますその後のHMAC - javaは複数のソリューションもサポートしています。受信側のHMACをチェックすることで、パディングオラクル攻撃を防ぐことができます。

異なる暗号化結果を比較するには、それらをbase64でエンコードしたものと比較します。

注:IVを暗号文の隣に保存しても問題ありません。事前計算攻撃から保護するために存在します。

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

このコードを使用する方が簡単だろう - デフォルトの128ビットを、あなたはしかし、暗号化キーを提供する必要があるものとします。 しかし、これは同じコードのC#版です

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