У меня есть код 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);
}
}
Не используйте фиксированную капельницу! Это разрушает всю причину существования IV. IV должен быть разным для разных вещей, зашифрованных одним и тем же ключом.
Кроме того, я не знаком с API-интерфейсами Java, но тот факт, что encVal
не используется, должен настораживать? Добавьте к этому вывод Java на 2 байта короче, и это указывает на проблему, когда вы опускаете последние несколько байтов вывода Java.
@FedericoklezCulloca Но эти две строки base64 содержат разные данные. (И могут ли две разные строки Base64 кодировать одно и то же значение? Игнорируя наличие/отсутствие конечных =
, это не проблема)
Однако выходные данные Java составляют 16 байт, что и следовало ожидать от полного блока, а выходные данные C# — 17 байт. Хотя я не уверен, откуда взялся последний 0x0D.
Вы просто используете разные кодировки для зашифрованного текста. UrlTokenEncode()
Base64url кодирует, но также заменяет байты заполнения Base64 (=
) числом, равным количеству байтов заполнения. Это вызывает разницу.
Подтверждено: dotnetfiddle.net/EsNa0w
@Topaco, поэтому в моем Java-коде мне нужно заменить дополненные байты количеством дополненных байтов.
Как упоминалось в комментарии @topaco, HttpServerUtility.UrlTokenEncode заменяет дополненные байты (=) числом, равным количеству заполняющих байтов. Поэтому я создал метод для этого в Java.
кроме вашего вопроса. Принцип вашей работы неправильный, пароли надо хешировать, а не шифровать.