У меня есть «унаследованное» приложение Ruby on Rails, и я должен перевести это приложение с Ruby на Java, и самое главное, у меня нет контакта с Создатель.AES-256: недопонимание векторов между реализацией Ruby и Java
Моя проблема связана с вектором IV в аутентификации AES-256. Приложение Ruby использует AESCrypt gem для шифрования и дешифрования пароля пользователя. Он отлично работает, и у меня уже есть несколько тысяч пользователей в БД.
Проблема в том, что я пытаюсь сделать то же самое в Java (я уже обновил JCE, чтобы разрешить длину в 256 бит). Ключ и IV записываются как двоичные строки в исходном коде ruby (см. Ниже), и когда я пытаюсь использовать его в Java, я получаю исключение, которое говорит о том, что длина IV должна быть 16 байтов (я знаю, что это должно быть 16 байтов, но двоичная строка в Ruby имеет 32 символа).
рубин код (работает отлично):
require 'openssl'
require 'digest/md5'
require 'base64'
module AESCrypt
KEY = "AB1CD237690AF13B6721AD237A"
IV = "por874hyufijdue7w63ysxwet4320o90"
TYPE = "AES-256-CBC"
def AESCrypt.key(key)
key = Digest::MD5.hexdigest(key)
key.slice(0..32)
end
# Encrypts a block of data given an encryption key and an
# initialization vector (iv). Keys, iv's, and the data returned
# are all binary strings. Cipher_type should be "AES-256-CBC",
# "AES-256-ECB", or any of the cipher types supported by OpenSSL.
# Pass nil for the iv if the encryption type doesn't use iv's (like
# ECB).
#:return: => String
#:arg: data => String
#:arg: key => String
#:arg: iv => String
#:arg: cipher_type => String
def AESCrypt.encrypt(data)
return nil if data.nil?
return data if data.blank?
aes = OpenSSL::Cipher::Cipher.new(TYPE)
aes.encrypt
aes.key = AESCrypt.key(KEY)
aes.iv = IV if IV != nil
result = aes.update(data) + aes.final
Base64.encode64(result)
end
end
и это мой Java-код (он должен делать то же самое, кажется, что работает с 16 символов/байт IV):
public static void main(String[] args) throws UnsupportedEncodingException {
String KEY = "AB1CD237690AF13B6721AD237A";
String IV = "por874hyufijdue7w63ysxwet4320o90";
SecretKeySpec key = generateKey(KEY);
String message = "password";
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphedText = cipher.doFinal(message.getBytes());
String encoded = Base64.encodeBase64String(ciphedText);
System.out.println("ENCRYPTED text= " + encoded);
}
public static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = password.getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
return secretKeySpec;
}
И я получаю это исключение (очевидно):
java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:516)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:339)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:859)
at javax.crypto.Cipher.init(Cipher.java:1370)
at javax.crypto.Cipher.init(Cipher.java:1301)
at com.javi.test.security.Test.main(Test.java:129)
Я думаю, что моя проблема в том, как я преобразовать Java строку IV в байтах []. Я думаю, что openSSL-код в ruby распаковывает (или делает что-то внутренне) 32 байта от IV до 16 байтов. Я много пробовал, но я схожу с ума.
У кого-то была такая же проблема или выяснить, где может быть моя проблема? Я опубликовал код шифрования, но у меня такая же проблема с расшифровкой.
Заранее благодарим за каждый ответ. :)
Я не знаю, как работает ruby / openssl, но, вероятно, только первые 16 символов молча используют внутривенно –
Я только что сделал тест, взяв в расчет только первые 16 символов моей строки IV. Зашифрованный мной текст - «123456», зашифрованный текст с помощью ruby-приложения - «APkjtkW8yg4ibXhc/OgO3w ==», а зашифрованный текст java - «n6ZD4972iputzGCstjifXw ==». Они не соответствуют друг другу :(Может быть, более раннее поколение KEY не работает, должно быть, я новичок в шифровании. Спасибо в любом случае @ArtjomB. –
Вы кодируете строку UTF-8 в Ruby-коде? UTF-8 по умолчанию, а строка UTF-8 будет кодироваться по-разному с ASCII/латинской строкой. – mcfinnigan