Динамическое создание шифра с использованием конфигурации: какие параметры необходимы?

Java использует класс Cipher как абстракцию конкретных реализаций шифров. В моем проекте я в основном использую симметричные блочные шифры (AES, Twofish, 3DES,...) и ищу способ динамического создания/инициализации любых возможных симметричных блочных шифров (используя конфигурацию XML), потому что я бы хотелось бы сделать шифрование настраиваемым.

Пример: <transformer type="cipher" cipher="AES/GCM/NoPadding" keysize="256" iv="true" unlimitedstrength="true" />

будет переведено на:

// Create secretKey using 'keysize' ...

if (encryption.isUnlimitedCrypto()) {
    Encryption.enableUnlimitedCrypto();
}

Cipher cipher = Cipher.getInstance(encryption.getCipherStr(), Encryption.PROVIDER);

if (encryption.isIvNeeded()) {
    byte[] iv = ... 
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
}
else {
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);
}

Мой вопрос таков: Какие параметры необходимы для создания экземпляра любого симметричного блочного шифра в Java?

Параметры (уже определены):

  • Строка шифра: строка для Cipher.getInstance(..), например. AES/CBC/PKCSЗаполнение
  • Размер ключа: размер ключа для генерации ключа (или функции получения ключа PBE).
  • Требуется IV: указывает, требуется ли IV, например. "true" для режимов CBC и GCM, но не для ECB
  • Размер IV: указывает размер IV (сейчас я предполагаю, что размер IV = размеру ключа, верно?)
  • Требуется неограниченная сила: указывает, необходимо ли включение файлов политики неограниченной силы.
  • Другие?

Первоначальный источник/проект:


person binwiederhier    schedule 21.10.2013    source источник
comment
Размер IV = размер ключа? Нет! Размер IV = размер блока, если в инструкциях для режима не указано иное.   -  person President James K. Polk    schedule 22.10.2013


Ответы (1)


Все режимы, кроме ECB, требуют IV. IV всегда будет равен размеру блока шифра (16 байтов для AES, 8 байтов для 3DES). Режим ECB небезопасен при шифровании более 1 блока открытого текста одним и тем же ключом, и его нельзя разрешать, если вы хотите обеспечить конфиденциальность.

Используемый алгоритм определяет, какой размер ключа требуется. AES, например, требует 128, 192 или 256. Политики неограниченной силы должны быть установлены для 192 и 256, если используется стандартный криптографический API Java. Политику неограниченной прочности нельзя переключать с помощью кода, ее необходимо установить в JRE конечных пользователей.

Если вы заботитесь о защите данных при передаче (а этот проект действительно нуждается в безопасности), я не могу убедить вас использовать для этого SSL/TLS. Создать безопасную криптосистему сложно, а массовое шифрование (то есть симметричные шифры, такие как AES, 3DES) сами по себе недостаточны для обеспечения безопасности. Вам также нужен криптографически надежный источник случайных данных, безопасный процесс обмена ключами и проверка целостности. Конфиденциальность трудно обеспечить без обеспечения целостности, которая обычно обеспечивается с помощью функций MAC. При внедрении безопасной криптосистемы следует избегать всех ловушек, таких как использование разных ключей для шифрования и MAC, правильная проверка MAC, чтобы не создавать вектор атаки по времени, использование надлежащего генератора случайных чисел, обеспечение целостности, чтобы не создавать дополняющий оракул и т. д.

Как видите, в защите передаваемых данных есть много движущихся частей, и выполнение этого с нуля может привести к уязвимостям, вызванным неправильно выбранными или неправильно сконфигурированными криптопримитивами. Вот почему TLS часто рекомендуется.

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

Используемый набор шифров — TLS_ECDH_anon_WITH_AES_128_CBC_SHA, который обычно не включен по умолчанию из-за вышеупомянутого отсутствия аутентификации. Ниже я разбиваю этот набор шифров

  • TLS — этот набор шифров был представлен стандартом TLS.
  • ECDH_anon — алгоритм Диффи-Хеллмана Eliptic Cuve используется для согласования ключей, однако согласование ключей не аутентифицируется.
  • AES_128_CBC — Advanced Encryption Standard с длиной ключа 128 бит в режиме цепочки блоков шифрования используется для массового шифрования.
  • SHA — алгоритм безопасного хеширования используется для обеспечения целостности зашифрованных данных.

Пример следует.

package com.stackoverflow._19505091;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;

public class AnonTLSExample {

    public static void main(String[] args) throws Exception {

        /* No certs for this example so we are using ECDH_anon exchange. */
        String[] cipherSuites = {"TLS_ECDH_anon_WITH_AES_128_CBC_SHA"};
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

        /* No certificates, use default secure random source.
         * If we were using authentication (and you should in a real
         * system), this is where we would load 
         * keystores and truststores. */
        sslContext.init(null, null, null);

        /* Create server socket. */
        SSLServerSocket ss = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(12345);
        ss.setEnabledCipherSuites(cipherSuites);

        /*
         * Normally when authentication is used only the client authenticates
         * the server. If you want the server to also authenticate the client
         * set this to true. This will establish bidirectional trust in the session.
         */
        ss.setWantClientAuth(false);

        /* Start server thread. */
        new Thread(new Server(ss), "ServerThread").start();

        /* Create client socket. */
        SSLSocket s = (SSLSocket) sslContext.getSocketFactory().createSocket();
        s.setEnabledCipherSuites(cipherSuites);

        /* Connect to server. */
        System.out.println("Client: Connecting...");
        s.connect(new InetSocketAddress("127.0.0.1", 12345));
        System.out.println("Client: Connected");

        /* Print out some TLS info for this connection. */
        SSLSession session = s.getSession();
        System.out.println("Client: Session secured with P: " + session.getProtocol() + " CS: " + session.getCipherSuite());

        /* Send the secret message. */
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
        String message = "Secret Message.";
        System.out.println("Client: Sending: " + message);
        dos.writeUTF(message);

        /* Wait for server to close stream. */
        System.out.println("Client: Waiting for server to close...");
        s.getInputStream().read();

        /* Close client socket. */
        s.close();
        System.out.println("Client: Done.");
    }


}

class Server implements Runnable {

    private final ServerSocket ss;

    public Server(ServerSocket ss){
        this.ss = ss;
    }

    @Override
    public void run() {
        try{
         /* Wait for client to connect. */
         System.out.println("Server: Waiting for connection...");
         Socket s = ss.accept();
         System.out.println("Server: Connected.");

         /* Read secret message. */
         DataInputStream dis = new DataInputStream(s.getInputStream());
         String message = dis.readUTF();
         System.out.println("Server: Received Message: " + message);

         /* Close our sockets. */
         s.close();
         ss.close();
         System.out.println("Server: Done.");
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}
person Dev    schedule 22.10.2013
comment
Спасибо за информацию о IV (размер IV = размер блока) и ECB, являющемся единственным режимом без IV. Мое приложение никак не влияет на безопасность транспорта, поэтому SSL/TLS меня не волнует. Неограниченная сила может быть включена программно с использованием отражения: github.com/binwiederhier/syncany/blob/ - person binwiederhier; 22.10.2013
comment
К сожалению, этот ответ не полностью отвечает на мой вопрос. Я до сих пор не знаю, полностью ли данные параметры идентифицируют шифр (чтобы создать его программно) - person binwiederhier; 22.10.2013
comment
Решено: реализация здесь: github.com/ binwiederhier/syncany/blob/ и использование здесь: github.com/binwiederhier/syncany/blob/ - person binwiederhier; 08.11.2013