Один и тот же алгоритм шифрования в С# и Java дает разные результаты

У меня есть код C# для шифрования пароля. Я хочу преобразовать его в Java. Преобразованный Java-код создает другую зашифрованную строку, чем С#. Что я могу сделать, чтобы вывод был одинаковым как для Java, так и для С#.

Пароль: Привет, мир2.

Вывод C#: orc_Aup5rLQZ_vB5atFuqw2

Вывод Java: orc_Aup5rLQZ_vB5atFuqw==

код С#

    using System;
        using System.IO;
        using System.Security.Cryptography;
        using System.Text;
        using System.Web;
        
        namespace Crypto.Client
        {
            /// <summary>
            ///     Helper functions to encrypt and decrypt stuff
            /// </summary>
            public static class CryptoHelper
            {
                private static readonly byte[] Key =
                    {
                        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
                        0x13, 0x14, 0x15, 0x16
                    };
        
                private static readonly byte[] InitializationVector =
                    {
                        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
                    };
        
                //Encrypts the input string using a .net function.
                public static string Encrypt(string plainText)
                {
                    var rmCrypto = new RijndaelManaged();
                    using (var memoryStream = new MemoryStream())
                    {
                        using (
                            var cryptoStream = new CryptoStream(
                                memoryStream, rmCrypto.CreateEncryptor(Key, InitializationVector), CryptoStreamMode.Write))
                        {
                            using (var streamWiter = new StreamWriter(cryptoStream))
                            {
                                streamWiter.Write(plainText);
                            }
                        }
                        return HttpServerUtility.UrlTokenEncode(memoryStream.ToArray());
                    }
                }
            }
        }

Java-код:

public class CryptoHelper
{
    private static final byte[] Key =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16
    };

    private static final byte[] InitializationVector =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
    };
    
    public static String Encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(Key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(InitializationVector);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cryptoStream = new CipherOutputStream(outputStream, cipher);
        cryptoStream.write(plainText.getBytes("UTF-8"));
        cryptoStream.close();
        
        byte[] encryptedBytes = outputStream.toByteArray();

        
        return Base64.getUrlEncoder().encodeToString(encryptedBytes);
    }
}

кроме вашего вопроса. Принцип вашей работы неправильный, пароли надо хешировать, а не шифровать.

Mohammad Aghazadeh 09.07.2024 14:08

Не используйте фиксированную капельницу! Это разрушает всю причину существования IV. IV должен быть разным для разных вещей, зашифрованных одним и тем же ключом.

canton7 09.07.2024 14:17

Кроме того, я не знаком с API-интерфейсами Java, но тот факт, что encVal не используется, должен настораживать? Добавьте к этому вывод Java на 2 байта короче, и это указывает на проблему, когда вы опускаете последние несколько байтов вывода Java.

canton7 09.07.2024 14:18

@FedericoklezCulloca Но эти две строки base64 содержат разные данные. (И могут ли две разные строки Base64 кодировать одно и то же значение? Игнорируя наличие/отсутствие конечных =, это не проблема)

canton7 09.07.2024 14:20

Однако выходные данные Java составляют 16 байт, что и следовало ожидать от полного блока, а выходные данные C# — 17 байт. Хотя я не уверен, откуда взялся последний 0x0D.

canton7 09.07.2024 14:26

Вы просто используете разные кодировки для зашифрованного текста. UrlTokenEncode() Base64url кодирует, но также заменяет байты заполнения Base64 (=) числом, равным количеству байтов заполнения. Это вызывает разницу.

Topaco 09.07.2024 14:31

Подтверждено: dotnetfiddle.net/EsNa0w

canton7 09.07.2024 14:33

@Topaco, поэтому в моем Java-коде мне нужно заменить дополненные байты количеством дополненных байтов.

Rajesh Kumar 09.07.2024 14:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминалось в комментарии @topaco, HttpServerUtility.UrlTokenEncode заменяет дополненные байты (=) числом, равным количеству заполняющих байтов. Поэтому я создал метод для этого в Java.

https://stackoverflow.com/a/55426707/4498738

Другие вопросы по теме