Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации
Учебное Введение и TOC Следующее Учебное руководство

Использование GSS-API Java для Безопасных Обменов сообщениями Без Программирования JAAS



Это учебное руководство представляет два примера приложения, демонстрирующие использование GSS-API Java для безопасных обменов сообщениями между связывающимися приложениями, в этом случае клиентским приложением и серверным приложением.

GSS-API Java использует то, что вызывают "механизмом безопасности", чтобы предоставить эти услуги. Реализация GSS-API, доступная с Java 2 Standard Edition платформа, содержит поддержку Kerberos механизм V5 в дополнение к любым другим специфичным для поставщика вариантам. Мы используем Kerberos механизм V5 для этого учебного руководства.

Чтобы выполнить аутентификацию между клиентом и сервером и установить криптографические ключи для безопасной передачи, механизм GSS-API нуждается в доступе к определенным учетным данным для локального объекта на каждой стороне соединения. В нашем случае учетные данные, используемые на клиентской стороне, состоят из билета Kerberos, и на серверной стороне, это состоит из длительного срока секретный ключ Kerberos. Билеты Kerberos могут дополнительно включать адрес узла и IPv4, и адреса узла IPv6 оба поддерживаются. GSS-API Java требует, чтобы механизм получил эти учетные данные из Предмета, связанного с контекстом управления доступом потока.

Чтобы заполнить Предмет с такими учетными данными, приложения клиента и сервера обычно будут сначала выполнять аутентификацию JAAS, используя модуль Kerberos. Учебное руководство по Аутентификации JAAS демонстрирует, как сделать это. Учебное руководство по Авторизации JAAS тогда демонстрирует, как связать аутентифицируемый Предмет с контекстом управления доступом потока. Утилита была также записана как удобство автоматически выполнить те операции от Вашего имени. Использование учебного руководства по Утилите Входа в систему JAAS демонстрирует, как использовать утилиту Login.

Для этого учебного руководства у нас не будет клиента и сервера, выполняют аутентификацию JAAS, и при этом мы не сделаем, чтобы они использовали утилиту Login. Вместо этого мы положимся на установку системного свойства javax.security.auth.useSubjectCredsOnly к false, который позволяет нам ослаблять ограничение требования, чтобы механизм GSS получил необходимые учетные данные из существующего Предмета, установленного JAAS. См. useSubjectCredsOnly Системное Свойство.

Отметьте: Это - упрощенное вводное учебное руководство. Например, мы не включаем файлов политики или выполняем пример кода, используя менеджера безопасности. В действительности код, используя GSS-API Java должен быть выполнен с менеджером безопасности, так, чтобы секретные операции безопасности не были бы позволены, если необходимые полномочия явно не предоставили.

Есть другое учебное руководство, Использование Утилиты Входа в систему JAAS и GSS-API Java для Безопасных Обменов сообщениями, который является точно так же как учебное руководство, которое Вы читаете за исключением того, что это использует утилиту Login, файлы политики, и более сложный конфигурационный файл входа в систему (Конфигурационный файл входа в систему, требуемый всякий раз, когда аутентификация JAAS делается, определяет требуемый модуль аутентификации).

Как со всеми учебными руководствами в этом ряду, базовая технология, используемая, чтобы поддерживать аутентификацию и безопасную передачу для приложений в этом учебном руководстве, Kerberos V5. См. Требования Kerberos.

Если Вы хотите сначала видеть учебный код в действии, можно пропустить непосредственно к Выполнению Программ SampleClient и SampleServer и затем вернуться к другим разделам, чтобы учиться больше.


Краткий обзор Приложений Клиента и сервера

Приложения для этого учебного руководства называют SampleClient и SampleServer.

Вот сводка выполнения приложений SampleClient и SampleServer:

  1. Запустите приложение SampleServer. SampleServer
    1. Читает его параметр, номер порта, что он должен слушать на для клиентских соединений.
    2. Создает ServerSocket для того, чтобы прислушаться к клиентским соединениям на том порту.
    3. Прислушивается к соединению.
  2. Запустите приложение SampleClient (возможно на различной машине). SampleClient
    1. Читает его параметры: (1) имя принципала Kerberos, который представляет SampleServer. (См. Имена Принципала Пользователя и Службы Kerberos.), (2) имя узла (машина), на которой SampleServer работает, и (3) номер порта, на котором SampleServer прислушивается к клиентским соединениям.
    2. Делает попытку сокетного соединения с SampleServer, используя узел и порт, это передали как параметры.
  3. Сокетное соединение принимается SampleServer, и оба приложения инициализируют DataInputStream и DataOutputStream от потоков входа и выхода сокета, чтобы использоваться для будущих обменов данными.
  4. SampleClient и SampleServer каждый инстанцирует GSSContext и следует за протоколом для того, чтобы установить совместно используемый контекст, который включит последующим безопасным обменам данными.
  5. SampleClient и SampleServer могут теперь надежно обмениваться сообщениями.
  6. Когда SampleClient и SampleServer делаются, обмениваясь сообщениями, они выполняют операции по зачистке местности.

Фактический код и более подробная информация представляются в следующих разделах.

Код SampleClient и SampleServer

Весь код и для программ SampleClient и для SampleServer находится в их main методы и могут быть разломаны на следующие подразделения:

  1. Получите Параметры командной строки
  2. Установите Сокетное соединение для Передач Между SampleClient и SampleServer
  3. Установите Контекст защиты
  4. Надежно сообщения Exchange
  5. Очистить

Отметьте: классы GSS-API Java, используемые этими программами (GSSManager, GSSContext, GSSName, GSSCredential, MessageProp, и Oid), находятся в org.ietf.jgss пакет.

Получение Параметров командной строки

Первая вещь оба наших клиента и сервера main методы делают читается параметры командной строки.

Параметры, Считанные SampleClient

