Предисловие: Я не знаю, правильнее ли задавать этот вопрос здесь или на сайте Crypto. Не стесняйтесь перемещать, удалять или выполнять любые другие действия SE.
Меня попросили помочь обновить программное обеспечение для шифрования. Вообще говоря, программное обеспечение уже выполняет следующие шаги, ни один из которых не является особенно необычным. Я упустил обработку ошибок и Provider
аргументы для простоты публикации:
1) Создает случайный симметричный секретный ключ для использования с AES-128 (или AES-256, mutatis mutandis ):
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init (128, a_SecureRandom_instance);
SecretKey sessionKey = keygen.generateKey();
2) Обертывает симметричный секретный ключ в зависимости от того, использует ли пользователь ...
2a) ... открытый ключ RSA из пары ключей:
// OAEP wasn't used in this software for hysterical raisins
Cipher wrapper = Cipher.getInstance("RSA/ECB/PKCS1Padding");
wrapper.init (Cipher.WRAP_MODE, user_RSA_PublicKey);
2b) ... кодовая фраза:
SecretKey stretched = ...passphrase stretched through a PBKDF like bcrypt...;
// I don't remember whether it's specified as "AES" or "AESWrap" here
Cipher wrapper = Cipher.getInstance("AES or AESWrap/ECB/NoPadding");
wrapper.init (Cipher.WRAP_MODE, stretched);
2c) Любой маршрут, ключ сеанса переносится:
byte[] wrapped = wrapper.wrap(sessionKey);
3) Используется ключ сеансачтобы создать Cipher
, используя Cipher.ENCRYPT_MODE
вместе со случайным IV, а затем через него пропускаются данные. Эта часть довольно стандартная, но я могу опубликовать ее, если вы действительно хотите увидеть CipherInputStream
использование. Обернутый сеансовый ключ хранится вместе с зашифрованными данными и кучей HMAC всего, что находится под солнцем.
Позже, во время расшифровки, пользователь предоставляет либо закрытый ключ RSA, либо пароль для растяжения;программное обеспечение разворачивает симметричный ключ и расшифровывает данные.
Все это работало в течение некоторого времени. Но, конечно, пары ключей RSA становятся большими и медленными, поэтому они хотели бы поддержать дополнительную возможность для шага № 2 выше, в котором открытые ключи генерируются с использованием алгоритма эллиптической кривой (P384 ECDH - это обычный случай). И вот тут мы запутались.
Кажется, что не существует алгоритма замены JCE / преобразования для эллиптических кривых в вызове Cipher wrapper = Cipher.getInstance("RSA/ECB/PKCS1Padding")
. Единственный из перечисленных в документации Java - «ECIES», который (?), Кажется, больше нацелен на согласование ключей от нескольких сторон?
Все API, которые я могу найти для встроенного в JCE Java, или дажепросматривая Bouncy Castle, упоминайте только ключи ECDH в контексте соглашения о ключах и транспорта, где они используются для генерации симметричного секретного ключа вместо переноса существующего.
Я чувствую, что мы что-то здесь упускаем, возможно, из-за плохих предположений. Cipher.wrap()
действительно не вариант с ключами ECDH? Или это равно , но нам нужно сделать что-то напуганное, чтобы создать экземпляр ECIES Cipher
?