Реализация шифрования 3DES сообщает о различных результатах реализации C # - PullRequest
1 голос
/ 09 февраля 2012

Я довольно безуспешно пытался зашифровать открытый текст, используя 3DES в Java, используя пакет BouncyCastle.Предполагается, что этот результат соответствует результату, достигнутому существующей реализацией C #, потому что я планирую расшифровать его позже.

Я продолжаю получать разные результаты, хотя я убежден, что создал «эквивалент» алгоритма C # в Java,Может ли кто-нибудь любезно просмотреть оба отрывка и посоветовать?Я был бы очень признателен.

C # шифрование:

public static byte[] encryptStringToBytes_3DES(string plainText, string passKey)
    {
        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");

        // Declare the streams used
        // to encrypt to an in memory
        // array of bytes.
        MemoryStream msEncrypt = null;
        CryptoStream csEncrypt = null;
        StreamWriter swEncrypt = null;
        ASCIIEncoding ascii = new System.Text.ASCIIEncoding();


        // used to encrypt the data.
        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        string passphrase = passKey;
        byte[] iv = ascii.GetBytes("AVREWASH");
        byte[] key = ascii.GetBytes(passphrase);

        try
        {
            // Create a TripleDES object
            // with the specified key and IV.
            //Console.WriteLine("Key size is " + tdes.KeySize+" and IV is "+tdes.IV+" and that of key is "+key.Length);
            tdes.Key = key;
            tdes.IV = iv;
            tdes.Padding = PaddingMode.Zeros;

            // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = tdes.CreateEncryptor(tdes.Key, tdes.IV);

            // Create the streams used for encryption.
            msEncrypt = new MemoryStream();
            csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
            swEncrypt = new StreamWriter(csEncrypt);

            //Write all data to the stream.
            swEncrypt.Write(plainText);

        }
        catch (Exception ex)
        {
            Console.WriteLine("Error is " + ex.Message);
            while (true)
            {
            }
        }

        finally
        {
            // Clean things up.

            // Close the streams.
            if (swEncrypt != null)
                swEncrypt.Close();
            if (csEncrypt != null)
                csEncrypt.Close();
            if (msEncrypt != null)
                msEncrypt.Close();

            // Clear the TripleDES object.
            if (tdes != null)
                tdes.Clear();
        }

        // Return the encrypted bytes from the memory stream.
        return msEncrypt.ToArray();

}

Есть эта вспомогательная функция, которую я использую при преобразовании результатов в Hex ...

public static string ByteArrayToString(byte[] ba)
    {
        string hex = BitConverter.ToString(ba);
        return hex.Replace("-", "");
    }

Javaфрагмент, который должен выполнять «эквивалентное» шифрование, также следует:

public void encrypt(String plaintext, String IV, String tripleDesKey){

try{

     SecretKey keySpec = new SecretKeySpec(tripleDesKey.getBytes("US-ASCII"),"DESede");

    IvParameterSpec iv = new IvParameterSpec(IV.getBytes("US-ASCII"));

    Cipher e_cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    e_cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);

    byte [] cipherText = e_cipher.doFinal(plaintext.trim().getBytes("US-ASCII"));

        System.out.println("Ciphertext: " + asHex(cipherText));
}
catch(Exception exc){
 ex.printStackTrace();
}
}

здесь его соответствующая функция Hex ..

public static String asHex (byte buf[]) {
  StringBuffer strbuf = new StringBuffer(buf.length * 2);
  int i;

  for (i = 0; i < buf.length; i++) {
   if (((int) buf[i] & 0xff) < 0x10)
        strbuf.append("0");

   strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
  }

  return strbuf.toString();
 }

ПОЖАЛУЙСТА, ПОМОГИТЕ.

Ответы [ 2 ]

3 голосов
/ 09 февраля 2012

Некоторые комментарии:

  1. Режимом по умолчанию .NET TripleDESCryptoServiceProvider действительно является CBC, который вы явно указываете в своем коде JAVA, но это не повредит, если вы укажетеэто явно в вашем коде C #.

  2. В исходном коде вы используете PaddingMode.Zeros в коде C #, но PKCS5Padding в коде JAVA.Существует AFAIK нет встроенного поставщика шифров в Java, который обеспечивает эквивалент PaddingMode.Zeros.Если вы все еще можете изменить свой код C #, вы должны вместо этого использовать PaddingMode.Pkcs7.В противном случае вам придется искать стороннего поставщика шифров для Java, который будет выполнять эту работу.

  3. Избегайте использования кодировки ASCII, если только вы не можете гарантировать, что входные данные действительно содержат 7-немного ascii.Если вы передаете строки с другими символами, вывод не определен.

  4. Ключевые данные, передаваемые в конструктор 3DES, должны иметь длину 8, 16 или 24 и, как правило, иметьБиты четности DES установлены.AFAIK и .NET, и Java будут игнорировать биты четности, но они могут вести себя по-разному, если длина ключа не принадлежит ни одному из правильных значений.Следовательно, если вы хотите, чтобы ваше шифрование работало для любого возможного ввода ключа, вы должны использовать функцию вывода ключа, которая поддерживается как .NET, так и Java.Попробуйте PBEWithHmacSHA1AndDESede в Java и в C # добавьте код, который преобразует пароль, используя System.Security.Cryptography.Rfc2898DeriveBytes.

3 голосов
/ 09 февраля 2012

Вы используете разные режимы заполнения. В C # вы написали tdes.Padding = PaddingMode.Zeros; а в Java вы использовали PKCS5Padding в режиме CBC. Это не одно и то же.

...