SampleClient ожидает три параметра:

  1. Имя принципала службы - имя принципала Kerberos, который представляет SampleServer. (См. Имена Принципала Пользователя и Службы Kerberos.)
  2. Имя хоста - машина, на которой работает SampleServer.
  3. Номер порта - номер порта порта, на котором SampleServer прислушивается к соединениям.

Вот код для того, чтобы считать параметры командной строки:

if (args.length < 3) {
    System.out.println("Usage: java <options> Login SampleClient "
       + " <servicePrincipal> <hostName> <port>");
    System.exit(-1);
}

String server = args[0];
String hostName = args[1];
int port = Integer.parseInt(args[2]);

Параметр, Считанный SampleServer

SampleServer ожидает только один параметр:

Вот код для того, чтобы считать параметр командной строки:

if (args.length != 1) {
    System.out.println(
        "Usage: java <options> Login SampleServer <localPort>");
    System.exit(-1);
}

int localPort = Integer.parseInt(args[0]);

Установление Сокетного соединения для Обменов сообщениями

GSS-API Java обеспечивает методы для создания и интерпретации маркеров (непрозрачные данные байта). Маркеры содержат сообщения, которыми надежно обменяются между двумя коллегами, но метод фактической маркерной передачи до коллег. Для наших приложений SampleClient и SampleServer мы устанавливаем сокетное соединение между клиентом и сервером и обмениваемся данными, используя потоки входа и выхода сокета.

Код SampleClient Для Сокетного соединения

SampleClient передали как параметры имя хост-машины, на которой SampleServer работает, так же как номер порта, на котором SampleServer будет прислушиваться к соединениям, таким образом, у SampleClient есть все, который это должно установить сокетное соединение с SampleServer. Это использует следующий код, чтобы установить соединение и инициализировать DataInputStream и DataOutputStream для будущих обменов данными:

Socket socket = new Socket(hostName, port);

DataInputStream inStream = 
  new DataInputStream(socket.getInputStream());
DataOutputStream outStream = 
  new DataOutputStream(socket.getOutputStream());

System.out.println("Connected to server " 
   + socket.getInetAddress());

Код SampleServer Для Сокетного соединения

Приложение SampleServer передали как параметр номер порта, который будет использоваться для того, чтобы прислушаться к соединениям от клиентов. Это создает ServerSocket для того, чтобы слушать на том порту:

ServerSocket ss = new ServerSocket(localPort);

ServerSocket может тогда ожидать и принять соединение от клиента, и затем инициализировать DataInputStream и DataOutputStream для будущих обменов данными с клиентом:

Socket socket = ss.accept();

DataInputStream inStream =
    new DataInputStream(socket.getInputStream());
DataOutputStream outStream = 
    new DataOutputStream(socket.getOutputStream());

System.out.println("Got connection from client "
    + socket.getInetAddress());

accept метод ожидает, пока клиент (в нашем случае, SampleClient) не запрашивает соединение на узле и порту SampleServer, через который делает SampleClient

Socket socket = new Socket(hostName, port);

Когда соединение требуют и устанавливается, accept метод возвращает новый объект Сокета, связанный с новым портом. Сервер может связаться с клиентом по этому новому сокету и продолжать прислушиваться к другим клиентским запросам соединения на ServerSocket, связанном с исходным портом. Таким образом у программы сервера обычно есть цикл, который может обработать многократные запросы соединения.

Структура основного цикла для нашего SampleServer является следующим:

while (true) {

    Socket socket = ss.accept();

    <Establish input and output streams for the connection> 
    <Establish a context with the client> 
    <Exchange messages with the client>;
    <Clean up>;
}

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

while (true) {
    <accept a connection>;
    <create a thread to handle the client>;
}

Установление Контекста защиты

Прежде, чем два приложения могут использовать GSS-API Java, чтобы надежно обмениваться сообщениями между ними, они должны установить объединенный контекст защиты, используя их учетные данные. (Отметьте: В случае SampleClient были установлены учетные данные, когда утилита Login, аутентифицируемая пользователь, на имени которого SampleClient был выполнен, и так же для SampleServer.) Контекст защиты инкапсулирует информацию об общем состоянии, которая могла бы включать, например, криптографические ключи. Одно использование таких ключей могло бы быть должно зашифровать сообщения, которыми обменяются, если шифрование требуют.

Как часть установления контекста защиты, инициатор контекста (в нашем случае, SampleClient) аутентифицируется получателю (SampleServer), и может потребовать, чтобы получатель также аутентифицировался назад инициатору, когда мы говорим, что "взаимная аутентификация" имела место.

Оба приложения создают и используют объект GSSContext установить и поддержать общую информацию, которая составляет контекст защиты.

Инстанцирование объекта контекста делается по-другому инициатором контекста и получателем контекста. После того, как инициатор инстанцирует GSSContext, он может хотеть устанавливать различные опции контекста, которые определят характеристики требуемого контекста защиты, например, определяя, должна ли взаимная аутентификация иметь место. После того, как все требуемые характеристики были установлены, инициатор вызывает initSecContext метод, который производит маркер, требуемый получателем acceptSecContext метод.

В то время как методы GSS-API Java существуют для того, чтобы подготовить маркеры, которыми обменяются между приложениями, это - обязанность приложений фактически передать маркеры между ними. Так после того, как инициатор получил маркер от его звонка initSecContext, это отправляет тот маркер получателю. Акцепторные вызовы acceptSecContext, передача этого маркер. acceptSecContext метод может поочередно возвратить маркер. Если это делает, получатель должен отправить тот маркер инициатору, который должен тогда вызвать initSecContext снова и передача это этот маркер. Каждый раз initSecContext или acceptSecContext возвращает маркер, приложение, которое названный методом должно отправить маркер его коллеге, и та коллега должна передать маркер к своему соответствующему методу (acceptSecContext или initSecContext). Это продолжается, пока контекст полностью не устанавливается (который имеет место когда контекст isEstablished возвраты метода true).

Код установления контекста для наших примеров приложения описывается в следующем:

Установление контекста SampleClient

