Обертка ключа AES с использованием другого ключа AES и развертывание для получения исходного ключа (RFC 3394 и RFC 5649) ⇐ JAVA
Обертка ключа AES с использованием другого ключа AES и развертывание для получения исходного ключа (RFC 3394 и RFC 5649)
Я пытаюсь обернуть ключ AES с использованием другого ключа AES и развернуть его, чтобы получить исходный ключ (RFC 3394 и RFC 5649). Способ упаковки и развертывания ключа следующий:
Упаковка ключей
[*]Преобразовать в байты[] [*]Перенос с использованием AES [*]Получить экземпляр шифрования Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); [*]Создать спецификацию IvParameterSpec [*]Создайте объект SecretKey из ключа-оболочки. SecretKey secretKey = new SecretKeySpec(wrapperKey, "AES"); [*]Инициализировать шифр для шифрования cipher.init(Cipher.WRAP_MODE, secretKey, iv); [*]Выполнить перенос byte[] WrapKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); [*]вернуть упакованный ключ
Развертывание ключа
[*]Преобразовать упакованный ключ в байт[] [*]Развертывание с использованием AES [*]Получить экземпляр шифрования Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); [*]Извлечение IV (16 байт) [*]Создайте объект SecretKey из ключа-оболочки. SecretKey secretKey = new SecretKeySpec(wrapperKey, "AES"); [*]Инициализировать шифр для шифрования cipher.init(Cipher.UNWRAP_MODE, secretKey, iv); [*]Выполнить развертывание Key unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
Проблема
Проблема, с которой я столкнулся при развертывании, заключается в том, что я не получаю обратно исходный ключ, а разница вызвана первыми 16 байтами в массиве байтов, которые имеют размер IV. Я отладил, но не смог найти причину, вызывающую это.
Используемые зависимости
SunJCE: Cipher.AES -> com.sun.crypto.provider.AESCipher$Общие псевдонимы: [Rijndael]
Ниже приведен результат.
1. Исходный ключ: 00112233445566778899aabbccddeeff
Исходный ключ в байтах[] : [-45, 77, 117, -37, 109, -9, -29, -114, 121, -21, -82, -5, -13, - 49, 125, 105, -90, -37, 113, -57, 93, 121, -25, -33]
Исходный IV: [-76, 50, 106, -33, -77, -80, -90, 53, -11, -91, 17, 25, -21, -63, -57, 17]
2.
Завернутый ключ: gxLT9+PTn8rikNLJnK1RcpNqFIL/fG7EPLVsIr5mwOA=
завернутый ключ в байт[] : [113, 0, 125, 123, 85, 97, 65, 123, 118, 91, -22, -117, 62, 37, 117, -11, - 119, 98, -128, 16, -85, -51, -47, 109, -15, -65, 123, -89, -92, -81, -78, 38]
IV из упакованного ключа: [113, 0, 125, 123, 85, 97, 65, 123, 118, 91, -22, -117, 62, 37, 117, -11]
3.
Развернутый ключ: RhzNRM6VgeHUTAkIpYfHnqbbccddeeff
Байт развернутого ключа[]: [22, 127, 98, 127, -117, 38, 4, -64, -6, 21, 85, 105, 38, 43, -49, -115, -90, -37, 113, -57, 93, 121, -25, -33]
========================================== Похоже, разница связана с 16 байтами (размер IV)
ключ организации: [-45, 77, 117, -37, 109, -9, -29, -114, 121, -21, -82, -5, -13, -49, 125, 105, -90, -37, 113, -57, 93, 121, -25, -33]
выходной ключ: [22, 127, 98, 127, -117, 38, 4, -64, -6, 21, 85, 105, 38, 43, -49, -115, -90, -37, 113, -57, 93, 121, -25, -33]
Добавление кода:
import javax.crypto.*; импортировать javax.crypto.spec.IvParameterSpec; импортировать javax.crypto.spec.SecretKeySpec; импортировать java.security.Key; импортировать java.security.SecureRandom; импортировать java.util.Arrays; импортировать java.util.Base64; публичный класс KeyWrapping { public static void main(String[] args) выдает исключение { String originalKeyHex = "00112233445566778899aabbccddeeff"; Перенос строкKeyHex = "000102030405060708090a0b0c0d0e0f"; // конвертируем шестнадцатеричные строки в байтовые массивы byte[] originalKey = hexStringToByteArray(originalKeyHex); byte[] WrapperKey = hexStringToByteArray(wrappingKeyHex); // Зашифровать ключ байт [] обернутый ключ = aesKeyWrapEncrypt (originalKey, WrapperKey); // Расшифруем ключ byte[] unwrappedKey = aesKeyWrapDecrypt(wrappedKey, WrapperKey); // Отображение результатов System.out.println("Исходный ключ: " + byteArrayToHexString(originalKey)); System.out.println("Завернутый ключ: " + byteArrayToHexString(wrappedKey)); System.out.println("Развернутый ключ: " + byteArrayToHexString(unwrappedKey)); } // Шифрование с переносом ключей AES частный статический byte[] aesKeyWrapEncrypt(byte[] keyToWrap, byte[] WrapperKey) выдает исключение { Шифр шифра = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Генерируем случайный вектор инициализации (IV) SecureRandom случайный = новый SecureRandom(); байт[] ivBytes = новый байт[16]; случайный.nextBytes(ivBytes); IvParameterSpec iv = новый IvParameterSpec(ivBytes); // Создаем объект SecretKey из ключа-обертки SecretKey secretKey = новый SecretKeySpec (wrapperKey, «AES»); // Инициализируем шифр для шифрования cipher.init(Cipher.WRAP_MODE, secretKey, iv); // Зашифровать ключ byte[] обернутыйKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); вернуть завернутый ключ; } // Расшифровка переноса ключей AES частный статический байт [] aesKeyWrapDecrypt (байт [] обернутый ключ, байт [] оберточный ключ) выдает исключение { Шифр шифра = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Извлекаем вектор инициализации (IV) из завернутого ключа байт[] ivBytes = новый байт[16]; System.arraycopy(wrappedKey, 0, ivBytes, 0, ivBytes.length); IvParameterSpec iv = новый IvParameterSpec(ivBytes); // Создаем объект SecretKey из ключа упаковки SecretKey secretKey = новый SecretKeySpec (оберточный ключ, «AES»); // Инициализируем шифр для дешифрования cipher.init(Cipher.UNWRAP_MODE, secretKey, iv); // Расшифруем ключ Ключ unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY); вернуть unwrappedKey.getEncoded(); } // Вспомогательный метод для преобразования массива байтов в шестнадцатеричную строку частная статическая строка byteArrayToHexString (массив байтов []) { вернуть Base64.getEncoder().encodeToString(массив); } // Вспомогательный метод для преобразования шестнадцатеричной строки в массив байтов частный статический байт [] hexStringToByteArray (String hexString) { return Base64.getDecoder().decode(hexString); } } Обновление:
Спасибо @президенту Джеймсу К. Полку за указание на конкретную проблему. Это работало с исправлением ниже.
// Шифрование с переносом ключей AES частный статический byte[] aesKeyWrapEncrypt(byte[] keyToWrap, byte[] WrapperKey) выдает исключение { ... byte[] обернутыйKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); // добавление IV к завернутому ключу результат байта [] = новый байт [ivBytes.length + обернутыйKey.length]; System.arraycopy(ivBytes, 0, результат, 0, ivBytes.length); System.arraycopy(wrappedKey, 0, результат, ivBytes.length, обернутыйKey.length); ...
Я пытаюсь обернуть ключ AES с использованием другого ключа AES и развернуть его, чтобы получить исходный ключ (RFC 3394 и RFC 5649). Способ упаковки и развертывания ключа следующий:
Упаковка ключей
[*]Преобразовать в байты[] [*]Перенос с использованием AES [*]Получить экземпляр шифрования Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); [*]Создать спецификацию IvParameterSpec [*]Создайте объект SecretKey из ключа-оболочки. SecretKey secretKey = new SecretKeySpec(wrapperKey, "AES"); [*]Инициализировать шифр для шифрования cipher.init(Cipher.WRAP_MODE, secretKey, iv); [*]Выполнить перенос byte[] WrapKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); [*]вернуть упакованный ключ
Развертывание ключа
[*]Преобразовать упакованный ключ в байт[] [*]Развертывание с использованием AES [*]Получить экземпляр шифрования Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); [*]Извлечение IV (16 байт) [*]Создайте объект SecretKey из ключа-оболочки. SecretKey secretKey = new SecretKeySpec(wrapperKey, "AES"); [*]Инициализировать шифр для шифрования cipher.init(Cipher.UNWRAP_MODE, secretKey, iv); [*]Выполнить развертывание Key unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
Проблема
Проблема, с которой я столкнулся при развертывании, заключается в том, что я не получаю обратно исходный ключ, а разница вызвана первыми 16 байтами в массиве байтов, которые имеют размер IV. Я отладил, но не смог найти причину, вызывающую это.
Используемые зависимости
SunJCE: Cipher.AES -> com.sun.crypto.provider.AESCipher$Общие псевдонимы: [Rijndael]
Ниже приведен результат.
1. Исходный ключ: 00112233445566778899aabbccddeeff
Исходный ключ в байтах[] : [-45, 77, 117, -37, 109, -9, -29, -114, 121, -21, -82, -5, -13, - 49, 125, 105, -90, -37, 113, -57, 93, 121, -25, -33]
Исходный IV: [-76, 50, 106, -33, -77, -80, -90, 53, -11, -91, 17, 25, -21, -63, -57, 17]
2.
Завернутый ключ: gxLT9+PTn8rikNLJnK1RcpNqFIL/fG7EPLVsIr5mwOA=
завернутый ключ в байт[] : [113, 0, 125, 123, 85, 97, 65, 123, 118, 91, -22, -117, 62, 37, 117, -11, - 119, 98, -128, 16, -85, -51, -47, 109, -15, -65, 123, -89, -92, -81, -78, 38]
IV из упакованного ключа: [113, 0, 125, 123, 85, 97, 65, 123, 118, 91, -22, -117, 62, 37, 117, -11]
3.
Развернутый ключ: RhzNRM6VgeHUTAkIpYfHnqbbccddeeff
Байт развернутого ключа[]: [22, 127, 98, 127, -117, 38, 4, -64, -6, 21, 85, 105, 38, 43, -49, -115, -90, -37, 113, -57, 93, 121, -25, -33]
========================================== Похоже, разница связана с 16 байтами (размер IV)
ключ организации: [-45, 77, 117, -37, 109, -9, -29, -114, 121, -21, -82, -5, -13, -49, 125, 105, -90, -37, 113, -57, 93, 121, -25, -33]
выходной ключ: [22, 127, 98, 127, -117, 38, 4, -64, -6, 21, 85, 105, 38, 43, -49, -115, -90, -37, 113, -57, 93, 121, -25, -33]
Добавление кода:
import javax.crypto.*; импортировать javax.crypto.spec.IvParameterSpec; импортировать javax.crypto.spec.SecretKeySpec; импортировать java.security.Key; импортировать java.security.SecureRandom; импортировать java.util.Arrays; импортировать java.util.Base64; публичный класс KeyWrapping { public static void main(String[] args) выдает исключение { String originalKeyHex = "00112233445566778899aabbccddeeff"; Перенос строкKeyHex = "000102030405060708090a0b0c0d0e0f"; // конвертируем шестнадцатеричные строки в байтовые массивы byte[] originalKey = hexStringToByteArray(originalKeyHex); byte[] WrapperKey = hexStringToByteArray(wrappingKeyHex); // Зашифровать ключ байт [] обернутый ключ = aesKeyWrapEncrypt (originalKey, WrapperKey); // Расшифруем ключ byte[] unwrappedKey = aesKeyWrapDecrypt(wrappedKey, WrapperKey); // Отображение результатов System.out.println("Исходный ключ: " + byteArrayToHexString(originalKey)); System.out.println("Завернутый ключ: " + byteArrayToHexString(wrappedKey)); System.out.println("Развернутый ключ: " + byteArrayToHexString(unwrappedKey)); } // Шифрование с переносом ключей AES частный статический byte[] aesKeyWrapEncrypt(byte[] keyToWrap, byte[] WrapperKey) выдает исключение { Шифр шифра = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Генерируем случайный вектор инициализации (IV) SecureRandom случайный = новый SecureRandom(); байт[] ivBytes = новый байт[16]; случайный.nextBytes(ivBytes); IvParameterSpec iv = новый IvParameterSpec(ivBytes); // Создаем объект SecretKey из ключа-обертки SecretKey secretKey = новый SecretKeySpec (wrapperKey, «AES»); // Инициализируем шифр для шифрования cipher.init(Cipher.WRAP_MODE, secretKey, iv); // Зашифровать ключ byte[] обернутыйKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); вернуть завернутый ключ; } // Расшифровка переноса ключей AES частный статический байт [] aesKeyWrapDecrypt (байт [] обернутый ключ, байт [] оберточный ключ) выдает исключение { Шифр шифра = Cipher.getInstance("AES/CBC/PKCS5Padding"); // Извлекаем вектор инициализации (IV) из завернутого ключа байт[] ivBytes = новый байт[16]; System.arraycopy(wrappedKey, 0, ivBytes, 0, ivBytes.length); IvParameterSpec iv = новый IvParameterSpec(ivBytes); // Создаем объект SecretKey из ключа упаковки SecretKey secretKey = новый SecretKeySpec (оберточный ключ, «AES»); // Инициализируем шифр для дешифрования cipher.init(Cipher.UNWRAP_MODE, secretKey, iv); // Расшифруем ключ Ключ unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY); вернуть unwrappedKey.getEncoded(); } // Вспомогательный метод для преобразования массива байтов в шестнадцатеричную строку частная статическая строка byteArrayToHexString (массив байтов []) { вернуть Base64.getEncoder().encodeToString(массив); } // Вспомогательный метод для преобразования шестнадцатеричной строки в массив байтов частный статический байт [] hexStringToByteArray (String hexString) { return Base64.getDecoder().decode(hexString); } } Обновление:
Спасибо @президенту Джеймсу К. Полку за указание на конкретную проблему. Это работало с исправлением ниже.
// Шифрование с переносом ключей AES частный статический byte[] aesKeyWrapEncrypt(byte[] keyToWrap, byte[] WrapperKey) выдает исключение { ... byte[] обернутыйKey = cipher.wrap(new SecretKeySpec(keyToWrap, "AES")); // добавление IV к завернутому ключу результат байта [] = новый байт [ivBytes.length + обернутыйKey.length]; System.arraycopy(ivBytes, 0, результат, 0, ivBytes.length); System.arraycopy(wrappedKey, 0, результат, ivBytes.length, обернутыйKey.length); ...
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение