You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2007/09/26 22:23:03 UTC
svn commit: r579785 - in /directory/sandbox/erodriguez/kerberos-pkinit/src:
main/java/org/apache/directory/server/kerberos/pkinit/
test/java/org/apache/directory/server/kerberos/pkinit/
Author: erodriguez
Date: Wed Sep 26 13:23:03 2007
New Revision: 579785
URL: http://svn.apache.org/viewvc?rev=579785&view=rev
Log:
Client and server-side implementations for PKINIT's Diffie-Hellman (DH) mechanism:
o Client component using DH group and generating key using octetstring2key(x) function.
o Server component using DH group and generating key using octetstring2key(x) function.
o Test case demonstrating use of Oakley 1024-bit Modular Exponential (MODP) well-known group 2 [RFC2412].
Added:
directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java (with props)
directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java (with props)
directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java (with props)
Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java?rev=579785&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java Wed Sep 26 13:23:03 2007
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.kerberos.pkinit;
+
+
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+
+/**
+ * The client-side of Diffie-Hellman key agreement for Kerberos PKINIT.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+class DhClient
+{
+ private static AlgorithmParameterSpec AES_IV = new IvParameterSpec( new byte[16] );
+
+ private KeyAgreement clientKeyAgree;
+ private SecretKey clientAesKey;
+
+
+ byte[] init( DHParameterSpec dhParamSpec ) throws Exception
+ {
+ // The client creates its own DH key pair, using the DH parameters from above.
+ KeyPairGenerator clientKpairGen = KeyPairGenerator.getInstance( "DH" );
+ clientKpairGen.initialize( dhParamSpec );
+ KeyPair clientKpair = clientKpairGen.generateKeyPair();
+
+ // The client creates and initializes its DH KeyAgreement object.
+ clientKeyAgree = KeyAgreement.getInstance( "DH" );
+ clientKeyAgree.init( clientKpair.getPrivate() );
+
+ // The client encodes its public key, and sends it over to the server.
+ return clientKpair.getPublic().getEncoded();
+ }
+
+
+ void doPhase( byte[] serverPubKeyEnc ) throws Exception
+ {
+ /*
+ * The client uses the server's public key for the first (and only) phase
+ * of its version of the DH protocol. Before it can do so, it has to
+ * instantiate a DH public key from the server's encoded key material.
+ */
+ KeyFactory clientKeyFac = KeyFactory.getInstance( "DH" );
+ X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec( serverPubKeyEnc );
+ PublicKey serverPubKey = clientKeyFac.generatePublic( x509KeySpec );
+
+ clientKeyAgree.doPhase( serverPubKey, true );
+ }
+
+
+ byte[] generateKey( byte[] clientDhNonce, byte[] serverDhNonce )
+ {
+ // ZZ length will be same as public key.
+ byte[] dhSharedSecret = clientKeyAgree.generateSecret();
+ byte[] x = dhSharedSecret;
+
+ if ( clientDhNonce != null && clientDhNonce.length > 0 )
+ {
+ x = concatenateBytes( dhSharedSecret, clientDhNonce );
+ x = concatenateBytes( dhSharedSecret, serverDhNonce );
+ }
+
+ byte[] secret = OctetString2Key.kTruncate( dhSharedSecret.length, x );
+ clientAesKey = new SecretKeySpec( secret, 0, 16, "AES" );
+
+ return clientAesKey.getEncoded();
+ }
+
+
+ /**
+ * Decrypt using AES in CTS mode.
+ *
+ * @param cipherText
+ * @return
+ * @throws Exception
+ */
+ byte[] decryptAes( byte[] cipherText ) throws Exception
+ {
+ // Use the secret key to encrypt/decrypt data.
+ Cipher serverCipher = Cipher.getInstance( "AES/CTS/NoPadding" );
+ serverCipher.init( Cipher.DECRYPT_MODE, clientAesKey, AES_IV );
+
+ return serverCipher.doFinal( cipherText );
+ }
+
+
+ byte[] concatenateBytes( byte[] array1, byte[] array2 )
+ {
+ byte concatenatedBytes[] = new byte[array1.length + array2.length];
+
+ for ( int i = 0; i < array1.length; i++ )
+ {
+ concatenatedBytes[i] = array1[i];
+ }
+
+ for ( int j = array1.length; j < concatenatedBytes.length; j++ )
+ {
+ concatenatedBytes[j] = array2[j - array1.length];
+ }
+
+ return concatenatedBytes;
+ }
+}
Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java?rev=579785&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java Wed Sep 26 13:23:03 2007
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.kerberos.pkinit;
+
+
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+
+/**
+ * The server-side of Diffie-Hellman key agreement for Kerberos PKINIT.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+class DhServer
+{
+ private static AlgorithmParameterSpec AES_IV = new IvParameterSpec( new byte[16] );
+
+ private KeyAgreement serverKeyAgree;
+ private SecretKey serverAesKey;
+
+
+ byte[] initAndDoPhase( byte[] clientPubKeyEnc ) throws Exception
+ {
+ /*
+ * The server has received the client's public key in encoded format. The
+ * server instantiates a DH public key from the encoded key material.
+ */
+ KeyFactory serverKeyFac = KeyFactory.getInstance( "DH" );
+ X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec( clientPubKeyEnc );
+ PublicKey clientPubKey = serverKeyFac.generatePublic( x509KeySpec );
+
+ /*
+ * The server gets the DH parameters associated with the client's public
+ * key. The server must use the same parameters when it generates its own key pair.
+ */
+ DHParameterSpec dhParamSpec = ( ( DHPublicKey ) clientPubKey ).getParams();
+
+ // The server creates its own DH key pair.
+ KeyPairGenerator serverKpairGen = KeyPairGenerator.getInstance( "DH" );
+ serverKpairGen.initialize( dhParamSpec );
+ KeyPair serverKpair = serverKpairGen.generateKeyPair();
+
+ // The server creates and initializes its DH KeyAgreement object.
+ serverKeyAgree = KeyAgreement.getInstance( "DH" );
+ serverKeyAgree.init( serverKpair.getPrivate() );
+
+ /*
+ * The server uses the client's public key for the only phase of its
+ * side of the DH protocol.
+ */
+ serverKeyAgree.doPhase( clientPubKey, true );
+
+ // The server encodes its public key, and sends it over to the client.
+ return serverKpair.getPublic().getEncoded();
+ }
+
+
+ byte[] generateKey( byte[] clientDhNonce, byte[] serverDhNonce )
+ {
+ // ZZ length will be same as public key.
+ byte[] dhSharedSecret = serverKeyAgree.generateSecret();
+ byte[] x = dhSharedSecret;
+
+ if ( clientDhNonce != null && clientDhNonce.length > 0 )
+ {
+ x = concatenateBytes( dhSharedSecret, clientDhNonce );
+ x = concatenateBytes( dhSharedSecret, serverDhNonce );
+ }
+
+ byte[] secret = OctetString2Key.kTruncate( dhSharedSecret.length, x );
+ serverAesKey = new SecretKeySpec( secret, 0, 16, "AES" );
+
+ return serverAesKey.getEncoded();
+ }
+
+
+ /**
+ * Encrypt using AES in CTS mode.
+ *
+ * @param cleartext
+ * @return The cipher text.
+ * @throws Exception
+ */
+ byte[] encryptAes( byte[] clearText ) throws Exception
+ {
+ // Use the secret key to encrypt/decrypt data.
+ Cipher serverCipher = Cipher.getInstance( "AES/CTS/NoPadding" );
+ serverCipher.init( Cipher.ENCRYPT_MODE, serverAesKey, AES_IV );
+
+ return serverCipher.doFinal( clearText );
+ }
+
+
+ byte[] concatenateBytes( byte[] array1, byte[] array2 )
+ {
+ byte concatenatedBytes[] = new byte[array1.length + array2.length];
+
+ for ( int i = 0; i < array1.length; i++ )
+ {
+ concatenatedBytes[i] = array1[i];
+ }
+
+ for ( int j = array1.length; j < concatenatedBytes.length; j++ )
+ {
+ concatenatedBytes[j] = array2[j - array1.length];
+ }
+
+ return concatenatedBytes;
+ }
+}
Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/main/java/org/apache/directory/server/kerberos/pkinit/DhServer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java
URL: http://svn.apache.org/viewvc/directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java?rev=579785&view=auto
==============================================================================
--- directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java (added)
+++ directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java Wed Sep 26 13:23:03 2007
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.kerberos.pkinit;
+
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Tests the Diffie-Hellman key agreement protocol between a client and server.
+ *
+ * Generating a Secret Key Using the Diffie-Hellman Key Agreement Algorithm
+ *
+ * Two parties use a key agreement protocol to generate identical secret keys for
+ * encryption without ever having to transmit the secret key. The protocol works
+ * by both parties agreeing on a set of values (a prime, a base, and a private
+ * value) which are used to generate a key pair.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DhKeyAgreementTest extends TestCase
+{
+ /**
+ * Tests Diffie-Hellman using Oakley 1024-bit Modular Exponential (MODP)
+ * well-known group 2 [RFC2412].
+ *
+ * @throws Exception
+ */
+ public void testPreGeneratedDhParams() throws Exception
+ {
+ DhClient client = new DhClient();
+ DhServer server = new DhServer();
+
+ byte[] clientPubKeyEnc = client.init( DhGroup.MODP_GROUP2 );
+ byte[] serverPubKeyEnc = server.initAndDoPhase( clientPubKeyEnc );
+
+ server.generateKey( null, null );
+
+ client.doPhase( serverPubKeyEnc );
+
+ client.generateKey( null, null );
+
+ byte[] clearText = "This is just an example".getBytes();
+
+ byte[] cipherText = server.encryptAes( clearText );
+ byte[] recovered = client.decryptAes( cipherText );
+
+ assertTrue( Arrays.equals( clearText, recovered ) );
+ }
+}
Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: directory/sandbox/erodriguez/kerberos-pkinit/src/test/java/org/apache/directory/server/kerberos/pkinit/DhKeyAgreementTest.java
------------------------------------------------------------------------------
svn:executable = *