В нашем клиент-серверном сценарии SampleClient является инициатором контекста. Вот основные шаги, которые это делает, чтобы установить контекст защиты. Это

  1. Инстанцирует GSSContext.
  2. Устанавливает требуемые дополнительные функции на контексте.
  3. Циклы в то время как контекст еще не устанавливается, каждый раз вызывая initSecContext, отправка любого возвращенного маркера к SampleServer, и получения маркера (если любой) от SampleServer.

SampleClient Инстанцирование GSSContext

GSSContext создается, инстанцируя GSSManager и затем вызывая один из createContext методы. Класс GSSManager служит фабрикой для других важных классов API GSS. Это может создать экземпляры классов, реализовывая GSSContext, GSSCredential, и интерфейсы GSSName.

SampleClient получает экземпляр подкласса GSSManager по умолчанию, вызывая статический метод GSSManager getInstance:

GSSManager manager = GSSManager.getInstance();

Подкласс GSSManager по умолчанию является тем чей create* методы (createContext, и т.д.), возвращают классы, реализации которых поддерживают Kerberos как базовую технологию.

У метода фабрики GSSManager для того, чтобы создать контекст на стороне инициатора есть следующая подпись:

GSSContext createContext(GSSName peer, Oid mech, 
            GSSCredential myCred, int lifetime); 

Параметры описываются ниже, сопровождаются полным звонком createContext.

GSSName peer Параметр

Коллега в нашей клиент-серверной парадигме является сервером. Для peer параметр, мы нуждаемся в GSSName для принципала службы представление сервера. (См. Имена Принципала Пользователя и Службы Kerberos.) Строку для имени принципала службы передают как первый параметр SampleClient, который помещает параметр в его локальную названную Строковую переменную server. GSSManager manager используется, чтобы инстанцировать GSSName, вызывая один из createName методы. SampleClient вызывает createName метод со следующей подписью:

GSSName createName(String nameStr, Oid nameType);

SampleClient передает server Строка для nameStr параметр.

Вторым параметром является Oid, Oid представляет Универсальный Объектный Идентификатор. Oids являются иерархически глобально поддающимися толкованию идентификаторами, используемыми в пределах платформы GSS-API, чтобы идентифицировать типы имени и механизмы. Структура и кодирование Oids определяются в ISOIEC-8824 и стандартах ISOIEC-8825. Oid передал к createName методом является определенно Oid типа имени (не Oid механизма).

В GSS-API названия строк часто отображаются от независимого от механизма формата в специфичный для механизма формат. Обычно, Oid определяет, какой формат имени строка находится в том, так, чтобы механизм знал, как сделать это отображение. Передача в a null Oid указывает, что имя уже находится в собственном формате, который использует механизм. Дело обстоит так для server Строка; это находится в соответствующем формате для имени Версии 5 Kerberos. Таким образом SampleClient передает a null для Oid. Вот вызов:

GSSName serverName = manager.createName(server, null);

Oid mech Параметр

Второй параметр GSSManager createContext методом является Oid, представляющий механизм, который будет использоваться для аутентификации между клиентом и сервером во время установления контекста и для последующей безопасной передачи между ними.

Наше учебное руководство будет использовать Kerberos V5 в качестве механизма безопасности. Oid для Kerberos, механизм V5 определяется в RFC 1964 как "1.2.840.113554.1.2.2", таким образом, мы создаем такой Oid:

Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");

Передачи SampleClient krb5Oid как второй параметр createContext.

GSSCredential myCred Параметр

Третий параметр GSSManager createContext метод является GSSCredential представление учетных данных вызывающей стороны. Если Вы передаете null для этого параметра, как SampleClient делает, используются учетные данные по умолчанию.

int lifetime Параметр

Заключительный параметр GSSManager createContext метод int определение требуемого времени жизни, в секундах, для контекста, который создается. Передачи SampleClient GSSContext.DEFAULT_LIFETIME запрашивать время жизни по умолчанию.

Полный Вызов createContext

Теперь, когда у нас есть все необходимые параметры, вот вызов, который SampleClient выполняет, чтобы создать GSSContext:

GSSContext context = 
    manager.createContext(serverName,
                          krb5Oid,
                          null,
                          GSSContext.DEFAULT_LIFETIME);

Установка SampleClient Требуемых Опций

После инстанцирования контекста, и до фактического устанавливания контекста с получателем контекста, инициатор контекста может хотеть устанавливать различные варианты, которые определяют требуемые характеристики контекста защиты. Каждая такая опция устанавливается, вызывая a request метод на инстанцированном контексте. Больше всего request методы берут a boolean параметр за указание, требуют ли функцию. Для запроса не всегда возможно быть удовлетворенным, так, было ли это, может быть определен после установления контекста, вызывая один из get методы.

SampleClient запрашивает следующее:

  1. Взаимная аутентификация. Инициатор контекста всегда аутентифицируется получателю. Если инициатор запрашивает взаимную аутентификацию, то получатель также аутентифицируется инициатору.
  2. Конфиденциальность. Запрос конфиденциальности означает, что Вы запрашиваете включение шифрования для названного метода контекста wrap. Шифрование фактически используется только если объект MessageProp, который передают к wrap метод запрашивает конфиденциальность.
  3. Целостность. Это запрашивает целостность на wrap и getMIC методы. Когда целостность требуют, криптографический тег, известный, поскольку Код Целостности сообщения (MIC) будет сгенерирован, вызывая те методы. Когда getMIC вызывается, сгенерированный MIC появляется в возвращенном маркере. Когда wrap вызывается, MIC упаковывается вместе с сообщением (исходное сообщение или результат шифрования сообщения, в зависимости от того, была ли конфиденциальность применена), все как часть одного маркера. Можно впоследствии проверить MIC против сообщения, чтобы гарантировать, что сообщение не было изменено в пути.

SampleClient кодируют для того, чтобы обратиться с этими просьбами на GSSException context следующее:

context.requestMutualAuth(true);  // Mutual authentication
context.requestConf(true);  // Will use encryption later
context.requestInteg(true); // Will use integrity later

