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 2004/09/28 20:55:17 UTC
svn commit: rev 47414 - incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto
Author: erodriguez
Date: Tue Sep 28 11:55:16 2004
New Revision: 47414
Added:
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Confounder.java
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/CryptoService.java
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/DesStringToKey.java
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/GlobalSequenceNumber.java
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Nonce.java
incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/SequenceNumber.java
Log:
kerberos crypto package
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Confounder.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Confounder.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+import java.security.*;
+
+public class Confounder {
+
+ private static final SecureRandom random = new SecureRandom();
+
+ public static synchronized byte[] bytes(int size) {
+ return bytes(size, false);
+ }
+
+ public static synchronized byte[] bytes(int size, boolean testMode) {
+
+ /*
+ * Use setSeed call to improve unit test performance or else
+ * the first call to SecureRandom may take a second.
+ *
+ * TODO - consider removing testMode; in practice, I haven't found
+ * SecureRandom to start slowly at all
+ */
+ if (testMode)
+ random.setSeed("testModeSeedString".getBytes());
+
+ byte[] bytes = new byte[size];
+ random.nextBytes(bytes);
+ return bytes;
+ }
+
+ public static synchronized int intValue() {
+ byte[] data = Confounder.bytes(4);
+ int result = 0;
+ for (int i = 0; i < 4; i++)
+ result += data[i] * (16 ^ i);
+ return result;
+ }
+
+ public static synchronized long longValue() {
+ byte[] data = Confounder.bytes(4);
+ long result = 0;
+ for (int i = 0; i < 8; i++)
+ result += (data[i]) * (16L ^ i);
+ return result;
+ }
+}
+
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/CryptoService.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/CryptoService.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+import org.apache.kerberos.crypto.checksum.*;
+import org.apache.kerberos.crypto.encryption.*;
+import org.apache.kerberos.kdc.*;
+import org.apache.kerberos.messages.value.*;
+import org.apache.kerberos.util.*;
+
+import java.util.*;
+
+public class CryptoService {
+
+ private static final Map _encryptionEngines = new HashMap();
+ private static final Map _checksumEngines = new HashMap();
+
+ // TODO - these maps are classic configuration and, as such, probably belong elsewhere
+ public CryptoService() {
+ _encryptionEngines.put(EncryptionType.NULL, new NullEncryption());
+ _encryptionEngines.put(EncryptionType.DES_CBC_CRC, new DesCbcCrcEncryption());
+ _encryptionEngines.put(EncryptionType.DES_CBC_MD4, new DesCbcMd4Encryption());
+ _encryptionEngines.put(EncryptionType.DES_CBC_MD5, new DesCbcMd5Encryption());
+
+ _checksumEngines.put(ChecksumType.CRC32, new Crc32Checksum());
+ _checksumEngines.put(ChecksumType.RSA_MD4, new RsaMd4Checksum());
+ _checksumEngines.put(ChecksumType.RSA_MD5, new RsaMd5Checksum());
+ _checksumEngines.put(ChecksumType.SHA1, new Sha1Checksum());
+ }
+
+ public static ChecksumEngine getInstance(ChecksumType type) throws KerberosException {
+ if (!_checksumEngines.containsKey(type))
+ throw KerberosException.KDC_ERR_SUMTYPE_NOSUPP;
+ return (ChecksumEngine)_checksumEngines.get(type);
+ }
+
+ public static EncryptionEngine getInstance(EncryptionType type) throws KerberosException {
+ if (!_encryptionEngines.containsKey(type))
+ throw KerberosException.KDC_ERR_ETYPE_NOSUPP;
+ return (EncryptionEngine)_encryptionEngines.get(type);
+ }
+
+ public static EncryptionType getBestEncryptionType(EncryptionType[] requestedTypes) {
+
+ for (int i = 0; i < requestedTypes.length; i++) {
+ for (int j = 0; j < LocalConfig.DEFAULT_ETYPE_LIST.length; j++) {
+ if (requestedTypes[i] == LocalConfig.DEFAULT_ETYPE_LIST[j])
+ return LocalConfig.DEFAULT_ETYPE_LIST[j];
+ }
+ }
+ return LocalConfig.DEFAULT_ETYPE;
+ }
+
+ public static EncryptionKey getNewSessionKey() {
+ byte[] confounder = Confounder.bytes(8);
+ DesStringToKey subSessionKey = new DesStringToKey(new String(confounder));
+ return new EncryptionKey(EncryptionType.DES_CBC_MD5, subSessionKey.getKey());
+ }
+
+ public static byte[] getEncryptedTimestamp(EncryptionKey key, Date date)
+ throws KerberosException {
+ EncryptionEngine encryptionEngine = getInstance(key.getKeyType());
+ byte[] plaintext = ConversionUtils.long2octet(date.getTime());
+ return encryptionEngine.encrypt(plaintext, key.getKeyValue());
+ }
+
+ public byte[] encrypt(EncryptionKey key, byte[] plaintext) throws KerberosException {
+ EncryptionEngine encryptionEngine = getInstance(key.getKeyType());
+ return encryptionEngine.encrypt(plaintext, key.getKeyValue());
+ }
+
+ public EncryptionKey getEncryptionKey(String username, String password, String realm) {
+ DesStringToKey key = new DesStringToKey(username, password, realm);
+ byte[] keyBytes = key.getKey();
+ return new EncryptionKey(EncryptionType.DES_CBC_MD5, keyBytes);
+ }
+
+ public byte[] decrypt(EncryptionKey key, EncryptedData data) throws KerberosException {
+ // TODO - check for matching encryptionType and keyVersion
+ EncryptionEngine type = getInstance(key.getKeyType());
+
+ byte[] decTicketPart = type.decrypt(data.getCipherText(), key.getKeyValue());
+
+ byte[] asn1ticket = removeBytes(decTicketPart, type.confounderSize(), type.checksumSize());
+
+ return asn1ticket;
+ }
+
+ public EncryptedData getEncryptedData(EncryptionKey key, byte[] plainText)
+ throws KerberosException {
+
+ EncryptionEngine type = getInstance(key.getKeyType());
+
+ byte[] conFounder = Confounder.bytes(type.confounderSize());
+ byte[] zeroedChecksum = new byte[type.checksumSize()];
+ byte[] dataBytes = concatenateBytes(conFounder, concatenateBytes(zeroedChecksum,
+ padString(plainText)));
+ byte[] checksumBytes = type.calculateChecksum(dataBytes);
+ byte[] paddedDataBytes = padString(dataBytes);
+ for (int i = type.confounderSize(); i < type.confounderSize() + type.checksumSize(); i++)
+ paddedDataBytes[i] = checksumBytes[i - type.confounderSize()];
+ byte[] encryptedData = encrypt(key, paddedDataBytes);
+
+ return new EncryptedData(type.encryptionType(), key.getKeyVersion(), encryptedData);
+ }
+
+ // TODO - The classes below are key production util code and I can picture them moving
+ // to a key production base class when I add DES3 and/or AES support.
+
+ private byte[] padString(byte encodedString[]) {
+ int x;
+ if (encodedString.length < 8)
+ x = encodedString.length;
+ else
+ x = encodedString.length % 8;
+
+ if (x == 0)
+ return encodedString;
+
+ byte paddedByteArray[] = new byte[(8 - x) + encodedString.length];
+ for (int y = paddedByteArray.length - 1; y > encodedString.length - 1; y--)
+ paddedByteArray[y] = 0;
+
+ System.arraycopy(encodedString, 0, paddedByteArray, 0, encodedString.length);
+
+ return paddedByteArray;
+ }
+
+ private 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;
+ }
+
+ private byte[] removeBytes(byte[] array, int confounder, int checksum) {
+ byte lessBytes[] = new byte[array.length - confounder - checksum];
+
+ int j = 0;
+ for (int i = confounder + checksum; i < array.length; i++) {
+ lessBytes[j] = array[i];
+ j++;
+ }
+
+ return lessBytes;
+ }
+}
+
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/DesStringToKey.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/DesStringToKey.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+import org.bouncycastle.crypto.engines.*;
+import org.bouncycastle.crypto.modes.*;
+import org.bouncycastle.crypto.params.*;
+
+public class DesStringToKey {
+
+ private byte[] _desKey;
+
+ public DesStringToKey(String passPhrase) {
+ _desKey = generateKey(passPhrase);
+ }
+
+ // This is the concatenation order as designated in RFC 1510
+ public DesStringToKey(String password, String realmName, String userName) {
+ _desKey = generateKey(password + realmName + userName);
+ }
+
+ public byte[] getKey() {
+ return _desKey;
+ }
+
+ private byte[] generateKey(String passPhrase) {
+
+ byte encodedByteArray[] = characterEncodeString(passPhrase);
+
+ byte paddedByteArray[] = padString(encodedByteArray);
+
+ byte secretKey[] = fanFold(paddedByteArray);
+
+ DESParameters.setOddParity(secretKey);
+
+ if (DESParameters.isWeakKey(secretKey, 0))
+ secretKey = getStrongKey(secretKey);
+
+ secretKey = encryptSecretKey(paddedByteArray, secretKey);
+
+ DESParameters.setOddParity(secretKey);
+
+ if (DESParameters.isWeakKey(secretKey, 0))
+ secretKey = getStrongKey(secretKey);
+
+ return secretKey;
+ }
+
+ private byte[] fanFold(byte[] paddedByteArray) {
+
+ byte secretKey[] = new byte[8];
+
+ int i = paddedByteArray.length / 8;
+
+ for (int x = 0; x < i; x++) {
+ byte blockValue1[] = new byte[8];
+ System.arraycopy(paddedByteArray, x * 8, blockValue1, 0, 8);
+
+ if (x % 2 == 1) {
+ byte tempbyte1 = 0;
+ byte tempbyte2 = 0;
+ byte blockValue2[] = new byte[8];
+
+ for (int y = 0; y < 8; y++) {
+ tempbyte2 = 0;
+ for (int z = 0; z < 4; z++) {
+ tempbyte2 = (byte) ((1 << (7 - z)) & 0xff);
+ tempbyte1 |= (blockValue1[y] & tempbyte2) >>> (7 - 2 * z);
+ tempbyte2 = 0;
+ }
+ for (int z = 4; z < 8; z++) {
+ tempbyte2 = (byte) ((1 << (7 - z)) & 0xff);
+ tempbyte1 |= (blockValue1[y] & tempbyte2) << (2 * z - 7);
+ tempbyte2 = 0;
+ }
+ blockValue2[7 - y] = tempbyte1;
+ tempbyte1 = 0;
+ }
+
+ for (int a = 0; a < 8; a++)
+ blockValue2[a] = (byte) (((blockValue2[a] & 0xff) >>> 1) & 0xff);
+
+ System.arraycopy(blockValue2, 0, blockValue1, 0, blockValue2.length);
+ }
+
+ for (int a = 0; a < 8; a++)
+ blockValue1[a] = (byte) (((blockValue1[a] & 0xff) << 1) & 0xff);
+
+ // ... eXclusive-ORed with itself to form an 8-byte DES key
+ for (int b = 0; b < 8; b++)
+ secretKey[b] ^= blockValue1[b];
+ }
+ return secretKey;
+ }
+
+ // TODO - Re-evaluate when DES3 keys are supported. This is duplicated
+ // with parts of CryptoService, but makes this class standalone.
+ private byte[] encryptSecretKey(byte data[], byte key[]) {
+
+ CBCBlockCipher cipher = new CBCBlockCipher(new DESEngine());
+ KeyParameter kp = new KeyParameter(key);
+ ParametersWithIV iv;
+
+ iv = new ParametersWithIV(kp, key);
+ cipher.init(true, iv);
+
+ byte encKey[] = new byte[data.length];
+ byte ivBytes[] = new byte[8];
+
+ for (int x = 0; x < data.length / 8; x++) {
+ cipher.processBlock(data, x * 8, encKey, x * 8);
+ System.arraycopy(encKey, x * 8, ivBytes, 0, 8);
+ iv = new ParametersWithIV(kp, ivBytes);
+ cipher.init(true, iv);
+ }
+
+ return ivBytes;
+ }
+
+ // Corrects the weak key by exclusive OR with 0xF0 constant.
+ private byte[] getStrongKey(byte keyValue[]) {
+ keyValue[7] ^= 0xf0;
+ return keyValue;
+ }
+
+ // Encodes string with ISO-Latin encoding
+ private byte[] characterEncodeString(String str) {
+ byte encodedByteArray[] = new byte[str.length()];
+ try {
+ encodedByteArray = str.getBytes("8859_1");
+ } catch (java.io.UnsupportedEncodingException ue) {
+ }
+ return encodedByteArray;
+ }
+
+ // Add padding to make an exact multiple of 8.
+ // TODO - Re-evaluate when DES3 keys are supported. This is duplicated
+ // with parts of CryptoService, but makes this class standalone.
+ private byte[] padString(byte encodedString[]) {
+ int x;
+ if (encodedString.length < 8)
+ x = encodedString.length;
+ else
+ x = encodedString.length % 8;
+
+ if (x == 0)
+ return encodedString;
+
+ byte paddedByteArray[] = new byte[(8 - x) + encodedString.length];
+ for (int y = paddedByteArray.length - 1; y > encodedString.length - 1; y--)
+ paddedByteArray[y] = 0;
+
+ System.arraycopy(encodedString, 0, paddedByteArray, 0, encodedString.length);
+
+ return paddedByteArray;
+
+ }
+}
+
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/GlobalSequenceNumber.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/GlobalSequenceNumber.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+public class GlobalSequenceNumber implements SequenceNumber {
+
+ private int _sequenceNumber = Confounder.intValue();
+
+ public GlobalSequenceNumber(int start) {
+ _sequenceNumber = start;
+ }
+
+ public synchronized void init() {
+ _sequenceNumber = Confounder.intValue();
+ }
+
+ public synchronized int current() {
+ return _sequenceNumber;
+ }
+
+ public synchronized int next() {
+ return _sequenceNumber + 1;
+ }
+
+ public synchronized void step() {
+ _sequenceNumber++;
+ }
+}
+
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Nonce.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/Nonce.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+public class Nonce {
+
+ private static int _nonce;
+
+ public static synchronized int getValue() {
+ int temp = (int)(System.currentTimeMillis() / 1000);
+ if (temp <= _nonce)
+ _nonce++;
+ else
+ _nonce = temp;
+ return _nonce;
+ }
+}
+
Added: incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/SequenceNumber.java
==============================================================================
--- (empty file)
+++ incubator/directory/kerberos/trunk/source/java/org/apache/kerberos/crypto/SequenceNumber.java Tue Sep 28 11:55:16 2004
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.kerberos.crypto;
+
+/**
+ * Sequence number
+ */
+public interface SequenceNumber {
+
+ /**
+ * Random initialization
+ */
+ public void init();
+
+ /**
+ * Returns current value
+ */
+ public int current();
+
+ /**
+ * Returns next value
+ */
+ public int next();
+
+ /**
+ * Increments the value
+ */
+ public void step();
+
+}
+