Отметьте: При использовании реализации GSSManager по умолчанию и механизма Kerberos, будут всегда предоставлять эти запросы.

Цикл Установления Контекста SampleClient

После того, как SampleClient инстанцировал GSSContext и определил требуемые опции контекста, он может фактически установить контекст защиты с SampleServer. Чтобы сделать так, у SampleClient есть цикл. Каждая итерация цикла

  1. Вызывает контекст initSecContext метод. Если это - первый вызов, метод передают a null маркер. Иначе, это передают маркер, последний раз отправленный SampleClient SampleServer (маркер, сгенерированный SampleServer, призывают acceptSecContext).
  2. Отправляет маркер, возвращенный initSecContext (если любой) к SampleServer. Первый звонок initSecContext всегда производит маркер. Последняя возможность не могла бы возвратить маркер.
  3. Проверки, чтобы видеть, устанавливается ли контекст. В противном случае SampleClient получает другой маркер от SampleServer и затем запускает следующую итерацию цикла.

Маркеры, возвращенные initSecContext или полученный от SampleServer помещаются в байтовый массив. Маркеры должны быть обработаны SampleClient и SampleServer как непрозрачные данные, которые передадут между ними и интерпретируют методами GSS-API Java.

initSecContext параметрами является байтовый массив, содержащий маркер, начальное смещение в тот массив того, где маркер начинается, и маркерная длина. Для первого вызова SampleClient передает нулевой маркер, так как никакой маркер еще не был получен от SampleServer.

Чтобы обмениваться маркерами с SampleServer, SampleClient использует DataInputStream inStream и DataOutputStream outStream это ранее устанавливало использование потоков входа и выхода для сокетного соединения, сделанного с SampleServer. Отметьте, что всякий раз, когда маркер пишется, число байтов в маркере пишется сначала, сопровождается маркером непосредственно. Причины обсуждаются во введении в раздел Обменов сообщениями SampleClient и SampleServer.

Вот цикл установления контекста SampleClient, сопровождаемый информацией об отображении кода о том, кто клиент и сервер и имела ли взаимная аутентификация фактически место:

byte[] token = new byte[0];

while (!context.isEstablished()) {

    // token is ignored on the first call
    token = context.initSecContext(token, 0, token.length);

    // Send a token to the server if one was generated by
    // initSecContext
    if (token != null) {
        System.out.println("Will send token of size "
                   + token.length + " from initSecContext.");
        outStream.writeInt(token.length);
        outStream.write(token);
        outStream.flush();
    }

    // If the client is done with context establishment
    // then there will be no more tokens to read in this loop
    if (!context.isEstablished()) {
        token = new byte[inStream.readInt()];
        System.out.println("Will read input token of size "
                   + token.length
                   + " for processing by initSecContext");
        inStream.readFully(token);
    }
}

System.out.println("Context Established! ");
System.out.println("Client is " + context.getSrcName());
System.out.println("Server is " + context.getTargName());
if (context.getMutualAuthState())
    System.out.println("Mutual authentication took place!");

Установление контекста SampleServer

В нашем клиент-серверном сценарии SampleServer является получателем контекста. Вот основные шаги, которые это делает, чтобы установить контекст защиты. Это

  1. Инстанцирует GSSContext.
  2. Циклы в то время как контекст еще не устанавливается, каждый раз получая маркер от SampleClient, вызывая acceptSecContext и передача этого маркер, и отправка любого возвращенного маркера к SampleClient.

SampleServer Инстанцирование GSSContext

Как описано в SampleClient Инстанцирование GSSContext, GSSContext создается, инстанцируя GSSManager и затем вызывая один из createContext методы.

Как SampleClient, SampleServer получает экземпляр подкласса GSSManager по умолчанию, вызывая статический метод GSSManager getInstance:

GSSManager manager = GSSManager.getInstance();

У метода фабрики GSSManager для того, чтобы создать контекст на стороне получателя есть следующая подпись:

GSSContext createContext(GSSCredential myCred);

Если Вы передаете null для параметра GSSCredential, как SampleServer делает, используются учетные данные по умолчанию. Контекст инстанцируют через следующее:

  GSSContext context = manager.createContext((GSSCredential)null);

Цикл Установления Контекста SampleServer

После того, как SampleServer инстанцировал GSSContext, он может установить контекст защиты с SampleClient. Чтобы сделать так, у SampleServer есть цикл, который продолжается, пока контекст не устанавливается. Каждая итерация цикла делает следующее:

  1. Получает маркер от SampleClient. Этот маркер является результатом SampleClient initSecContext вызвать.
  2. Вызывает контекст acceptSecContext метод, передавая это маркер только получается.
  3. Если acceptSecContext возвращает маркер, тогда SampleServer отправляет этот маркер SampleClient и затем запускает следующую итерацию цикла, если контекст еще не устанавливается.

Маркеры, возвращенные acceptSecContext или полученный от SampleClient помещаются в байтовый массив.

acceptSecContext параметрами является байтовый массив, содержащий маркер, начальное смещение в тот массив того, где маркер начинается, и маркерная длина.

Чтобы обмениваться маркерами с SampleClient, SampleServer использует DataInputStream inStream и DataOutputStream outStream это ранее устанавливало использование потоков входа и выхода для сокетного соединения, сделанного с SampleClient.

Вот цикл установления контекста SampleServer:

byte[] token = null;

while (!context.isEstablished()) {

    token = new byte[inStream.readInt()];
    System.out.println("Will read input token of size "
       + token.length
       + " for processing by acceptSecContext");
    inStream.readFully(token);
    
    token = context.acceptSecContext(token, 0, token.length);
    
    // Send a token to the peer if one was generated by
    // acceptSecContext
    if (token != null) {
        System.out.println("Will send token of size "
           + token.length
           + " from acceptSecContext.");
        outStream.writeInt(token.length);
        outStream.write(token);
        outStream.flush();
    }
}

System.out.print("Context Established! ");
System.out.println("Client is " + context.getSrcName());
System.out.println("Server is " + context.getTargName());
if (context.getMutualAuthState())
    System.out.println("Mutual authentication took place!");

Обмен сообщениями Надежно

Как только контекст защиты был установлен между SampleClient и SampleServer, они могут использовать контекст, чтобы надежно обмениваться сообщениями.

Методы GSSContext для Обмена сообщениями

Два типа методов существуют для того, чтобы подготовить сообщения к безопасному обмену: wrap и getMIC. Есть фактически два wrap методы (и два getMIC методы), где различиями между этими двумя является индикация относительно того, где входной сигнал (байтовый массив или входной поток) и куда вывод должен пойти (в возвращаемое значение байтового массива или в поток вывода).

Эти методы для того, чтобы подготовить сообщения к обмену, и соответствующие методы для интерпретации коллегой получающихся маркеров, описываются ниже.

обертка

wrap метод является основным методом для обменов сообщениями.

Подпись для wrap метод, вызванный SampleClient, является следующим:

byte[] wrap (byte[] inBuf, int offset, interface len, 
                MessageProp msgProp)

Вы передаете wrap сообщение (в inBuf), смещение в inBuf где сообщение начинается (offset), и длина сообщения (len). Вы также передаете MessageProp, который используется, чтобы указать на требуемый QOP (Качество защиты) и определить, требуется ли конфиденциальность (шифрование). Значение QOP выбирает криптографическую целостность и шифрование (если требующийся) алгоритм (ы), который будет использоваться. Алгоритмы, соответствующие различным значениям QOP, определяются провайдером базового механизма. Например, значения для Kerberos V5 определяются в RFC 1964 в разделе 4.2. Распространено определить 0 как значение QOP, чтобы запросить QOP по умолчанию.

wrap метод возвращает маркер, содержащий сообщение и криптографический Код Целостности сообщения (MIC) по этому. Сообщение, помещенное в маркер, будет зашифровано, если MessageProp укажет, что конфиденциальность требуется. Вы не должны знать формат возвращенного маркера; это должно быть обработано как непрозрачные данные. Вы отправляете возвращенный маркер своему равноправному приложению, которое вызывает unwrap метод, чтобы "развернуть" маркер, чтобы получить исходное сообщение и проверить его целостность.

getMIC

Если Вы просто хотите получить маркер, содержащий криптографический Код Целостности сообщения (MIC) для предоставленного сообщения, Вы вызываете getMIC. Демонстрационная причина, которую Вы могли бы хотеть сделать, это должно подтвердить с Вашей коллегой, что у Вас обоих есть те же самые данные, только транспортируя MIC для тех данных, не подвергаясь стоимости переноса данных непосредственно друг другу.

Подпись для getMIC метод, вызванный SampleServer, является следующим:

byte[] getMIC (byte[] inMsg, int offset, int len,
            MessageProp msgProp)

Вы передаете getMIC сообщение (в inMsg), смещение в inMsg где сообщение начинается (offset), и длина сообщения (len). Вы также передаете MessageProp, который используется, чтобы указать на требуемый QOP (Качество защиты). Распространено определить 0 как значение QOP, чтобы запросить QOP по умолчанию.

Если Вам создали маркер getMIC и сообщение, используемое, чтобы вычислить MIC (или сообщение, подразумеваемое, чтобы быть сообщением, на которое был вычислен MIC), можно вызвать verifyMIC метод, чтобы проверить MIC для сообщения. Если проверка успешна (то есть, если GSSException не бросается), оказывается, что сообщение является точно тем же самым, как это было, когда MIC был вычислен. Коллега, получающая сообщение от приложения обычно, ожидает MIC также, так, чтобы они могли проверить MIC и быть уверены, что сообщение не было изменено или повреждено в пути. Отметьте: Если Вы будете знать заранее это, то Вы будете хотеть MIC так же как сообщение тогда, более удобно использовать wrap и unwrap методы. Но могли быть ситуации, где сообщение и MIC получаются отдельно.

Подпись для verifyMIC соответствие getMIC показанный выше

void verifyMIC (byte[] inToken, int tokOffset, int tokLen,
        byte[] inMsg, int msgOffset, int msgLen,
        MessageProp msgProp);

Это проверяет MIC, содержавшийся в inToken (длины tokLen, запуск при смещении tokOffset) по сообщению, содержавшемуся в inMsg (длины msgLen, запуск при смещении msgOffset). MessageProp используется базовым механизмом, чтобы возвратить информацию вызывающей стороне, такой как QOP указание на силу защиты, которая была применена к сообщению.

Обмены сообщениями SampleClient и SampleServer

Обмены сообщениями между SampleClient и SampleServer получаются в итоге ниже, сопровождаются деталями кодирования.

Эти шаги являются "стандартными" шагами, используемыми для того, чтобы проверить клиент и сервер GSS-API. Группа в MIT записала клиенту GSS-API и серверу GSS-API, которые стали довольно популярными тестовыми программами для того, чтобы проверить функциональную совместимость между различными реализациями библиотеки GSS-API. (Эти примеры приложения GSS-API могут быть загружены как часть распределения Kerberos, доступного от MIT в http://web.mit.edu/kerberos.) Этот клиент и сервер от MIT следует за протоколом, что, как только контекст устанавливается, клиент отправляет сообщение через, и это ожидает назад MIC на том сообщении. Если Вы реализуете библиотеку GSS-API, это - обычная практика, чтобы протестировать это, выполняя или клиент или сервер, используя Вашу реализацию библиотеки против соответствующего равноправного сервера или клиента, который использует другую реализацию библиотеки GSS-API. Если обе реализации библиотеки будут соответствовать стандартам, то две коллеги будут в состоянии связаться успешно.

Одна импликация тестирования Вашего клиента или сервера против, записанных в C (как MIT), является способом, которым нужно обменяться маркерами. C реализации GSS-API не включают основанные на потоке методы. В отсутствие основанных на потоке методов на Вашей коллеге, когда Вы пишете маркер, следует сначала записать число байтов и затем записать маркер. Точно так же, когда Вы читаете маркер, Вы первое чтение число байтов и затем читаете маркер. Это - то, что делают SampleClient и SampleServer.

Вот сводка обменов сообщениями SampleClient и SampleServer:

  1. Вызовы SampleClient wrap зашифровать и вычислить MIC для сообщения.
  2. SampleClient отправляет маркер, возвращенный из wrap к SampleServer.
  3. Вызовы SampleServer unwrap получить исходное сообщение и проверить его целостность.
  4. Вызовы SampleServer getMIC вычислить MIC на дешифрованное сообщение.
  5. SampleServer отправляет маркер, возвращенный getMIC (который содержит MIC) к SampleClient.
  6. Вызовы SampleClient verifyMIC проверять, что MIC, отправленный SampleServer, является допустимым MIC для исходного сообщения.

Код SampleClient, чтобы Зашифровать сообщение и Отправить Это

Код SampleClient для того, чтобы зашифровать сообщение, вычисляя MIC для этого, и отправляя результат SampleServer является следующим:

byte[] messageBytes = "Hello There!\0".getBytes();

/*
 * The first MessageProp argument is 0 to request
 * the default Quality-of-Protection.
 * The second argument is true to request
 * privacy (encryption of the message).
 */
MessageProp prop =  new MessageProp(0, true);

/*
 * Encrypt the data and send it across. Integrity protection
 * is always applied, irrespective of encryption.
 */
token = context.wrap(messageBytes, 0, messageBytes.length, 
    prop);
System.out.println("Will send wrap token of size " 
    + token.length);
outStream.writeInt(token.length);
outStream.write(token);
outStream.flush();

Код SampleServer, чтобы Развернуть Маркер, Вычислите MIC, и Отправьте Это

Следующий код SampleServer читает обернутый маркер, отправленный SampleClient, и "разворачивает" это, чтобы получить исходное сообщение и проверить его целостность. Разворачивание в этом случае включает дешифрование, так как сообщение было зашифровано.

Отметьте: Здесь проверка целостности, как ожидают, успешно выполнится. Но отметьте, что вообще, если проверка целостности перестала работать, она показывает, что сообщение было изменено в пути. Если unwrap метод встречается с отказом проверки целостности, он бросает GSSException с главным кодом ошибки GSSException. BAD_MIC.

/*
 * Create a MessageProp which unwrap will use to return 
 * information such as the Quality-of-Protection that was 
 * applied to the wrapped token, whether or not it was 
 * encrypted, etc. Since the initial MessageProp values
 * are ignored, it doesn't matter what they are set to.
 */
MessageProp prop = new MessageProp(0, false);

/* 
 * Read the token. This uses the same token byte array 
 * as that used during context establishment.
 */
token = new byte[inStream.readInt()];
System.out.println("Will read token of size " 
    + token.length);
inStream.readFully(token);

byte[] bytes = context.unwrap(token, 0, token.length, prop);
String str = new String(bytes);
System.out.println("Received data \""
    + str + "\" of length " + str.length());
System.out.println("Encryption applied: "
    + prop.getPrivacy());

Затем, SampleServer генерирует MIC для дешифрованного сообщения и отправляет его SampleClient. Это не действительно необходимо, но просто иллюстрирует генерирование MIC на дешифрованном сообщении, которое должно быть точно тем же самым как исходным сообщением SampleClient, обернутый и отправленный SampleServer. Когда SampleServer генерирует это и отправляет это SampleClient, и SampleClient проверяет это, это доказывает SampleClient, что дешифрованное сообщение, которое имеет SampleServer, является фактически точно тем же самым как исходным сообщением от SampleClient.

/*
 * First reset the QOP of the MessageProp to 0
 * to ensure the default Quality-of-Protection
 * is applied.
 */
prop.setQOP(0);

token = context.getMIC(bytes, 0, bytes.length, prop);

System.out.println("Will send MIC token of size " 
                   + token.length);
outStream.writeInt(token.length);
outStream.write(token);
outStream.flush();

Код SampleClient, чтобы Проверить MIC

Следующий код SampleClient читает MIC, вычисленный SampleServer на дешифрованное сообщение, и затем проверяет, что MIC является MIC для исходного сообщения, доказывая, что дешифрованное сообщение, которое имеет SampleServer, является тем же самым как исходным сообщением:

token = new byte[inStream.readInt()];
System.out.println("Will read token of size " + token.length);
inStream.readFully(token);

/* 
 * Recall messageBytes is the byte array containing
 * the original message and prop is the MessageProp 
 * already instantiated by SampleClient.
 */
context.verifyMIC(token, 0, token.length, 
          messageBytes, 0, messageBytes.length,
          prop);

System.out.println("Verified received MIC for message.");

Очистить

Когда SampleClient и SampleServer закончили обмениваться сообщениями, они должны выполнить операции уборки. Оба содержат следующий код к
socket.close();
context.dispose();

Пользователь Kerberos и Имена Принципала Службы

Начиная с базовой аутентификации и безопасной коммуникационной технологии, используемой этим учебным руководством, Kerberos V5, мы используем имена принципала стиля Kerberos везде, где пользователь или служба вызываются.

Например, когда Вы выполняете SampleClient, Вас просят обеспечить Ваше имя пользователя. Ваше имя пользователя стиля Kerberos является просто именем пользователя, Вы были присвоены для аутентификации Kerberos. Это состоит из основного имени пользователя (как "mjones") сопровождаемый и Ваша область (как "mjones@KRBNT-OPERATIONS.EXAMPLE.COM").

Программа сервера как SampleServer, как обычно полагают, предлагает "услугу" и выполняется от имени определенного "принципала службы." Имя принципала службы для SampleServer необходимо в нескольких местах:

Всюду по этому документу, и в сопроводительном конфигурационном файле входа в систему,

service_principal@your_realm
используется в качестве заполнителя, который будет заменен подлинным именем, которое будет использоваться в Вашей среде. Любой принципал Kerberos может фактически использоваться для имени принципала службы. Так в целях испытать это учебное руководство, Вы могли использовать свое имя пользователя и в качестве клиентского имени пользователя и в качестве имени принципала службы.

В продуктивной среде системные администраторы обычно как серверы, которые будут выполнены, поскольку, определенные принципалы только и могут присвоить определенное имя, которое будет использоваться. Часто присвоенное имя принципала службы стиля Kerberos имеет форму

service_name/machine_name@realm; 

Например, у службы nfs, на которой работают машина, названная "вороном" в области под названием "KRBNT-OPERATIONS.EXAMPLE.COM", могло быть имя принципала службы

nfs/raven@KRBNT-OPERATIONS.EXAMPLE.COM

Такие многокомпонентные имена не требуются, как бы то ни было. Единственные имена компонентов, точно так же как таковые из пользовательских принципалов, могут использоваться. Например, установка могла бы использовать тот же самый принципал службы протокола передачи файлов ftp@realm для всех серверов протокола передачи файлов в той области, в то время как у другой установки могли бы быть различные принципалы протокола передачи файлов для различных серверов протокола передачи файлов, такой как ftp/host1@realm и ftp/host2@realm на машинах host1 и host2, соответственно.

Когда Область Требуется на Основные Имена

Если область пользователя или имени принципала службы является областью по умолчанию (см. Требования Kerberos), можно бросить область, когда Вы регистрируете в Kerberos (то есть, когда Вы запрашиваетесь Ваше имя пользователя). Таким образом, например, если Ваше имя пользователя "mjones@KRBNT-OPERATIONS.EXAMPLE.COM", и Вы выполняете SampleClient, когда это запрашивает Ваше имя пользователя, Вы могли только определить "mjones", бросая область. Имя интерпретируется в контексте того, чтобы быть именем принципала Kerberos, и область по умолчанию добавляется, как необходимый.

Можно также бросить область, если основное имя будет преобразовано в GSSName GSSManager createName метод. Например, когда Вы выполняете SampleClient, одним из параметров является имя принципала серверной службы. Можно определить имя без включения области, потому что SampleClient передает имя к такому createName метод, который добавляет область по умолчанию как необходимый.

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

Конфигурационный файл Входа в систему

Для этого учебного руководства мы позволяем базовому механизму Kerberos получать учетные данные пользовательского выполнения SampleClient и SampleServer, вместо того, чтобы вызывать методы JAAS непосредственно (как в Аутентификации JAAS и учебных руководствах по Авторизации JAAS) или косвенно (например, через утилиту Login, описанную в Использовании учебного руководства по Утилите Входа в систему JAAS и в Использовании Утилиты Входа в систему JAAS и GSS-API Java для Безопасного учебного руководства по Обменам сообщениями).

Реализация механизма Kerberos по умолчанию, предоставленная Sun Microsystems фактически, запрашивает имя и пароль Kerberos и аутентифицирует указанного пользователя (или служба) к Kerberos KDC. Механизм полагается на JAAS, чтобы выполнить эту аутентификацию.

JAAS поддерживает сменную платформу аутентификации, означая, что любой тип модуля аутентификации может быть включен в соответствии с вызывающим приложением. Конфигурация входа в систему определяет модуль входа в систему, который будет использоваться для определенного приложения. Реализация JAAS по умолчанию от Sun Microsystems требует, чтобы конфигурационная информация входа в систему была определена в файле. (Отметьте: у Некоторых других поставщиков не могло бы быть основанных на файле реализаций.) Видят Конфигурационный файл Входа в систему JAAS для информации относительно того, каков конфигурационный файл входа в систему, что это содержит, и как определить, какой конфигурационный файл входа в систему должен использоваться.

Для этого учебного руководства, модуля входа в систему Kerberos com.sun.security.auth.module.Krb5LoginModule определяется в конфигурационном файле. Этот модуль входа в систему запрашивает имя и пароль Kerberos и попытки аутентифицировать к Kerberos KDC.

И SampleClient и SampleServer могут использовать тот же самый конфигурационный файл входа в систему, если тот файл содержит две записи, одну запись для клиентской стороны и один для серверной стороны.

Конфигурационный файл входа в систему bcsLogin.conf, используемый для этого учебного руководства, является следующим:

com.sun.security.jgss.initiate  {
  com.sun.security.auth.module.Krb5LoginModule required;
};

com.sun.security.jgss.accept  {
  com.sun.security.auth.module.Krb5LoginModule required storeKey=true 
};

Записи с этими двумя именами (com.sun.security.jgss.initiate и com.sun.security.jgss.accept) используются реализациями Sun механизмов GSS-API, когда они нуждаются в новых учетных данных. Так как механизмом, используемым в этом учебном руководстве, является Kerberos механизм V5, модуль входа в систему Kerberos должен будет быть вызван, чтобы получить эти учетные данные. Таким образом мы перечисляем Krb5LoginModule как необходимый модуль в этих записях. com.sun.security.jgss.initiate запись определяет конфигурацию для клиентской стороны и com.sun.security.jgss.accept запись для серверной стороны.

Krb5LoginModule успешно выполняется, только если попытка войти в систему к Kerberos KDC как указанный объект успешна. Выполняя SampleClient или SampleServer, пользователь будет запрошен имя и пароль.

Запись SampleServer storeKey=true указывает, что секретный ключ должен быть вычислен от пароля, обеспеченного во время входа в систему, и это должно быть сохранено в частных учетных данных Предмета, создаваемого в результате входа в систему. Этот ключ впоследствии используется во время взаимной аутентификации, устанавливая контекст защиты между SampleClient и SampleServer.

Для получения информации обо всех возможных вариантах, которые можно передать к Krb5LoginModule, см. документацию Krb5LoginModule.

useSubjectCredsOnly Системное Свойство

Для этого учебного руководства мы устанавливаем системное свойство javax.security.auth.useSubjectCredsOnly к false, который позволяет нам ослаблять обычное ограничение требования, чтобы механизм GSS получил необходимые учетные данные из существующего Предмета, установленного JAAS. Когда это ограничение ослабляется, оно позволяет механизму получать учетные данные из некоторого специфичного для поставщика расположения. Например, некоторые поставщики могли бы хотеть использовать кэш операционной системы, если Вы существуете, в то время как другие могли бы хотеть читать из защищенного файла на диске.

Когда это ограничение ослабляется, Микросистема Sun, механизм Kerberos все еще ищет учетные данные в Предмете, связанном с контекстом управления доступом потока, но если это не находит никого там, это выполняет аутентификацию JAAS, используя модуль Kerberos, чтобы получить новые. Модуль Kerberos запрашивает Вас имя и пароль принципала Kerberos. Отметьте, что реализации механизма Kerberos от других поставщиков могут вести себя по-другому, когда это свойство устанавливается в false. Консультируйтесь с их документацией, чтобы определить поведение их реализации.

Выполнение Программ SampleClient и SampleServer

Чтобы выполнить программы SampleClient и SampleServer, сделайте следующее:

Подготовьте SampleServer к Выполнению

Чтобы подготовить SampleServer к выполнению, сделайте следующее:

  1. Скопируйте следующие файлы в каталог, доступный машиной, на которой Вы выполните SampleServer:
  2. Скомпилировать SampleServer.java:
    javac SampleServer.java
    

Подготовьте SampleClient к Выполнению

Чтобы подготовить SampleClient к выполнению, сделайте следующее:

  1. Скопируйте следующие файлы в каталог, доступный машиной, на которой Вы выполните SampleClient:
  2. Скомпилировать SampleClient.java:
    javac SampleClient.java
    

Выполните SampleServer

Важно выполнить SampleServer перед SampleClient, потому что SampleClient попытается сделать сокетное соединение с SampleServer, и это перестанет работать, если SampleServer еще не выполнит и примет сокетные соединения.

Чтобы выполнить SampleServer, убедиться, что выполнили это на машине, на этом, как ожидают, будут работать. Это машинное имя (имя хоста) определяется как параметр SampleClient. Имя принципала службы появляется в нескольких местах, включая конфигурационный файл входа в систему и файлы политики.

Пойдите в каталог, в котором Вы подготовили SampleServer к выполнению. Выполните SampleServer, определяя

Единственным параметром, требуемым SampleServer, является тот, определяющий номер порта, который будет использоваться для того, чтобы прислушаться к клиентским соединениям. Выберите высокий номер порта вряд ли, чтобы использоваться для чего-либо еще. Пример был бы чем-то как 4444.

Ниже полная команда, чтобы использовать и для Microsoft Windows и для систем Unix.

Важный: В этой команде следует заменить <port_number> с соответствующим номером порта, <your_realm> с Вашей областью Kerberos, и <your_kdc> с Вашим Kerberos KDC.

Вот команда:

java -Djava.security.krb5.realm=<your_realm> 
 -Djava.security.krb5.kdc=<your_kdc> 
 -Djavax.security.auth.useSubjectCredsOnly=false
 -Djava.security.auth.login.config=bcsLogin.conf 
 SampleServer <port_number>

Полная команда должна появиться на одной строке (или, на системах UNIX, на многократных строках, где каждая строка, но последнее завершается с "\" указание, что есть больше, чтобы прибыть). Многократные строки используются здесь только для четкости. Так как эта команда очень длинна, Вы, возможно, должны поместить ее в.bat файл (для Windows) или.sh файл (для UNIX) и затем петлять, чтобы выполнить команду.

SampleServer код прислушается к сокетным соединениям на указанном порту. Когда запрошено, введите имя и пароль Kerberos для принципала службы. Базовый механизм аутентификации Kerberos, определенный в конфигурационном файле входа в систему, зарегистрирует принципал службы в Kerberos.

Для предложений поиска и устранения неисправностей входа в систему см. Поиск и устранение неисправностей.

Выполните SampleClient

Чтобы выполнить SampleClient, сначала пойдите в каталог, в котором Вы подготовили SampleClient к выполнению. Выполните SampleClient, определяя

Параметры SampleClient (1) имя Kerberos принципала службы, который представляет SampleServer, (2) имя узла (машина), на которой SampleServer работает, и (3) номер порта, на котором SampleServer прислушивается к клиентским соединениям.

Ниже полная команда, чтобы использовать и для Windows и для систем Unix.

Важный: В этой команде следует заменить <service_principal>, <host>, <port_number>, <your_realm>, и <your_kdc> с соответствующими значениями (и примечание, что номер порта должен быть тем же самым как номером порта, который передают как параметр SampleServer). Эти значения не должны быть помещены в кавычки.

Вот команда:

java -Djava.security.krb5.realm=<your_realm> 
 -Djava.security.krb5.kdc=<your_kdc> 
 -Djavax.security.auth.useSubjectCredsOnly=false
 -Djava.security.auth.login.config=bcsLogin.conf 
 SampleClient <service_principal> <host> <port_number>

Введите полную команду на одной строке. Многократные строки используются здесь для четкости. Как с командой для того, чтобы выполнить SampleServer, если команда является слишком длинной, чтобы ввести непосредственно в Ваше окно команд, поместите это в.bat файл (Windows) или.sh файл (UNIX) и затем выполните тот файл.

Когда запрошено, введите свое имя пользователя Kerberos и пароль. Базовый механизм аутентификации Kerberos, определенный в конфигурационном файле входа в систему, зарегистрирует Вас в Kerberos. Код SampleClient запрашивает сокетное соединение с SampleServer. Как только SampleServer принимает соединение, SampleClient и SampleServer устанавливают совместно используемый контекст и затем обмениваются сообщениями как описано в этом учебном руководстве.

Для предложений поиска и устранения неисправностей входа в систему см. Поиск и устранение неисправностей.



Учебное Введение и TOC Следующее Учебное руководство

Oracle и/или его филиалы Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами