feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
85
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Aes128.java
Normal file
85
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Aes128.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.internal.crypto.dk.AesDkCrypto;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Class with static methods for doing AES operations.
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class Aes128 {
|
||||
private static final AesDkCrypto CRYPTO = new AesDkCrypto(128);
|
||||
|
||||
private Aes128() {
|
||||
}
|
||||
|
||||
public static byte[] stringToKey(char[] password, String salt, byte[] params)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.stringToKey(password, salt, params);
|
||||
}
|
||||
|
||||
// in bytes
|
||||
public static int getChecksumLength() {
|
||||
return CRYPTO.getChecksumLength();
|
||||
}
|
||||
|
||||
public static byte[] calculateChecksum(byte[] baseKey, int usage,
|
||||
byte[] input, int start, int len) throws GeneralSecurityException {
|
||||
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
|
||||
plaintext, start, len);
|
||||
}
|
||||
|
||||
/* Encrypt plaintext; do not add confounder, or checksum */
|
||||
public static byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
|
||||
/* Decrypt ciphertext; do not remove confounder, or check checksum */
|
||||
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.Checksum;
|
||||
|
||||
/*
|
||||
* This class encapsulates the encryption type for AES128
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public final class Aes128CtsHmacSha1EType extends EType {
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return blockSize();
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return Aes128.getChecksumLength();
|
||||
}
|
||||
|
||||
public int blockSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_AES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return encrypt(data, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
return Aes128.encrypt(key, usage, ivec, data, 0, data.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return decrypt(cipher, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
try {
|
||||
return Aes128.decrypt(key, usage, ivec, cipher, 0, cipher.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
// Override default, because our decrypted data does not return confounder
|
||||
// Should eventually get rid of EType.decryptedData and
|
||||
// EncryptedData.decryptedData altogether
|
||||
public byte[] decryptedData(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
88
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Aes256.java
Normal file
88
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Aes256.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.internal.crypto.dk.AesDkCrypto;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Class with static methods for doing AES operations.
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class Aes256 {
|
||||
private static final AesDkCrypto CRYPTO = new AesDkCrypto(256);
|
||||
|
||||
private Aes256() {
|
||||
}
|
||||
|
||||
public static byte[] stringToKey(char[] password, String salt, byte[] params)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.stringToKey(password, salt, params);
|
||||
}
|
||||
|
||||
// in bytes
|
||||
public static int getChecksumLength() {
|
||||
return CRYPTO.getChecksumLength();
|
||||
}
|
||||
|
||||
public static byte[] calculateChecksum(byte[] baseKey, int usage,
|
||||
byte[] input, int start, int len) throws GeneralSecurityException {
|
||||
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
|
||||
plaintext, start, len);
|
||||
}
|
||||
|
||||
/* Encrypt plaintext; do not add confounder, padding, or checksum */
|
||||
public static byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt ciphertext; do not remove confounder, padding, or check
|
||||
* checksum
|
||||
*/
|
||||
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.Checksum;
|
||||
|
||||
/*
|
||||
* This class encapsulates the encryption type for AES256
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public final class Aes256CtsHmacSha1EType extends EType {
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return blockSize();
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return Aes256.getChecksumLength();
|
||||
}
|
||||
|
||||
public int blockSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_AES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 32; // bytes
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return encrypt(data, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
return Aes256.encrypt(key, usage, ivec, data, 0, data.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return decrypt(cipher, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
try {
|
||||
return Aes256.decrypt(key, usage, ivec, cipher, 0, cipher.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
// Override default, because our decrypted data does not return confounder
|
||||
// Should eventually get rid of EType.decryptedData and
|
||||
// EncryptedData.decryptedData altogether
|
||||
public byte[] decryptedData(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
100
jdkSrc/jdk8/sun/security/krb5/internal/crypto/ArcFourHmac.java
Normal file
100
jdkSrc/jdk8/sun/security/krb5/internal/crypto/ArcFourHmac.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.internal.crypto.dk.ArcFourCrypto;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Class with static methods for doing RC4-HMAC operations.
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class ArcFourHmac {
|
||||
private static final ArcFourCrypto CRYPTO = new ArcFourCrypto(128);
|
||||
|
||||
private ArcFourHmac() {
|
||||
}
|
||||
|
||||
public static byte[] stringToKey(char[] password)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.stringToKey(password);
|
||||
}
|
||||
|
||||
// in bytes
|
||||
public static int getChecksumLength() {
|
||||
return CRYPTO.getChecksumLength();
|
||||
}
|
||||
|
||||
public static byte[] calculateChecksum(byte[] baseKey, int usage,
|
||||
byte[] input, int start, int len) throws GeneralSecurityException {
|
||||
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
|
||||
}
|
||||
|
||||
/* Encrypt Sequence Number */
|
||||
public static byte[] encryptSeq(byte[] baseKey, int usage,
|
||||
byte[] checksum, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encryptSeq(baseKey, usage, checksum, plaintext, start, len);
|
||||
}
|
||||
|
||||
/* Decrypt Sequence Number */
|
||||
public static byte[] decryptSeq(byte[] baseKey, int usage, byte[] checksum,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.decryptSeq(baseKey, usage, checksum, ciphertext, start, len);
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
|
||||
plaintext, start, len);
|
||||
}
|
||||
|
||||
/* Encrypt plaintext; do not add confounder, or checksum */
|
||||
public static byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] seqNum, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encryptRaw(baseKey, usage, seqNum, plaintext, start, len);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
|
||||
/* Decrypt ciphertext; do not remove confounder, or check checksum */
|
||||
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len, byte[] seqNum)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len, seqNum);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.Checksum;
|
||||
|
||||
/*
|
||||
* This class encapsulates the encryption type for RC4-HMAC
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public final class ArcFourHmacEType extends EType {
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_ARCFOUR_HMAC;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return ArcFourHmac.getChecksumLength();
|
||||
}
|
||||
|
||||
public int blockSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_ARCFOUR_HMAC;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return encrypt(data, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
return ArcFourHmac.encrypt(key, usage, ivec, data, 0, data.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return decrypt(cipher, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
try {
|
||||
return ArcFourHmac.decrypt(key, usage, ivec, cipher, 0, cipher.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
// Override default, because our decrypted data does not return confounder
|
||||
// Should eventually get rid of EType.decryptedData and
|
||||
// EncryptedData.decryptedData altogether
|
||||
public byte[] decryptedData(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
152
jdkSrc/jdk8/sun/security/krb5/internal/crypto/CksumType.java
Normal file
152
jdkSrc/jdk8/sun/security/krb5/internal/crypto/CksumType.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
public abstract class CksumType {
|
||||
|
||||
private static boolean DEBUG = Krb5.DEBUG;
|
||||
|
||||
public static CksumType getInstance(int cksumTypeConst)
|
||||
throws KdcErrException {
|
||||
CksumType cksumType = null;
|
||||
String cksumTypeName = null;
|
||||
switch (cksumTypeConst) {
|
||||
case Checksum.CKSUMTYPE_CRC32:
|
||||
cksumType = new Crc32CksumType();
|
||||
cksumTypeName = "sun.security.krb5.internal.crypto.Crc32CksumType";
|
||||
break;
|
||||
case Checksum.CKSUMTYPE_DES_MAC:
|
||||
cksumType = new DesMacCksumType();
|
||||
cksumTypeName = "sun.security.krb5.internal.crypto.DesMacCksumType";
|
||||
break;
|
||||
case Checksum.CKSUMTYPE_DES_MAC_K:
|
||||
cksumType = new DesMacKCksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.DesMacKCksumType";
|
||||
break;
|
||||
case Checksum.CKSUMTYPE_RSA_MD5:
|
||||
cksumType = new RsaMd5CksumType();
|
||||
cksumTypeName = "sun.security.krb5.internal.crypto.RsaMd5CksumType";
|
||||
break;
|
||||
case Checksum.CKSUMTYPE_RSA_MD5_DES:
|
||||
cksumType = new RsaMd5DesCksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.RsaMd5DesCksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
|
||||
cksumType = new HmacSha1Des3KdCksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha1Des3KdCksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
|
||||
cksumType = new HmacSha1Aes128CksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha1Aes128CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
|
||||
cksumType = new HmacSha1Aes256CksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacSha1Aes256CksumType";
|
||||
break;
|
||||
|
||||
case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
|
||||
cksumType = new HmacMd5ArcFourCksumType();
|
||||
cksumTypeName =
|
||||
"sun.security.krb5.internal.crypto.HmacMd5ArcFourCksumType";
|
||||
break;
|
||||
|
||||
// currently we don't support MD4.
|
||||
case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
|
||||
// cksumType = new RsaMd4DesKCksumType();
|
||||
// cksumTypeName =
|
||||
// "sun.security.krb5.internal.crypto.RsaMd4DesKCksumType";
|
||||
case Checksum.CKSUMTYPE_RSA_MD4:
|
||||
// cksumType = new RsaMd4CksumType();
|
||||
// linux box support rsamd4, how to solve conflict?
|
||||
// cksumTypeName =
|
||||
// "sun.security.krb5.internal.crypto.RsaMd4CksumType";
|
||||
case Checksum.CKSUMTYPE_RSA_MD4_DES:
|
||||
// cksumType = new RsaMd4DesCksumType();
|
||||
// cksumTypeName =
|
||||
// "sun.security.krb5.internal.crypto.RsaMd4DesCksumType";
|
||||
|
||||
default:
|
||||
throw new KdcErrException(Krb5.KDC_ERR_SUMTYPE_NOSUPP);
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println(">>> CksumType: " + cksumTypeName);
|
||||
}
|
||||
return cksumType;
|
||||
}
|
||||
|
||||
public abstract int confounderSize();
|
||||
|
||||
public abstract int cksumType();
|
||||
|
||||
public abstract boolean isKeyed();
|
||||
|
||||
public abstract int cksumSize();
|
||||
|
||||
public abstract int keyType();
|
||||
|
||||
public abstract int keySize();
|
||||
|
||||
// Note: key and usage will be ignored for an unkeyed checksum.
|
||||
public abstract byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) throws KrbCryptoException;
|
||||
|
||||
// Note: key and usage will be ignored for an unkeyed checksum.
|
||||
public abstract boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
|
||||
|
||||
public static boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
|
||||
if (cksum1 == cksum2)
|
||||
return true;
|
||||
if ((cksum1 == null && cksum2 != null) ||
|
||||
(cksum1 != null && cksum2 == null))
|
||||
return false;
|
||||
if (cksum1.length != cksum2.length)
|
||||
return false;
|
||||
for (int i = 0; i < cksum1.length; i++)
|
||||
if (cksum1[i] != cksum2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.*;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
public class Crc32CksumType extends CksumType {
|
||||
|
||||
public Crc32CksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_CRC32;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_NULL;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) {
|
||||
return crc32.byte2crc32sum_bytes(data, size);
|
||||
}
|
||||
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) {
|
||||
return CksumType.isChecksumEqual(checksum,
|
||||
crc32.byte2crc32sum_bytes(data));
|
||||
}
|
||||
|
||||
public static byte[] int2quad(long input) {
|
||||
byte[] output = new byte[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output[i] = (byte)((input >>> (i * 8)) & 0xff);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static long bytes2long(byte[] input) {
|
||||
long result = 0;
|
||||
|
||||
result |= (((long)input[0]) & 0xffL) << 24;
|
||||
result |= (((long)input[1]) & 0xffL) << 16;
|
||||
result |= (((long)input[2]) & 0xffL) << 8;
|
||||
result |= (((long)input[3]) & 0xffL);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
368
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Des.java
Normal file
368
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Des.java
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.security.GeneralSecurityException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.util.Arrays;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
public final class Des {
|
||||
|
||||
// RFC 3961 demands that UTF-8 encoding be used in DES's
|
||||
// string-to-key function. For historical reasons, some
|
||||
// implementations use a locale-specific encoding. Even
|
||||
// so, when the client and server use different locales,
|
||||
// they must agree on a common value, normally the one
|
||||
// used when the password is set/reset.
|
||||
//
|
||||
// The following system property is provided to perform the
|
||||
// string-to-key encoding. When set, the specified charset
|
||||
// name is used. Otherwise, the system default charset.
|
||||
|
||||
private final static String CHARSET =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new GetPropertyAction("sun.security.krb5.msinterop.des.s2kcharset"));
|
||||
|
||||
private static final long[] bad_keys = {
|
||||
0x0101010101010101L, 0xfefefefefefefefeL,
|
||||
0x1f1f1f1f1f1f1f1fL, 0xe0e0e0e0e0e0e0e0L,
|
||||
0x01fe01fe01fe01feL, 0xfe01fe01fe01fe01L,
|
||||
0x1fe01fe00ef10ef1L, 0xe01fe01ff10ef10eL,
|
||||
0x01e001e001f101f1L, 0xe001e001f101f101L,
|
||||
0x1ffe1ffe0efe0efeL, 0xfe1ffe1ffe0efe0eL,
|
||||
0x011f011f010e010eL, 0x1f011f010e010e01L,
|
||||
0xe0fee0fef1fef1feL, 0xfee0fee0fef1fef1L
|
||||
};
|
||||
|
||||
private static final byte[] good_parity = {
|
||||
1, 1, 2, 2, 4, 4, 7, 7,
|
||||
8, 8, 11, 11, 13, 13, 14, 14,
|
||||
16, 16, 19, 19, 21, 21, 22, 22,
|
||||
25, 25, 26, 26, 28, 28, 31, 31,
|
||||
32, 32, 35, 35, 37, 37, 38, 38,
|
||||
41, 41, 42, 42, 44, 44, 47, 47,
|
||||
49, 49, 50, 50, 52, 52, 55, 55,
|
||||
56, 56, 59, 59, 61, 61, 62, 62,
|
||||
64, 64, 67, 67, 69, 69, 70, 70,
|
||||
73, 73, 74, 74, 76, 76, 79, 79,
|
||||
81, 81, 82, 82, 84, 84, 87, 87,
|
||||
88, 88, 91, 91, 93, 93, 94, 94,
|
||||
97, 97, 98, 98, 100, 100, 103, 103,
|
||||
104, 104, 107, 107, 109, 109, 110, 110,
|
||||
112, 112, 115, 115, 117, 117, 118, 118,
|
||||
121, 121, 122, 122, 124, 124, 127, 127,
|
||||
(byte)128, (byte)128, (byte)131, (byte)131,
|
||||
(byte)133, (byte)133, (byte)134, (byte)134,
|
||||
(byte)137, (byte)137, (byte)138, (byte)138,
|
||||
(byte)140, (byte)140, (byte)143, (byte)143,
|
||||
(byte)145, (byte)145, (byte)146, (byte)146,
|
||||
(byte)148, (byte)148, (byte)151, (byte)151,
|
||||
(byte)152, (byte)152, (byte)155, (byte)155,
|
||||
(byte)157, (byte)157, (byte)158, (byte)158,
|
||||
(byte)161, (byte)161, (byte)162, (byte)162,
|
||||
(byte)164, (byte)164, (byte)167, (byte)167,
|
||||
(byte)168, (byte)168, (byte)171, (byte)171,
|
||||
(byte)173, (byte)173, (byte)174, (byte)174,
|
||||
(byte)176, (byte)176, (byte)179, (byte)179,
|
||||
(byte)181, (byte)181, (byte)182, (byte)182,
|
||||
(byte)185, (byte)185, (byte)186, (byte)186,
|
||||
(byte)188, (byte)188, (byte)191, (byte)191,
|
||||
(byte)193, (byte)193, (byte)194, (byte)194,
|
||||
(byte)196, (byte)196, (byte)199, (byte)199,
|
||||
(byte)200, (byte)200, (byte)203, (byte)203,
|
||||
(byte)205, (byte)205, (byte)206, (byte)206,
|
||||
(byte)208, (byte)208, (byte)211, (byte)211,
|
||||
(byte)213, (byte)213, (byte)214, (byte)214,
|
||||
(byte)217, (byte)217, (byte)218, (byte)218,
|
||||
(byte)220, (byte)220, (byte)223, (byte)223,
|
||||
(byte)224, (byte)224, (byte)227, (byte)227,
|
||||
(byte)229, (byte)229, (byte)230, (byte)230,
|
||||
(byte)233, (byte)233, (byte)234, (byte)234,
|
||||
(byte)236, (byte)236, (byte)239, (byte)239,
|
||||
(byte)241, (byte)241, (byte)242, (byte)242,
|
||||
(byte)244, (byte)244, (byte)247, (byte)247,
|
||||
(byte)248, (byte)248, (byte)251, (byte)251,
|
||||
(byte)253, (byte)253, (byte)254, (byte)254
|
||||
};
|
||||
|
||||
public static final byte[] set_parity(byte[] key) {
|
||||
for (int i=0; i < 8; i++) {
|
||||
key[i] = good_parity[key[i] & 0xff];
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public static final long set_parity(long key) {
|
||||
return octet2long(set_parity(long2octet(key)));
|
||||
}
|
||||
|
||||
public static final boolean bad_key(long key) {
|
||||
for (int i = 0; i < bad_keys.length; i++) {
|
||||
if (bad_keys[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final boolean bad_key(byte[] key) {
|
||||
return bad_key(octet2long(key));
|
||||
}
|
||||
|
||||
public static long octet2long(byte[] input) {
|
||||
return octet2long(input, 0);
|
||||
}
|
||||
|
||||
public static long octet2long(byte[] input, int offset) { //convert a 8-byte to a long
|
||||
long result = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i + offset < input.length) {
|
||||
result |= (((long)input[i + offset]) & 0xffL) << ((7 - i) * 8);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] long2octet(long input) {
|
||||
byte[] output = new byte[8];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
output[i] = (byte)((input >>> ((7 - i) * 8)) & 0xffL);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static void long2octet(long input, byte[] output) {
|
||||
long2octet(input, output, 0);
|
||||
}
|
||||
|
||||
public static void long2octet(long input, byte[] output, int offset) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i + offset < output.length) {
|
||||
output[i + offset] =
|
||||
(byte)((input >>> ((7 - i) * 8)) & 0xffL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DES cipher in Electronic Codebook mode, with no padding.
|
||||
* @param input plain text.
|
||||
* @param output the buffer for the result.
|
||||
* @param key DES the key to encrypt the text.
|
||||
* @param ivec initialization vector.
|
||||
*
|
||||
* @created by Yanni Zhang, Dec 6 99.
|
||||
*/
|
||||
public static void cbc_encrypt (
|
||||
byte[] input,
|
||||
byte[] output,
|
||||
byte[] key,
|
||||
byte[] ivec,
|
||||
boolean encrypt) throws KrbCryptoException {
|
||||
|
||||
Cipher cipher = null;
|
||||
|
||||
try {
|
||||
cipher = Cipher.getInstance("DES/CBC/NoPadding");
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException("JCE provider may not be installed. "
|
||||
+ e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
IvParameterSpec params = new IvParameterSpec(ivec);
|
||||
SecretKeySpec skSpec = new SecretKeySpec(key, "DES");
|
||||
try {
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
|
||||
// SecretKey sk = skf.generateSecret(skSpec);
|
||||
SecretKey sk = (SecretKey) skSpec;
|
||||
if (encrypt)
|
||||
cipher.init(Cipher.ENCRYPT_MODE, sk, params);
|
||||
else
|
||||
cipher.init(Cipher.DECRYPT_MODE, sk, params);
|
||||
byte[] result;
|
||||
result = cipher.doFinal(input);
|
||||
System.arraycopy(result, 0, output, 0, result.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates DES key from the password.
|
||||
* @param passwdChars a char[] used to create the key.
|
||||
* @return DES key.
|
||||
*
|
||||
* @modified by Yanni Zhang, Dec 6, 99
|
||||
*/
|
||||
public static long char_to_key(char[] passwdChars) throws KrbCryptoException {
|
||||
long key = 0;
|
||||
long octet, octet1, octet2 = 0;
|
||||
byte[] cbytes = null;
|
||||
|
||||
// Convert password to byte array
|
||||
try {
|
||||
if (CHARSET == null) {
|
||||
cbytes = (new String(passwdChars)).getBytes();
|
||||
} else {
|
||||
cbytes = (new String(passwdChars)).getBytes(CHARSET);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// clear-up sensitive information
|
||||
if (cbytes != null) {
|
||||
Arrays.fill(cbytes, 0, cbytes.length, (byte) 0);
|
||||
}
|
||||
KrbCryptoException ce =
|
||||
new KrbCryptoException("Unable to convert passwd, " + e);
|
||||
ce.initCause(e);
|
||||
throw ce;
|
||||
}
|
||||
|
||||
// pad data
|
||||
byte[] passwdBytes = pad(cbytes);
|
||||
|
||||
byte[] newkey = new byte[8];
|
||||
int length = (passwdBytes.length / 8) + (passwdBytes.length % 8 == 0 ? 0 : 1);
|
||||
for (int i = 0; i < length; i++) {
|
||||
octet = octet2long(passwdBytes, i * 8) & 0x7f7f7f7f7f7f7f7fL;
|
||||
if (i % 2 == 1) {
|
||||
octet1 = 0;
|
||||
for (int j = 0; j < 64; j++) {
|
||||
octet1 |= ((octet & (1L << j)) >>> j) << (63 - j);
|
||||
}
|
||||
octet = octet1 >>> 1;
|
||||
}
|
||||
key ^= (octet << 1);
|
||||
}
|
||||
key = set_parity(key);
|
||||
if (bad_key(key)) {
|
||||
byte [] temp = long2octet(key);
|
||||
temp[7] ^= 0xf0;
|
||||
key = octet2long(temp);
|
||||
}
|
||||
|
||||
newkey = des_cksum(long2octet(key), passwdBytes, long2octet(key));
|
||||
key = octet2long(set_parity(newkey));
|
||||
if (bad_key(key)) {
|
||||
byte [] temp = long2octet(key);
|
||||
temp[7] ^= 0xf0;
|
||||
key = octet2long(temp);
|
||||
}
|
||||
|
||||
// clear-up sensitive information
|
||||
if (cbytes != null) {
|
||||
Arrays.fill(cbytes, 0, cbytes.length, (byte) 0);
|
||||
}
|
||||
if (passwdBytes != null) {
|
||||
Arrays.fill(passwdBytes, 0, passwdBytes.length, (byte) 0);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the message blocks using DES CBC and output the
|
||||
* final block of 8-byte ciphertext.
|
||||
* @param ivec Initialization vector.
|
||||
* @param msg Input message as an byte array.
|
||||
* @param key DES key to encrypt the message.
|
||||
* @return the last block of ciphertext.
|
||||
*
|
||||
* @created by Yanni Zhang, Dec 6, 99.
|
||||
*/
|
||||
public static byte[] des_cksum(byte[] ivec, byte[] msg, byte[] key) throws KrbCryptoException {
|
||||
Cipher cipher = null;
|
||||
|
||||
byte[] result = new byte[8];
|
||||
try{
|
||||
cipher = Cipher.getInstance("DES/CBC/NoPadding");
|
||||
} catch (Exception e) {
|
||||
KrbCryptoException ke = new KrbCryptoException("JCE provider may not be installed. "
|
||||
+ e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
IvParameterSpec params = new IvParameterSpec(ivec);
|
||||
SecretKeySpec skSpec = new SecretKeySpec(key, "DES");
|
||||
try {
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
|
||||
// SecretKey sk = skf.generateSecret(skSpec);
|
||||
SecretKey sk = (SecretKey) skSpec;
|
||||
cipher.init(Cipher.ENCRYPT_MODE, sk, params);
|
||||
for (int i = 0; i < msg.length / 8; i++) {
|
||||
result = cipher.doFinal(msg, i * 8, 8);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, sk, (new IvParameterSpec(result)));
|
||||
}
|
||||
}
|
||||
catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads the data so that its length is a multiple of 8 bytes.
|
||||
* @param data the raw data.
|
||||
* @return the data being padded.
|
||||
*
|
||||
* @created by Yanni Zhang, Dec 6 99. //Kerberos does not use PKCS5 padding.
|
||||
*/
|
||||
static byte[] pad(byte[] data) {
|
||||
int len;
|
||||
if (data.length < 8) len = data.length;
|
||||
else len = data.length % 8;
|
||||
if (len == 0) return data;
|
||||
else {
|
||||
byte[] padding = new byte[ 8 - len + data.length];
|
||||
for (int i = padding.length - 1; i > data.length - 1; i--) {
|
||||
padding[i] = 0;
|
||||
}
|
||||
System.arraycopy(data, 0, padding, 0, data.length);
|
||||
return padding;
|
||||
}
|
||||
}
|
||||
|
||||
// Caller is responsible for clearing password
|
||||
public static byte[] string_to_key_bytes(char[] passwdChars)
|
||||
throws KrbCryptoException {
|
||||
return long2octet(char_to_key(passwdChars));
|
||||
}
|
||||
}
|
||||
91
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Des3.java
Normal file
91
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Des3.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.internal.crypto.dk.Des3DkCrypto;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Class with static methods for doing Triple DES operations.
|
||||
*/
|
||||
public class Des3 {
|
||||
private static final Des3DkCrypto CRYPTO = new Des3DkCrypto();
|
||||
|
||||
private Des3() {
|
||||
}
|
||||
|
||||
public static byte[] stringToKey(char[] chars)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.stringToKey(chars);
|
||||
}
|
||||
|
||||
public static byte[] parityFix(byte[] value)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.parityFix(value);
|
||||
}
|
||||
|
||||
// in bytes
|
||||
public static int getChecksumLength() {
|
||||
return CRYPTO.getChecksumLength();
|
||||
}
|
||||
|
||||
public static byte[] calculateChecksum(byte[] baseKey, int usage,
|
||||
byte[] input, int start, int len) throws GeneralSecurityException {
|
||||
return CRYPTO.calculateChecksum(baseKey, usage, input, start, len);
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encrypt(baseKey, usage, ivec, null /* new_ivec */,
|
||||
plaintext, start, len);
|
||||
}
|
||||
|
||||
/* Encrypt plaintext; do not add confounder, padding, or checksum */
|
||||
public static byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
return CRYPTO.encryptRaw(baseKey, usage, ivec, plaintext, start, len);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decrypt(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt ciphertext; do not remove confounder, padding,
|
||||
* or check checksum
|
||||
*/
|
||||
public static byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
return CRYPTO.decryptRaw(baseKey, usage, ivec, ciphertext, start, len);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.Checksum;
|
||||
|
||||
public final class Des3CbcHmacSha1KdEType extends EType {
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return blockSize();
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return Des3.getChecksumLength();
|
||||
}
|
||||
|
||||
public int blockSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES3;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 24; // bytes
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return encrypt(data, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
return Des3.encrypt(key, usage, ivec, data, 0, data.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException{
|
||||
byte[] ivec = new byte[blockSize()];
|
||||
return decrypt(cipher, key, ivec, usage);
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
try {
|
||||
return Des3.decrypt(key, usage, ivec, cipher, 0, cipher.length);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
// Override default, because our decrypted data does not return confounder
|
||||
// Should eventually get rid of EType.decryptedData and
|
||||
// EncryptedData.decryptedData altogether
|
||||
public byte[] decryptedData(byte[] data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
public class DesCbcCrcEType extends DesCbcEType {
|
||||
|
||||
public DesCbcCrcEType() {
|
||||
}
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_DES_CBC_CRC;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts data using DES in CBC mode with CRC32.
|
||||
* @param data the data to be encrypted.
|
||||
* @param key the secret key to encrypt the data. It is also used as initialization vector during cipher block chaining.
|
||||
* @return the buffer for cipher text.
|
||||
*
|
||||
* @written by Yanni Zhang, Dec 10, 1999
|
||||
*/
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
return encrypt(data, key, key, usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts data with provided key using DES in CBC mode with CRC32.
|
||||
* @param cipher the cipher text to be decrypted.
|
||||
* @param key the secret key to decrypt the data.
|
||||
*
|
||||
* @written by Yanni Zhang, Dec 10, 1999
|
||||
*/
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException{
|
||||
return decrypt(cipher, key, key, usage);
|
||||
}
|
||||
|
||||
protected byte[] calculateChecksum(byte[] data, int size) {
|
||||
return crc32.byte2crc32sum_bytes(data, size);
|
||||
}
|
||||
|
||||
}
|
||||
222
jdkSrc/jdk8/sun/security/krb5/internal/crypto/DesCbcEType.java
Normal file
222
jdkSrc/jdk8/sun/security/krb5/internal/crypto/DesCbcEType.java
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
abstract class DesCbcEType extends EType {
|
||||
protected abstract byte[] calculateChecksum(byte[] data, int size)
|
||||
throws KrbCryptoException;
|
||||
|
||||
public int blockSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the data using DES in CBC mode.
|
||||
* @param data the buffer for plain text.
|
||||
* @param key the key to encrypt the data.
|
||||
* @return the buffer for encrypted data.
|
||||
*
|
||||
* @written by Yanni Zhang, Dec 6 99.
|
||||
*/
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException {
|
||||
byte[] ivec = new byte[keySize()];
|
||||
return encrypt(data, key, ivec, usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the data using DES in CBC mode.
|
||||
* @param data the buffer for plain text.
|
||||
* @param key the key to encrypt the data.
|
||||
* @param ivec initialization vector.
|
||||
* @return buffer for encrypted data.
|
||||
*
|
||||
* @modified by Yanni Zhang, Feb 24 00.
|
||||
*/
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
/*
|
||||
* To meet export control requirements, double check that the
|
||||
* key being used is no longer than 64 bits.
|
||||
*
|
||||
* Note that from a protocol point of view, an
|
||||
* algorithm that is not DES will be rejected before this
|
||||
* point. Also, a DES key that is not 64 bits will be
|
||||
* rejected by a good implementations of JCE.
|
||||
*/
|
||||
if (key.length > 8)
|
||||
throw new KrbCryptoException("Invalid DES Key!");
|
||||
|
||||
int new_size = data.length + confounderSize() + checksumSize();
|
||||
byte[] new_data;
|
||||
byte pad;
|
||||
/*Data padding: using Kerberos 5 GSS-API mechanism (1.2.2.3), Jun 1996.
|
||||
*Before encryption, plain text data is padded to the next highest multiple of blocksize.
|
||||
*by appending between 1 and 8 bytes, the value of each such byte being the total number
|
||||
*of pad bytes. For example, if new_size = 10, blockSize is 8, we should pad 2 bytes,
|
||||
*and the value of each byte is 2.
|
||||
*If plaintext data is a multiple of blocksize, we pad a 8 bytes of 8.
|
||||
*/
|
||||
if (new_size % blockSize() == 0) {
|
||||
new_data = new byte[new_size + blockSize()];
|
||||
pad = (byte)8;
|
||||
}
|
||||
else {
|
||||
new_data = new byte[new_size + blockSize() - new_size % blockSize()];
|
||||
pad = (byte)(blockSize() - new_size % blockSize());
|
||||
}
|
||||
for (int i = new_size; i < new_data.length; i++) {
|
||||
new_data[i] = pad;
|
||||
}
|
||||
byte[] conf = Confounder.bytes(confounderSize());
|
||||
System.arraycopy(conf, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, startOfData(), data.length);
|
||||
byte[] cksum = calculateChecksum(new_data, new_data.length);
|
||||
System.arraycopy(cksum, 0, new_data, startOfChecksum(),
|
||||
checksumSize());
|
||||
byte[] cipher = new byte[new_data.length];
|
||||
Des.cbc_encrypt(new_data, cipher, key, ivec, true);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the data using DES in CBC mode.
|
||||
* @param cipher the input buffer.
|
||||
* @param key the key to decrypt the data.
|
||||
*
|
||||
* @written by Yanni Zhang, Dec 6 99.
|
||||
*/
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException{
|
||||
byte[] ivec = new byte[keySize()];
|
||||
return decrypt(cipher, key, ivec, usage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the data using DES in CBC mode.
|
||||
* @param cipher the input buffer.
|
||||
* @param key the key to decrypt the data.
|
||||
* @param ivec initialization vector.
|
||||
*
|
||||
* @modified by Yanni Zhang, Dec 6 99.
|
||||
*/
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException, KrbCryptoException {
|
||||
|
||||
/*
|
||||
* To meet export control requirements, double check that the
|
||||
* key being used is no longer than 64 bits.
|
||||
*
|
||||
* Note that from a protocol point of view, an
|
||||
* algorithm that is not DES will be rejected before this
|
||||
* point. Also, a DES key that is not 64 bits will be
|
||||
* rejected by a good JCE provider.
|
||||
*/
|
||||
if (key.length > 8)
|
||||
throw new KrbCryptoException("Invalid DES Key!");
|
||||
|
||||
byte[] data = new byte[cipher.length];
|
||||
Des.cbc_encrypt(cipher, data, key, ivec, false);
|
||||
if (!isChecksumValid(data))
|
||||
throw new KrbApErrException(Krb5.KRB_AP_ERR_BAD_INTEGRITY);
|
||||
return data;
|
||||
}
|
||||
|
||||
private void copyChecksumField(byte[] data, byte[] cksum) {
|
||||
for (int i = 0; i < checksumSize(); i++)
|
||||
data[startOfChecksum() + i] = cksum[i];
|
||||
}
|
||||
|
||||
private byte[] checksumField(byte[] data) {
|
||||
byte[] result = new byte[checksumSize()];
|
||||
for (int i = 0; i < checksumSize(); i++)
|
||||
result[i] = data[startOfChecksum() + i];
|
||||
return result;
|
||||
}
|
||||
|
||||
private void resetChecksumField(byte[] data) {
|
||||
for (int i = startOfChecksum(); i < startOfChecksum() +
|
||||
checksumSize(); i++)
|
||||
data[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// Not used.
|
||||
public void setChecksum(byte[] data, int size) throws KrbCryptoException{
|
||||
resetChecksumField(data);
|
||||
byte[] cksum = calculateChecksum(data, size);
|
||||
copyChecksumField(data, cksum);
|
||||
}
|
||||
*/
|
||||
|
||||
private byte[] generateChecksum(byte[] data) throws KrbCryptoException{
|
||||
byte[] cksum1 = checksumField(data);
|
||||
resetChecksumField(data);
|
||||
byte[] cksum2 = calculateChecksum(data, data.length);
|
||||
copyChecksumField(data, cksum1);
|
||||
return cksum2;
|
||||
}
|
||||
|
||||
private boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
|
||||
if (cksum1 == cksum2)
|
||||
return true;
|
||||
if ((cksum1 == null && cksum2 != null) ||
|
||||
(cksum1 != null && cksum2 == null))
|
||||
return false;
|
||||
if (cksum1.length != cksum2.length)
|
||||
return false;
|
||||
for (int i = 0; i < cksum1.length; i++)
|
||||
if (cksum1[i] != cksum2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isChecksumValid(byte[] data) throws KrbCryptoException {
|
||||
byte[] cksum1 = checksumField(data);
|
||||
byte[] cksum2 = generateChecksum(data);
|
||||
return isChecksumEqual(cksum1, cksum2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.internal.*;
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
|
||||
public final class DesCbcMd5EType extends DesCbcEType {
|
||||
|
||||
public DesCbcMd5EType() {
|
||||
}
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_DES_CBC_MD5;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates checksum using MD5.
|
||||
* @param data the input data.
|
||||
* @param size the length of data.
|
||||
* @return the checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/06/99.
|
||||
*/
|
||||
protected byte[] calculateChecksum(byte[] data, int size)
|
||||
throws KrbCryptoException {
|
||||
MessageDigest md5 = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
md5.update(data);
|
||||
return(md5.digest());
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
public class DesMacCksumType extends CksumType {
|
||||
|
||||
public DesMacCksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_DES_MAC;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
byte[] conf = Confounder.bytes(confounderSize());
|
||||
System.arraycopy(conf, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(key, 0)) {
|
||||
key[7] = (byte)(key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] residue_ivec = new byte[key.length];
|
||||
byte[] residue = Des.des_cksum(residue_ivec, new_data, key);
|
||||
byte[] cksum = new byte[cksumSize()];
|
||||
System.arraycopy(conf, 0, cksum, 0, confounderSize());
|
||||
System.arraycopy(residue, 0, cksum, confounderSize(),
|
||||
cksumSize() - confounderSize());
|
||||
|
||||
byte[] new_key = new byte[keySize()];
|
||||
System.arraycopy(key, 0, new_key, 0, key.length);
|
||||
for (int i = 0; i < new_key.length; i++)
|
||||
new_key[i] = (byte)(new_key[i] ^ 0xf0);
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(new_key, 0)) {
|
||||
new_key[7] = (byte)(new_key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[new_key.length];
|
||||
|
||||
//des-cbc encrypt
|
||||
byte[] enc_cksum = new byte[cksum.length];
|
||||
Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true);
|
||||
return enc_cksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
byte[] cksum = decryptKeyedChecksum(checksum, key);
|
||||
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
System.arraycopy(cksum, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(key, 0)) {
|
||||
key[7] = (byte)(key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[key.length];
|
||||
byte[] new_cksum = Des.des_cksum(ivec, new_data, key);
|
||||
byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
|
||||
System.arraycopy(cksum, confounderSize(), orig_cksum, 0,
|
||||
cksumSize() - confounderSize());
|
||||
return isChecksumEqual(orig_cksum, new_cksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts keyed checksum.
|
||||
* @param enc_cksum the buffer for encrypted checksum.
|
||||
* @param key the key.
|
||||
* @return the checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException {
|
||||
byte[] new_key = new byte[keySize()];
|
||||
System.arraycopy(key, 0, new_key, 0, key.length);
|
||||
for (int i = 0; i < new_key.length; i++)
|
||||
new_key[i] = (byte)(new_key[i] ^ 0xf0);
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(new_key, 0)) {
|
||||
new_key[7] = (byte)(new_key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[new_key.length];
|
||||
byte[] cksum = new byte[enc_cksum.length];
|
||||
Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false);
|
||||
return cksum;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
public class DesMacKCksumType extends CksumType {
|
||||
|
||||
public DesMacKCksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_DES_MAC_K;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(key, 0)) {
|
||||
key[7] = (byte)(key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[key.length];
|
||||
System.arraycopy(key, 0, ivec, 0, key.length);
|
||||
byte[] cksum = Des.des_cksum(ivec, data, key);
|
||||
return cksum;
|
||||
}
|
||||
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
byte[] new_cksum = calculateChecksum(data, data.length, key, usage);
|
||||
return isChecksumEqual(checksum, new_cksum);
|
||||
}
|
||||
|
||||
}
|
||||
370
jdkSrc/jdk8/sun/security/krb5/internal/crypto/EType.java
Normal file
370
jdkSrc/jdk8/sun/security/krb5/internal/crypto/EType.java
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.internal.*;
|
||||
import sun.security.krb5.Config;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.EncryptionKey;
|
||||
import sun.security.krb5.KrbException;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import javax.crypto.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
//only needed if dataSize() implementation changes back to spec;
|
||||
//see dataSize() below
|
||||
|
||||
public abstract class EType {
|
||||
|
||||
private static final boolean DEBUG = Krb5.DEBUG;
|
||||
private static boolean allowWeakCrypto;
|
||||
|
||||
static {
|
||||
initStatic();
|
||||
}
|
||||
|
||||
public static void initStatic() {
|
||||
boolean allowed = false;
|
||||
try {
|
||||
Config cfg = Config.getInstance();
|
||||
allowed = cfg.getBooleanObject("libdefaults", "allow_weak_crypto")
|
||||
== Boolean.TRUE;
|
||||
} catch (Exception exc) {
|
||||
if (DEBUG) {
|
||||
System.out.println ("Exception in getting allow_weak_crypto, " +
|
||||
"using default value " +
|
||||
exc.getMessage());
|
||||
}
|
||||
}
|
||||
allowWeakCrypto = allowed;
|
||||
}
|
||||
|
||||
public static EType getInstance (int eTypeConst)
|
||||
throws KdcErrException {
|
||||
EType eType = null;
|
||||
String eTypeName = null;
|
||||
switch (eTypeConst) {
|
||||
case EncryptedData.ETYPE_NULL:
|
||||
eType = new NullEType();
|
||||
eTypeName = "sun.security.krb5.internal.crypto.NullEType";
|
||||
break;
|
||||
case EncryptedData.ETYPE_DES_CBC_CRC:
|
||||
eType = new DesCbcCrcEType();
|
||||
eTypeName = "sun.security.krb5.internal.crypto.DesCbcCrcEType";
|
||||
break;
|
||||
case EncryptedData.ETYPE_DES_CBC_MD5:
|
||||
eType = new DesCbcMd5EType();
|
||||
eTypeName = "sun.security.krb5.internal.crypto.DesCbcMd5EType";
|
||||
break;
|
||||
|
||||
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
|
||||
eType = new Des3CbcHmacSha1KdEType();
|
||||
eTypeName =
|
||||
"sun.security.krb5.internal.crypto.Des3CbcHmacSha1KdEType";
|
||||
break;
|
||||
|
||||
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
|
||||
eType = new Aes128CtsHmacSha1EType();
|
||||
eTypeName =
|
||||
"sun.security.krb5.internal.crypto.Aes128CtsHmacSha1EType";
|
||||
break;
|
||||
|
||||
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
|
||||
eType = new Aes256CtsHmacSha1EType();
|
||||
eTypeName =
|
||||
"sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType";
|
||||
break;
|
||||
|
||||
case EncryptedData.ETYPE_ARCFOUR_HMAC:
|
||||
eType = new ArcFourHmacEType();
|
||||
eTypeName = "sun.security.krb5.internal.crypto.ArcFourHmacEType";
|
||||
break;
|
||||
|
||||
default:
|
||||
String msg = "encryption type = " + toString(eTypeConst)
|
||||
+ " (" + eTypeConst + ")";
|
||||
throw new KdcErrException(Krb5.KDC_ERR_ETYPE_NOSUPP, msg);
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.println(">>> EType: " + eTypeName);
|
||||
}
|
||||
return eType;
|
||||
}
|
||||
|
||||
public abstract int eType();
|
||||
|
||||
public abstract int minimumPadSize();
|
||||
|
||||
public abstract int confounderSize();
|
||||
|
||||
public abstract int checksumType();
|
||||
|
||||
public abstract int checksumSize();
|
||||
|
||||
public abstract int blockSize();
|
||||
|
||||
public abstract int keyType();
|
||||
|
||||
public abstract int keySize();
|
||||
|
||||
public abstract byte[] encrypt(byte[] data, byte[] key, int usage)
|
||||
throws KrbCryptoException;
|
||||
|
||||
public abstract byte[] encrypt(byte[] data, byte[] key, byte[] ivec,
|
||||
int usage) throws KrbCryptoException;
|
||||
|
||||
public abstract byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException, KrbCryptoException;
|
||||
|
||||
public abstract byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec,
|
||||
int usage) throws KrbApErrException, KrbCryptoException;
|
||||
|
||||
public int dataSize(byte[] data)
|
||||
// throws Asn1Exception
|
||||
{
|
||||
// EncodeRef ref = new EncodeRef(data, startOfData());
|
||||
// return ref.end - startOfData();
|
||||
// should be the above according to spec, but in fact
|
||||
// implementations include the pad bytes in the data size
|
||||
return data.length - startOfData();
|
||||
}
|
||||
|
||||
public int padSize(byte[] data) {
|
||||
return data.length - confounderSize() - checksumSize() -
|
||||
dataSize(data);
|
||||
}
|
||||
|
||||
public int startOfChecksum() {
|
||||
return confounderSize();
|
||||
}
|
||||
|
||||
public int startOfData() {
|
||||
return confounderSize() + checksumSize();
|
||||
}
|
||||
|
||||
public int startOfPad(byte[] data) {
|
||||
return confounderSize() + checksumSize() + dataSize(data);
|
||||
}
|
||||
|
||||
public byte[] decryptedData(byte[] data) {
|
||||
int tempSize = dataSize(data);
|
||||
byte[] result = new byte[tempSize];
|
||||
System.arraycopy(data, startOfData(), result, 0, tempSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Note: the first 2 entries of BUILTIN_ETYPES and BUILTIN_ETYPES_NOAES256
|
||||
// should be kept DES-related. They will be removed when allow_weak_crypto
|
||||
// is set to false.
|
||||
|
||||
private static final int[] BUILTIN_ETYPES = new int[] {
|
||||
EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96,
|
||||
EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
|
||||
EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
|
||||
EncryptedData.ETYPE_ARCFOUR_HMAC,
|
||||
EncryptedData.ETYPE_DES_CBC_CRC,
|
||||
EncryptedData.ETYPE_DES_CBC_MD5,
|
||||
};
|
||||
|
||||
private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] {
|
||||
EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96,
|
||||
EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD,
|
||||
EncryptedData.ETYPE_ARCFOUR_HMAC,
|
||||
EncryptedData.ETYPE_DES_CBC_CRC,
|
||||
EncryptedData.ETYPE_DES_CBC_MD5,
|
||||
};
|
||||
|
||||
|
||||
// used in Config
|
||||
public static int[] getBuiltInDefaults() {
|
||||
int allowed = 0;
|
||||
try {
|
||||
allowed = Cipher.getMaxAllowedKeyLength("AES");
|
||||
} catch (Exception e) {
|
||||
// should not happen
|
||||
}
|
||||
int[] result;
|
||||
if (allowed < 256) {
|
||||
result = BUILTIN_ETYPES_NOAES256;
|
||||
} else {
|
||||
result = BUILTIN_ETYPES;
|
||||
}
|
||||
if (!allowWeakCrypto) {
|
||||
// The last 4 etypes are now weak ones
|
||||
return Arrays.copyOfRange(result, 0, result.length - 4);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default etypes from the configuration file, or
|
||||
* if that's not available, return the built-in list of default etypes.
|
||||
* This result is always non-empty. If no etypes are found,
|
||||
* an exception is thrown.
|
||||
*/
|
||||
public static int[] getDefaults(String configName)
|
||||
throws KrbException {
|
||||
Config config = null;
|
||||
try {
|
||||
config = Config.getInstance();
|
||||
} catch (KrbException exc) {
|
||||
if (DEBUG) {
|
||||
System.out.println("Exception while getting " +
|
||||
configName + exc.getMessage());
|
||||
System.out.println("Using default builtin etypes");
|
||||
}
|
||||
return getBuiltInDefaults();
|
||||
}
|
||||
return config.defaultEtype(configName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default etypes from the configuration file for
|
||||
* those etypes for which there are corresponding keys.
|
||||
* Used in scenario we have some keys from a keytab with etypes
|
||||
* different from those named in configName. Then, in order
|
||||
* to decrypt an AS-REP, we should only ask for etypes for which
|
||||
* we have keys.
|
||||
*/
|
||||
public static int[] getDefaults(String configName, EncryptionKey[] keys)
|
||||
throws KrbException {
|
||||
int[] answer = getDefaults(configName);
|
||||
|
||||
List<Integer> list = new ArrayList<>(answer.length);
|
||||
for (int i = 0; i < answer.length; i++) {
|
||||
if (EncryptionKey.findKey(answer[i], keys) != null) {
|
||||
list.add(answer[i]);
|
||||
}
|
||||
}
|
||||
int len = list.size();
|
||||
if (len <= 0) {
|
||||
StringBuffer keystr = new StringBuffer();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
keystr.append(toString(keys[i].getEType()));
|
||||
keystr.append(" ");
|
||||
}
|
||||
throw new KrbException(
|
||||
"Do not have keys of types listed in " + configName +
|
||||
" available; only have keys of following type: " +
|
||||
keystr.toString());
|
||||
} else {
|
||||
answer = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
answer[i] = list.get(i);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupported(int eTypeConst, int[] config) {
|
||||
for (int i = 0; i < config.length; i++) {
|
||||
if (eTypeConst == config[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isSupported(int eTypeConst) {
|
||||
int[] enabledETypes = getBuiltInDefaults();
|
||||
return isSupported(eTypeConst, enabledETypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* https://tools.ietf.org/html/rfc4120#section-3.1.3:
|
||||
*
|
||||
* A "newer" enctype is any enctype first officially
|
||||
* specified concurrently with or subsequent to the issue of this RFC.
|
||||
* The enctypes DES, 3DES, or RC4 and any defined in [RFC1510] are not
|
||||
* "newer" enctypes.
|
||||
*
|
||||
* @param eTypeConst the encryption type
|
||||
* @return true if "newer"
|
||||
*/
|
||||
public static boolean isNewer(int eTypeConst) {
|
||||
return eTypeConst != EncryptedData.ETYPE_DES_CBC_CRC &&
|
||||
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD4 &&
|
||||
eTypeConst != EncryptedData.ETYPE_DES_CBC_MD5 &&
|
||||
eTypeConst != EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD &&
|
||||
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC &&
|
||||
eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC_EXP;
|
||||
}
|
||||
|
||||
public static String toString(int type) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return "NULL";
|
||||
case 1:
|
||||
return "DES CBC mode with CRC-32";
|
||||
case 2:
|
||||
return "DES CBC mode with MD4";
|
||||
case 3:
|
||||
return "DES CBC mode with MD5";
|
||||
case 4:
|
||||
return "reserved";
|
||||
case 5:
|
||||
return "DES3 CBC mode with MD5";
|
||||
case 6:
|
||||
return "reserved";
|
||||
case 7:
|
||||
return "DES3 CBC mode with SHA1";
|
||||
case 9:
|
||||
return "DSA with SHA1- Cms0ID";
|
||||
case 10:
|
||||
return "MD5 with RSA encryption - Cms0ID";
|
||||
case 11:
|
||||
return "SHA1 with RSA encryption - Cms0ID";
|
||||
case 12:
|
||||
return "RC2 CBC mode with Env0ID";
|
||||
case 13:
|
||||
return "RSA encryption with Env0ID";
|
||||
case 14:
|
||||
return "RSAES-0AEP-ENV-0ID";
|
||||
case 15:
|
||||
return "DES-EDE3-CBC-ENV-0ID";
|
||||
case 16:
|
||||
return "DES3 CBC mode with SHA1-KD";
|
||||
case 17:
|
||||
return "AES128 CTS mode with HMAC SHA1-96";
|
||||
case 18:
|
||||
return "AES256 CTS mode with HMAC SHA1-96";
|
||||
case 23:
|
||||
return "RC4 with HMAC";
|
||||
case 24:
|
||||
return "RC4 with HMAC EXP";
|
||||
|
||||
}
|
||||
return "Unknown (" + type + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* This class encapsulates the checksum type for HMAC RC4
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class HmacMd5ArcFourCksumType extends CksumType {
|
||||
|
||||
public HmacMd5ArcFourCksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_ARCFOUR_HMAC;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
return ArcFourHmac.calculateChecksum(key, usage, data, 0, size);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
byte[] newCksum = ArcFourHmac.calculateChecksum(key, usage,
|
||||
data, 0, size);
|
||||
|
||||
return isChecksumEqual(checksum, newCksum);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/*
|
||||
* This class encapsulates the checksum type for AES128
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class HmacSha1Aes128CksumType extends CksumType {
|
||||
|
||||
public HmacSha1Aes128CksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 12; // bytes
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_AES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 16; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
return Aes128.calculateChecksum(key, usage, data, 0, size);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
byte[] newCksum = Aes128.calculateChecksum(key, usage,
|
||||
data, 0, size);
|
||||
return isChecksumEqual(checksum, newCksum);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/*
|
||||
* This class encapsulates the checksum type for AES256
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class HmacSha1Aes256CksumType extends CksumType {
|
||||
|
||||
public HmacSha1Aes256CksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 12; // bytes
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_AES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 32; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
return Aes256.calculateChecksum(key, usage, data, 0, size);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
byte[] newCksum = Aes256.calculateChecksum(key, usage, data,
|
||||
0, size);
|
||||
return isChecksumEqual(checksum, newCksum);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
public class HmacSha1Des3KdCksumType extends CksumType {
|
||||
|
||||
public HmacSha1Des3KdCksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 20; // bytes
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES3;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 24; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
return Des3.calculateChecksum(key, usage, data, 0, size);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
|
||||
try {
|
||||
byte[] newCksum = Des3.calculateChecksum(key, usage,
|
||||
data, 0, size);
|
||||
|
||||
return isChecksumEqual(checksum, newCksum);
|
||||
} catch (GeneralSecurityException e) {
|
||||
KrbCryptoException ke = new KrbCryptoException(e.getMessage());
|
||||
ke.initCause(e);
|
||||
throw ke;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
jdkSrc/jdk8/sun/security/krb5/internal/crypto/KeyUsage.java
Normal file
64
jdkSrc/jdk8/sun/security/krb5/internal/crypto/KeyUsage.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
/**
|
||||
* Key usages used for key derivation in Kerberos.
|
||||
*/
|
||||
public class KeyUsage {
|
||||
|
||||
private KeyUsage() {
|
||||
}
|
||||
|
||||
public static final int KU_UNKNOWN = 0; // Cannot be 0
|
||||
|
||||
// Defined in draft-yu-krb-wg-kerberos-extensions-00.txt, Appendix A
|
||||
public static final int KU_PA_ENC_TS = 1; // KrbAsReq
|
||||
public static final int KU_TICKET = 2; // KrbApReq (ticket)
|
||||
public static final int KU_ENC_AS_REP_PART = 3; // KrbAsRep
|
||||
public static final int KU_TGS_REQ_AUTH_DATA_SESSKEY= 4; // KrbTgsReq
|
||||
public static final int KU_TGS_REQ_AUTH_DATA_SUBKEY = 5; // KrbTgsReq
|
||||
public static final int KU_PA_TGS_REQ_CKSUM = 6; // KrbTgsReq
|
||||
public static final int KU_PA_TGS_REQ_AUTHENTICATOR = 7; // KrbApReq
|
||||
public static final int KU_ENC_TGS_REP_PART_SESSKEY = 8; // KrbTgsRep
|
||||
public static final int KU_ENC_TGS_REP_PART_SUBKEY = 9; // KrbTgsRep
|
||||
public static final int KU_AUTHENTICATOR_CKSUM = 10;
|
||||
public static final int KU_AP_REQ_AUTHENTICATOR = 11; // KrbApReq
|
||||
public static final int KU_ENC_AP_REP_PART = 12; // KrbApRep
|
||||
public static final int KU_ENC_KRB_PRIV_PART = 13; // KrbPriv
|
||||
public static final int KU_ENC_KRB_CRED_PART = 14; // KrbCred
|
||||
public static final int KU_KRB_SAFE_CKSUM = 15; // KrbSafe
|
||||
public static final int KU_PA_FOR_USER_ENC_CKSUM = 17; // S4U2user
|
||||
public static final int KU_AD_KDC_ISSUED_CKSUM = 19;
|
||||
public static final int KU_AS_REQ = 56;
|
||||
|
||||
public static final boolean isValid(int usage) {
|
||||
return usage >= 0;
|
||||
}
|
||||
}
|
||||
40
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Nonce.java
Normal file
40
jdkSrc/jdk8/sun/security/krb5/internal/crypto/Nonce.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
public class Nonce {
|
||||
|
||||
public static synchronized int value() {
|
||||
return sun.security.krb5.Confounder.intValue() & 0x7fffffff;
|
||||
}
|
||||
|
||||
}
|
||||
94
jdkSrc/jdk8/sun/security/krb5/internal/crypto/NullEType.java
Normal file
94
jdkSrc/jdk8/sun/security/krb5/internal/crypto/NullEType.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.internal.*;
|
||||
|
||||
public class NullEType extends EType {
|
||||
|
||||
public NullEType() {
|
||||
}
|
||||
|
||||
public int eType() {
|
||||
return EncryptedData.ETYPE_NULL;
|
||||
}
|
||||
|
||||
public int minimumPadSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int checksumType() {
|
||||
return Checksum.CKSUMTYPE_NULL;
|
||||
}
|
||||
|
||||
public int checksumSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int blockSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_NULL;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, int usage) {
|
||||
byte[] cipher = new byte[data.length];
|
||||
System.arraycopy(data, 0, cipher, 0, data.length);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data, byte[] key, byte[] ivec, int usage) {
|
||||
byte[] cipher = new byte[data.length];
|
||||
System.arraycopy(data, 0, cipher, 0, data.length);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, int usage)
|
||||
throws KrbApErrException {
|
||||
return cipher.clone();
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipher, byte[] key, byte[] ivec, int usage)
|
||||
throws KrbApErrException {
|
||||
return cipher.clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public final class RsaMd5CksumType extends CksumType {
|
||||
|
||||
public RsaMd5CksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_NULL;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates checksum using MD5.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @return the checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
|
||||
public byte[] calculateChecksum(byte[] data, int size,
|
||||
byte[] key, int usage) throws KrbCryptoException{
|
||||
MessageDigest md5;
|
||||
byte[] result = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
md5.update(data);
|
||||
result = md5.digest();
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage)
|
||||
throws KrbCryptoException {
|
||||
try {
|
||||
byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
|
||||
return CksumType.isChecksumEqual(calculated, checksum);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import sun.security.krb5.Checksum;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.internal.*;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
public final class RsaMd5DesCksumType extends CksumType {
|
||||
|
||||
public RsaMd5DesCksumType() {
|
||||
}
|
||||
|
||||
public int confounderSize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public int cksumType() {
|
||||
return Checksum.CKSUMTYPE_RSA_MD5_DES;
|
||||
}
|
||||
|
||||
public boolean isKeyed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int cksumSize() {
|
||||
return 24;
|
||||
}
|
||||
|
||||
public int keyType() {
|
||||
return Krb5.KEYTYPE_DES;
|
||||
}
|
||||
|
||||
public int keySize() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates keyed checksum.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @return keyed checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] data, int size, byte[] key,
|
||||
int usage) throws KrbCryptoException {
|
||||
//prepend confounder
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
byte[] conf = Confounder.bytes(confounderSize());
|
||||
System.arraycopy(conf, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
//calculate md5 cksum
|
||||
byte[] mdc_cksum = calculateRawChecksum(new_data, new_data.length);
|
||||
byte[] cksum = new byte[cksumSize()];
|
||||
System.arraycopy(conf, 0, cksum, 0, confounderSize());
|
||||
System.arraycopy(mdc_cksum, 0, cksum, confounderSize(),
|
||||
cksumSize() - confounderSize());
|
||||
|
||||
//compute modified key
|
||||
byte[] new_key = new byte[keySize()];
|
||||
System.arraycopy(key, 0, new_key, 0, key.length);
|
||||
for (int i = 0; i < new_key.length; i++)
|
||||
new_key[i] = (byte)(new_key[i] ^ 0xf0);
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(new_key, 0)) {
|
||||
new_key[7] = (byte)(new_key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[new_key.length];
|
||||
|
||||
//des-cbc encrypt
|
||||
byte[] enc_cksum = new byte[cksum.length];
|
||||
Des.cbc_encrypt(cksum, enc_cksum, new_key, ivec, true);
|
||||
return enc_cksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies keyed checksum.
|
||||
* @param data the data.
|
||||
* @param size the length of data.
|
||||
* @param key the key used to encrypt the checksum.
|
||||
* @param checksum the checksum.
|
||||
* @return true if verification is successful.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
public boolean verifyChecksum(byte[] data, int size,
|
||||
byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
|
||||
//decrypt checksum
|
||||
byte[] cksum = decryptKeyedChecksum(checksum, key);
|
||||
|
||||
//prepend confounder
|
||||
byte[] new_data = new byte[size + confounderSize()];
|
||||
System.arraycopy(cksum, 0, new_data, 0, confounderSize());
|
||||
System.arraycopy(data, 0, new_data, confounderSize(), size);
|
||||
|
||||
byte[] new_cksum = calculateRawChecksum(new_data, new_data.length);
|
||||
//extract original cksum value
|
||||
byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
|
||||
System.arraycopy(cksum, confounderSize(), orig_cksum, 0,
|
||||
cksumSize() - confounderSize());
|
||||
|
||||
return isChecksumEqual(orig_cksum, new_cksum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts keyed checksum.
|
||||
* @param enc_cksum the buffer for encrypted checksum.
|
||||
* @param key the key.
|
||||
* @return the checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
private byte[] decryptKeyedChecksum(byte[] enc_cksum, byte[] key) throws KrbCryptoException {
|
||||
//compute modified key
|
||||
byte[] new_key = new byte[keySize()];
|
||||
System.arraycopy(key, 0, new_key, 0, key.length);
|
||||
for (int i = 0; i < new_key.length; i++)
|
||||
new_key[i] = (byte)(new_key[i] ^ 0xf0);
|
||||
//check for weak keys
|
||||
try {
|
||||
if (DESKeySpec.isWeak(new_key, 0)) {
|
||||
new_key[7] = (byte)(new_key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
byte[] ivec = new byte[new_key.length];
|
||||
|
||||
byte[] cksum = new byte[enc_cksum.length];
|
||||
Des.cbc_encrypt(enc_cksum, cksum, new_key, ivec, false);
|
||||
return cksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates checksum using MD5.
|
||||
* @param data the data used to generate the checksum.
|
||||
* @param size length of the data.
|
||||
* @return the checksum.
|
||||
*
|
||||
* @modified by Yanni Zhang, 12/08/99.
|
||||
*/
|
||||
private byte[] calculateRawChecksum(byte[] data, int size) throws KrbCryptoException{
|
||||
MessageDigest md5;
|
||||
byte[] result = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException("JCE provider may not be installed. " + e.getMessage());
|
||||
}
|
||||
try {
|
||||
md5.update(data);
|
||||
result = md5.digest();
|
||||
} catch (Exception e) {
|
||||
throw new KrbCryptoException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
278
jdkSrc/jdk8/sun/security/krb5/internal/crypto/crc32.java
Normal file
278
jdkSrc/jdk8/sun/security/krb5/internal/crypto/crc32.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
|
||||
* Copyright 1997 The Open Group Research Institute. All rights reserved.
|
||||
*/
|
||||
// crc32.java
|
||||
|
||||
package sun.security.krb5.internal.crypto;
|
||||
|
||||
import java.security.MessageDigestSpi;
|
||||
import java.security.DigestException;
|
||||
|
||||
public final class crc32 extends MessageDigestSpi implements Cloneable {
|
||||
private static final int CRC32_LENGTH = 4; //32-bit
|
||||
private int seed;
|
||||
private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
|
||||
// buffer;
|
||||
// private int bufferIndex, bufferLeft;
|
||||
|
||||
public crc32() {
|
||||
init();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
try {
|
||||
crc32 crc = (crc32)super.clone();
|
||||
crc.init();
|
||||
return crc;
|
||||
}
|
||||
catch (CloneNotSupportedException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the digest length in bytes
|
||||
*/
|
||||
protected int engineGetDigestLength() {
|
||||
return (CRC32_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected byte[] engineDigest() {
|
||||
byte[] result = new byte[CRC32_LENGTH];
|
||||
result = int2quad(seed);
|
||||
//processBuffer(buffer, 0, bufferIndex, result, 0);
|
||||
init();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected int engineDigest(byte[] buf, int offset, int len) throws DigestException {
|
||||
byte[] result = new byte[CRC32_LENGTH];
|
||||
result = int2quad(seed);
|
||||
if (len < CRC32_LENGTH) {
|
||||
throw new DigestException("partial digests not returned");
|
||||
}
|
||||
if (buf.length - offset < CRC32_LENGTH) {
|
||||
throw new DigestException("insufficient space in the output " +
|
||||
"buffer to store the digest");
|
||||
}
|
||||
System.arraycopy(result, 0, buf, offset, CRC32_LENGTH);
|
||||
//processBuffer(buffer, 0, bufferIndex, result, 0);
|
||||
/*if (len < CRC32_LENGTH) {
|
||||
throw new DigestException("partial digests not returned");
|
||||
}
|
||||
if (buf.length - offset < CRC32_LENGTH) {
|
||||
throw new DigestException("insufficient space in the output " +
|
||||
"buffer to store the digest");
|
||||
}
|
||||
System.arraycopy(result, 0, buf, offset, CRC32_LENGTH); */
|
||||
init();
|
||||
return CRC32_LENGTH;
|
||||
}
|
||||
/**
|
||||
* Update adds the passed byte to the digested data.
|
||||
*/
|
||||
protected synchronized void engineUpdate(byte b) {
|
||||
byte[] input = new byte[1];
|
||||
input[0] = b;
|
||||
//engineUpdate(input, 0, 1);
|
||||
engineUpdate(input, seed, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update adds the selected part of an array of bytes to the digest.
|
||||
* This version is more efficient than the byte-at-a-time version;
|
||||
* it avoids data copies and reduces per-byte call overhead.
|
||||
*/
|
||||
protected synchronized void engineUpdate(byte input[], int offset,
|
||||
int len) {
|
||||
processData(input, offset, len);
|
||||
}
|
||||
private static int[] crc32Table = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
protected void engineReset() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the CRC32 information
|
||||
*/
|
||||
public void init() {
|
||||
seed = 0;
|
||||
}
|
||||
|
||||
private void processData(byte[] data, int off, int len) {
|
||||
int result = seed;
|
||||
for (int i = 0; i < len; i++)
|
||||
result = (result >>> 8) ^ crc32Table[(result ^ data[i]) & 0xff];
|
||||
seed = result;
|
||||
}
|
||||
|
||||
public static int int2crc32(int b) {
|
||||
int crc = b;
|
||||
|
||||
for (int i = 8; i > 0; i--) {
|
||||
if ((crc & 1) != 0)
|
||||
crc = (crc >>> 1) ^ 0xedb88320;
|
||||
else
|
||||
crc = crc >>> 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
public static void printcrc32Table() {
|
||||
String temp;
|
||||
String zerofill = "00000000";
|
||||
|
||||
System.out.print("\tpublic static int[] crc32Table = {");
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if ((i % 4) == 0)
|
||||
System.out.print("\n\t\t");
|
||||
temp = Integer.toHexString(int2crc32(i));
|
||||
System.out.print("0x" +
|
||||
zerofill.substring(temp.length()) + temp);
|
||||
if (i != 255)
|
||||
System.out.print(", ");
|
||||
}
|
||||
System.out.println("\n\t};");
|
||||
}
|
||||
|
||||
public static int byte2crc32sum(int seed, byte[] data, int size) {
|
||||
int crc = seed;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
crc = (crc >>> 8) ^ crc32Table[(crc ^ data[i]) & 0xff];
|
||||
return crc;
|
||||
}
|
||||
|
||||
public static int byte2crc32sum(int seed, byte[] data) {
|
||||
return byte2crc32sum(seed, data, data.length);
|
||||
}
|
||||
|
||||
//sum from zero, i.e., no pre- or post-conditioning
|
||||
public static int byte2crc32sum(byte[] data) {
|
||||
return byte2crc32sum(0, data);
|
||||
}
|
||||
|
||||
//CCITT ITU-T 3309 CRC-32 w/ standard pre- and post-conditioning
|
||||
public static int byte2crc32(byte[] data) {
|
||||
return ~byte2crc32sum(0xffffffff, data);
|
||||
}
|
||||
|
||||
public static byte[] byte2crc32sum_bytes(byte[] data) {
|
||||
int temp = byte2crc32sum(data);
|
||||
return int2quad(temp);
|
||||
}
|
||||
|
||||
public static byte[] byte2crc32sum_bytes(byte[] data, int size) {
|
||||
int temp = byte2crc32sum(0, data, size);
|
||||
if (DEBUG) {
|
||||
System.out.println(">>>crc32: " + Integer.toHexString(temp));
|
||||
System.out.println(">>>crc32: " + Integer.toBinaryString(temp));
|
||||
}
|
||||
return int2quad(temp);
|
||||
}
|
||||
|
||||
public static byte[] int2quad(long input) {
|
||||
byte[] output = new byte[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output[i] = (byte)((input >>> (i * 8)) & 0xff);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto.dk;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.crypto.spec.DESedeKeySpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.GeneralSecurityException;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.internal.crypto.KeyUsage;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class provides the implementation of AES Encryption for Kerberos
|
||||
* as defined RFC 3962.
|
||||
* http://www.ietf.org/rfc/rfc3962.txt
|
||||
*
|
||||
* Algorithm profile described in [KCRYPTO]:
|
||||
* +--------------------------------------------------------------------+
|
||||
* | protocol key format 128- or 256-bit string |
|
||||
* | |
|
||||
* | string-to-key function PBKDF2+DK with variable |
|
||||
* | iteration count (see |
|
||||
* | above) |
|
||||
* | |
|
||||
* | default string-to-key parameters 00 00 10 00 |
|
||||
* | |
|
||||
* | key-generation seed length key size |
|
||||
* | |
|
||||
* | random-to-key function identity function |
|
||||
* | |
|
||||
* | hash function, H SHA-1 |
|
||||
* | |
|
||||
* | HMAC output size, h 12 octets (96 bits) |
|
||||
* | |
|
||||
* | message block size, m 1 octet |
|
||||
* | |
|
||||
* | encryption/decryption functions, AES in CBC-CTS mode |
|
||||
* | E and D (cipher block size 16 |
|
||||
* | octets), with next to |
|
||||
* | last block as CBC-style |
|
||||
* | ivec |
|
||||
* +--------------------------------------------------------------------+
|
||||
*
|
||||
* Supports AES128 and AES256
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class AesDkCrypto extends DkCrypto {
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
private static final int BLOCK_SIZE = 16;
|
||||
private static final int DEFAULT_ITERATION_COUNT = 4096;
|
||||
private static final byte[] ZERO_IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
private static final int hashSize = 96/8;
|
||||
private final int keyLength;
|
||||
|
||||
public AesDkCrypto(int length) {
|
||||
keyLength = length;
|
||||
}
|
||||
|
||||
protected int getKeySeedLength() {
|
||||
return keyLength; // bits; AES key material
|
||||
}
|
||||
|
||||
public byte[] stringToKey(char[] password, String salt, byte[] s2kparams)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
byte[] saltUtf8 = null;
|
||||
try {
|
||||
saltUtf8 = salt.getBytes("UTF-8");
|
||||
return stringToKey(password, saltUtf8, s2kparams);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (saltUtf8 != null) {
|
||||
Arrays.fill(saltUtf8, (byte)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] stringToKey(char[] secret, byte[] salt, byte[] params)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
int iter_count = DEFAULT_ITERATION_COUNT;
|
||||
if (params != null) {
|
||||
if (params.length != 4) {
|
||||
throw new RuntimeException("Invalid parameter to stringToKey");
|
||||
}
|
||||
iter_count = readBigEndian(params, 0, 4);
|
||||
}
|
||||
|
||||
byte[] tmpKey = randomToKey(PBKDF2(secret, salt, iter_count,
|
||||
getKeySeedLength()));
|
||||
byte[] result = dk(tmpKey, KERBEROS_CONSTANT);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected byte[] randomToKey(byte[] in) {
|
||||
// simple identity operation
|
||||
return in;
|
||||
}
|
||||
|
||||
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
// IV
|
||||
if (ivec == null) {
|
||||
ivec = ZERO_IV;
|
||||
}
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
|
||||
cipher.init(mode, secretKey, encIv);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
// get an instance of the AES Cipher in CTS mode
|
||||
public int getChecksumLength() {
|
||||
return hashSize; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the truncated HMAC
|
||||
*/
|
||||
protected byte[] getHmac(byte[] key, byte[] msg)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
SecretKey keyKi = new SecretKeySpec(key, "HMAC");
|
||||
Mac m = Mac.getInstance("HmacSHA1");
|
||||
m.init(keyKi);
|
||||
|
||||
// generate hash
|
||||
byte[] hash = m.doFinal(msg);
|
||||
|
||||
// truncate hash
|
||||
byte[] output = new byte[hashSize];
|
||||
System.arraycopy(hash, 0, output, 0, hashSize);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the checksum
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
|
||||
int start, int len) throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
// Derive keys
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
|
||||
constant[4] = (byte) 0x99;
|
||||
|
||||
byte[] Kc = dk(baseKey, constant); // Checksum key
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
traceOutput("input", input, start, Math.min(len, 32));
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
traceOutput("Kc", Kc, 0, Kc.length);
|
||||
}
|
||||
|
||||
try {
|
||||
// Generate checksum
|
||||
// H1 = HMAC(Kc, input)
|
||||
byte[] hmac = getHmac(Kc, input);
|
||||
if (debug) {
|
||||
traceOutput("hmac", hmac, 0, hmac.length);
|
||||
}
|
||||
if (hmac.length == getChecksumLength()) {
|
||||
return hmac;
|
||||
} else if (hmac.length > getChecksumLength()) {
|
||||
byte[] buf = new byte[getChecksumLength()];
|
||||
System.arraycopy(hmac, 0, buf, 0, buf.length);
|
||||
return buf;
|
||||
} else {
|
||||
throw new GeneralSecurityException("checksum size too short: " +
|
||||
hmac.length + "; expecting : " + getChecksumLength());
|
||||
}
|
||||
} finally {
|
||||
Arrays.fill(Kc, 0, Kc.length, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption using derived key; adds confounder.
|
||||
*/
|
||||
public byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
byte[] output = encryptCTS(baseKey, usage, ivec, new_ivec, plaintext,
|
||||
start, len, true);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption using derived key; does not add confounder.
|
||||
*/
|
||||
public byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
byte[] output = encryptCTS(baseKey, usage, ivec, null, plaintext,
|
||||
start, len, false);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param baseKey key from which keys are to be derived using usage
|
||||
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
|
||||
*/
|
||||
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len) throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
|
||||
start, len, true);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts data using specified key and initial vector.
|
||||
* @param baseKey encryption key to use
|
||||
* @param ciphertext encrypted data to be decrypted
|
||||
* @param usage ignored
|
||||
*/
|
||||
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
byte[] output = decryptCTS(baseKey, usage, ivec, ciphertext,
|
||||
start, len, false);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt AES in CBC-CTS mode using derived keys.
|
||||
*/
|
||||
private byte[] encryptCTS(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] new_ivec, byte[] plaintext, int start, int len,
|
||||
boolean confounder_exists)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
byte[] Ke = null;
|
||||
byte[] Ki = null;
|
||||
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
}
|
||||
|
||||
try {
|
||||
// derive Encryption key
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
constant[4] = (byte) 0xaa;
|
||||
Ke = dk(baseKey, constant); // Encryption key
|
||||
|
||||
byte[] toBeEncrypted = null;
|
||||
if (confounder_exists) {
|
||||
byte[] confounder = Confounder.bytes(BLOCK_SIZE);
|
||||
toBeEncrypted = new byte[confounder.length + len];
|
||||
System.arraycopy(confounder, 0, toBeEncrypted,
|
||||
0, confounder.length);
|
||||
System.arraycopy(plaintext, start, toBeEncrypted,
|
||||
confounder.length, len);
|
||||
} else {
|
||||
toBeEncrypted = new byte[len];
|
||||
System.arraycopy(plaintext, start, toBeEncrypted, 0, len);
|
||||
}
|
||||
|
||||
// encryptedData + HMAC
|
||||
byte[] output = new byte[toBeEncrypted.length + hashSize];
|
||||
|
||||
// AES in JCE
|
||||
Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
|
||||
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, encIv);
|
||||
cipher.doFinal(toBeEncrypted, 0, toBeEncrypted.length, output);
|
||||
|
||||
// Derive integrity key
|
||||
constant[4] = (byte) 0x55;
|
||||
Ki = dk(baseKey, constant);
|
||||
if (debug) {
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("Ki", Ki, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Generate checksum
|
||||
// H1 = HMAC(Ki, conf | plaintext | pad)
|
||||
byte[] hmac = getHmac(Ki, toBeEncrypted);
|
||||
|
||||
// encryptedData + HMAC
|
||||
System.arraycopy(hmac, 0, output, toBeEncrypted.length,
|
||||
hmac.length);
|
||||
return output;
|
||||
} finally {
|
||||
if (Ke != null) {
|
||||
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
|
||||
}
|
||||
if (Ki != null) {
|
||||
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt AES in CBC-CTS mode using derived keys.
|
||||
*/
|
||||
private byte[] decryptCTS(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len, boolean confounder_exists)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
byte[] Ke = null;
|
||||
byte[] Ki = null;
|
||||
|
||||
try {
|
||||
// Derive encryption key
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
|
||||
constant[4] = (byte) 0xaa;
|
||||
Ke = dk(baseKey, constant); // Encryption key
|
||||
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
traceOutput("Ke", Ke, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Decrypt [confounder | plaintext ] (without checksum)
|
||||
|
||||
// AES in JCE
|
||||
Cipher cipher = Cipher.getInstance("AES/CTS/NoPadding");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(Ke, "AES");
|
||||
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, encIv);
|
||||
byte[] plaintext = cipher.doFinal(ciphertext, start, len-hashSize);
|
||||
|
||||
if (debug) {
|
||||
traceOutput("AES PlainText", plaintext, 0,
|
||||
Math.min(plaintext.length, 32));
|
||||
}
|
||||
|
||||
// Derive integrity key
|
||||
constant[4] = (byte) 0x55;
|
||||
Ki = dk(baseKey, constant); // Integrity key
|
||||
if (debug) {
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("Ki", Ki, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Verify checksum
|
||||
// H1 = HMAC(Ki, conf | plaintext | pad)
|
||||
byte[] calculatedHmac = getHmac(Ki, plaintext);
|
||||
int hmacOffset = start + len - hashSize;
|
||||
if (debug) {
|
||||
traceOutput("calculated Hmac", calculatedHmac,
|
||||
0, calculatedHmac.length);
|
||||
traceOutput("message Hmac", ciphertext, hmacOffset, hashSize);
|
||||
}
|
||||
boolean cksumFailed = false;
|
||||
if (calculatedHmac.length >= hashSize) {
|
||||
for (int i = 0; i < hashSize; i++) {
|
||||
if (calculatedHmac[i] != ciphertext[hmacOffset+i]) {
|
||||
cksumFailed = true;
|
||||
if (debug) {
|
||||
System.err.println("Checksum failed !");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cksumFailed) {
|
||||
throw new GeneralSecurityException("Checksum failed");
|
||||
}
|
||||
|
||||
if (confounder_exists) {
|
||||
// Get rid of confounder
|
||||
// [ confounder | plaintext ]
|
||||
byte[] output = new byte[plaintext.length - BLOCK_SIZE];
|
||||
System.arraycopy(plaintext, BLOCK_SIZE, output,
|
||||
0, output.length);
|
||||
return output;
|
||||
} else {
|
||||
return plaintext;
|
||||
}
|
||||
} finally {
|
||||
if (Ke != null) {
|
||||
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
|
||||
}
|
||||
if (Ki != null) {
|
||||
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke the PKCS#5 PBKDF2 algorithm
|
||||
*/
|
||||
private static byte[] PBKDF2(char[] secret, byte[] salt,
|
||||
int count, int keyLength) throws GeneralSecurityException {
|
||||
|
||||
PBEKeySpec keySpec = new PBEKeySpec(secret, salt, count, keyLength);
|
||||
SecretKeyFactory skf =
|
||||
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
SecretKey key = skf.generateSecret(keySpec);
|
||||
byte[] result = key.getEncoded();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int readBigEndian(byte[] data, int pos, int size) {
|
||||
int retVal = 0;
|
||||
int shifter = (size-1)*8;
|
||||
while (size > 0) {
|
||||
retVal += (data[pos] & 0xff) << shifter;
|
||||
shifter -= 8;
|
||||
pos++;
|
||||
size--;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto.dk;
|
||||
|
||||
import java.security.*;
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
import java.util.*;
|
||||
import sun.security.krb5.EncryptedData;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.internal.crypto.KeyUsage;
|
||||
|
||||
/**
|
||||
* Support for ArcFour in Kerberos
|
||||
* as defined in RFC 4757.
|
||||
* http://www.ietf.org/rfc/rfc4757.txt
|
||||
*
|
||||
* @author Seema Malkani
|
||||
*/
|
||||
|
||||
public class ArcFourCrypto extends DkCrypto {
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
private static final int confounderSize = 8;
|
||||
private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
private static final int hashSize = 16;
|
||||
private final int keyLength;
|
||||
|
||||
public ArcFourCrypto(int length) {
|
||||
keyLength = length;
|
||||
}
|
||||
|
||||
protected int getKeySeedLength() {
|
||||
return keyLength; // bits; RC4 key material
|
||||
}
|
||||
|
||||
protected byte[] randomToKey(byte[] in) {
|
||||
// simple identity operation
|
||||
return in;
|
||||
}
|
||||
|
||||
public byte[] stringToKey(char[] passwd)
|
||||
throws GeneralSecurityException {
|
||||
return stringToKey(passwd, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* String2Key(Password)
|
||||
* K = MD4(UNICODE(password))
|
||||
*/
|
||||
private byte[] stringToKey(char[] secret, byte[] opaque)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (opaque != null && opaque.length > 0) {
|
||||
throw new RuntimeException("Invalid parameter to stringToKey");
|
||||
}
|
||||
|
||||
byte[] passwd = null;
|
||||
byte[] digest = null;
|
||||
try {
|
||||
// convert ascii to unicode
|
||||
passwd = charToUtf16(secret);
|
||||
|
||||
// provider for MD4
|
||||
MessageDigest md = sun.security.provider.MD4.getInstance();
|
||||
md.update(passwd);
|
||||
digest = md.digest();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (passwd != null) {
|
||||
Arrays.fill(passwd, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
return digest;
|
||||
}
|
||||
|
||||
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
// IV
|
||||
if (ivec == null) {
|
||||
ivec = ZERO_IV;
|
||||
}
|
||||
SecretKeySpec secretKey = new SecretKeySpec(key, "ARCFOUR");
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
|
||||
cipher.init(mode, secretKey, encIv);
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public int getChecksumLength() {
|
||||
return hashSize; // bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HMAC-MD5
|
||||
*/
|
||||
protected byte[] getHmac(byte[] key, byte[] msg)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
SecretKey keyKi = new SecretKeySpec(key, "HmacMD5");
|
||||
Mac m = Mac.getInstance("HmacMD5");
|
||||
m.init(keyKi);
|
||||
|
||||
// generate hash
|
||||
byte[] hash = m.doFinal(msg);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the checksum
|
||||
*/
|
||||
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
|
||||
int start, int len) throws GeneralSecurityException {
|
||||
|
||||
if (debug) {
|
||||
System.out.println("ARCFOUR: calculateChecksum with usage = " +
|
||||
usage);
|
||||
}
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
byte[] Ksign = null;
|
||||
// Derive signing key from session key
|
||||
try {
|
||||
byte[] ss = "signaturekey".getBytes();
|
||||
// need to append end-of-string 00
|
||||
byte[] new_ss = new byte[ss.length+1];
|
||||
System.arraycopy(ss, 0, new_ss, 0, ss.length);
|
||||
Ksign = getHmac(baseKey, new_ss);
|
||||
} catch (Exception e) {
|
||||
GeneralSecurityException gse =
|
||||
new GeneralSecurityException("Calculate Checkum Failed!");
|
||||
gse.initCause(e);
|
||||
throw gse;
|
||||
}
|
||||
|
||||
// get the salt using key usage
|
||||
byte[] salt = getSalt(usage);
|
||||
|
||||
// Generate checksum of message
|
||||
MessageDigest messageDigest = null;
|
||||
try {
|
||||
messageDigest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
GeneralSecurityException gse =
|
||||
new GeneralSecurityException("Calculate Checkum Failed!");
|
||||
gse.initCause(e);
|
||||
throw gse;
|
||||
}
|
||||
messageDigest.update(salt);
|
||||
messageDigest.update(input, start, len);
|
||||
byte[] md5tmp = messageDigest.digest();
|
||||
|
||||
// Generate checksum
|
||||
byte[] hmac = getHmac(Ksign, md5tmp);
|
||||
if (debug) {
|
||||
traceOutput("hmac", hmac, 0, hmac.length);
|
||||
}
|
||||
if (hmac.length == getChecksumLength()) {
|
||||
return hmac;
|
||||
} else if (hmac.length > getChecksumLength()) {
|
||||
byte[] buf = new byte[getChecksumLength()];
|
||||
System.arraycopy(hmac, 0, buf, 0, buf.length);
|
||||
return buf;
|
||||
} else {
|
||||
throw new GeneralSecurityException("checksum size too short: " +
|
||||
hmac.length + "; expecting : " + getChecksumLength());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption of Sequence Number using derived key.
|
||||
*/
|
||||
public byte[] encryptSeq(byte[] baseKey, int usage,
|
||||
byte[] checksum, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
// derive encryption for sequence number
|
||||
byte[] salt = new byte[4];
|
||||
byte[] kSeq = getHmac(baseKey, salt);
|
||||
|
||||
// derive new encryption key salted with sequence number
|
||||
kSeq = getHmac(kSeq, checksum);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(kSeq, "ARCFOUR");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] output = cipher.doFinal(plaintext, start, len);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs decryption of Sequence Number using derived key.
|
||||
*/
|
||||
public byte[] decryptSeq(byte[] baseKey, int usage,
|
||||
byte[] checksum, byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
// derive decryption for sequence number
|
||||
byte[] salt = new byte[4];
|
||||
byte[] kSeq = getHmac(baseKey, salt);
|
||||
|
||||
// derive new encryption key salted with sequence number
|
||||
kSeq = getHmac(kSeq, checksum);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(kSeq, "ARCFOUR");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
byte[] output = cipher.doFinal(ciphertext, start, len);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption using derived key; adds confounder.
|
||||
*/
|
||||
public byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
System.out.println("ArcFour: ENCRYPT with key usage = " + usage);
|
||||
}
|
||||
|
||||
// get the confounder
|
||||
byte[] confounder = Confounder.bytes(confounderSize);
|
||||
|
||||
// add confounder to the plaintext for encryption
|
||||
int plainSize = roundup(confounder.length + len, 1);
|
||||
byte[] toBeEncrypted = new byte[plainSize];
|
||||
System.arraycopy(confounder, 0, toBeEncrypted, 0, confounder.length);
|
||||
System.arraycopy(plaintext, start, toBeEncrypted,
|
||||
confounder.length, len);
|
||||
|
||||
/* begin the encryption, compute K1 */
|
||||
byte[] k1 = new byte[baseKey.length];
|
||||
System.arraycopy(baseKey, 0, k1, 0, baseKey.length);
|
||||
|
||||
// get the salt using key usage
|
||||
byte[] salt = getSalt(usage);
|
||||
|
||||
// compute K2 using K1
|
||||
byte[] k2 = getHmac(k1, salt);
|
||||
|
||||
// generate checksum using K2
|
||||
byte[] checksum = getHmac(k2, toBeEncrypted);
|
||||
|
||||
// compute K3 using K2 and checksum
|
||||
byte[] k3 = getHmac(k2, checksum);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(k3, "ARCFOUR");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] output = cipher.doFinal(toBeEncrypted, 0, toBeEncrypted.length);
|
||||
|
||||
// encryptedData + HMAC
|
||||
byte[] result = new byte[hashSize + output.length];
|
||||
System.arraycopy(checksum, 0, result, 0, hashSize);
|
||||
System.arraycopy(output, 0, result, hashSize, output.length);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption using derived key; does not add confounder.
|
||||
*/
|
||||
public byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] seqNum, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
System.out.println("\nARCFOUR: encryptRaw with usage = " + usage);
|
||||
}
|
||||
|
||||
// Derive encryption key for data
|
||||
// Key derivation salt = 0
|
||||
byte[] klocal = new byte[baseKey.length];
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
klocal[i] = (byte) (baseKey[i] ^ 0xF0);
|
||||
}
|
||||
byte[] salt = new byte[4];
|
||||
byte[] kcrypt = getHmac(klocal, salt);
|
||||
|
||||
// Note: When using this RC4 based encryption type, the sequence number
|
||||
// is always sent in big-endian rather than little-endian order.
|
||||
|
||||
// new encryption key salted with sequence number
|
||||
kcrypt = getHmac(kcrypt, seqNum);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(kcrypt, "ARCFOUR");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||
byte[] output = cipher.doFinal(plaintext, start, len);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param baseKey key from which keys are to be derived using usage
|
||||
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
|
||||
*/
|
||||
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
if (debug) {
|
||||
System.out.println("\nARCFOUR: DECRYPT using key usage = " + usage);
|
||||
}
|
||||
|
||||
// compute K1
|
||||
byte[] k1 = new byte[baseKey.length];
|
||||
System.arraycopy(baseKey, 0, k1, 0, baseKey.length);
|
||||
|
||||
// get the salt using key usage
|
||||
byte[] salt = getSalt(usage);
|
||||
|
||||
// compute K2 using K1
|
||||
byte[] k2 = getHmac(k1, salt);
|
||||
|
||||
// compute K3 using K2 and checksum
|
||||
byte[] checksum = new byte[hashSize];
|
||||
System.arraycopy(ciphertext, start, checksum, 0, hashSize);
|
||||
byte[] k3 = getHmac(k2, checksum);
|
||||
|
||||
// Decrypt [confounder | plaintext ] (without checksum)
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(k3, "ARCFOUR");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
byte[] plaintext = cipher.doFinal(ciphertext, start+hashSize,
|
||||
len-hashSize);
|
||||
|
||||
// Verify checksum
|
||||
byte[] calculatedHmac = getHmac(k2, plaintext);
|
||||
if (debug) {
|
||||
traceOutput("calculated Hmac", calculatedHmac, 0,
|
||||
calculatedHmac.length);
|
||||
traceOutput("message Hmac", ciphertext, 0,
|
||||
hashSize);
|
||||
}
|
||||
boolean cksumFailed = false;
|
||||
if (calculatedHmac.length >= hashSize) {
|
||||
for (int i = 0; i < hashSize; i++) {
|
||||
if (calculatedHmac[i] != ciphertext[i]) {
|
||||
cksumFailed = true;
|
||||
if (debug) {
|
||||
System.err.println("Checksum failed !");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cksumFailed) {
|
||||
throw new GeneralSecurityException("Checksum failed");
|
||||
}
|
||||
|
||||
// Get rid of confounder
|
||||
// [ confounder | plaintext ]
|
||||
byte[] output = new byte[plaintext.length - confounderSize];
|
||||
System.arraycopy(plaintext, confounderSize, output, 0, output.length);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts data using specified key and initial vector.
|
||||
* @param baseKey encryption key to use
|
||||
* @param ciphertext encrypted data to be decrypted
|
||||
* @param usage ignored
|
||||
*/
|
||||
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len, byte[] seqNum)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
if (debug) {
|
||||
System.out.println("\nARCFOUR: decryptRaw with usage = " + usage);
|
||||
}
|
||||
|
||||
// Derive encryption key for data
|
||||
// Key derivation salt = 0
|
||||
byte[] klocal = new byte[baseKey.length];
|
||||
for (int i = 0; i <= 15; i++) {
|
||||
klocal[i] = (byte) (baseKey[i] ^ 0xF0);
|
||||
}
|
||||
byte[] salt = new byte[4];
|
||||
byte[] kcrypt = getHmac(klocal, salt);
|
||||
|
||||
// need only first 4 bytes of sequence number
|
||||
byte[] sequenceNum = new byte[4];
|
||||
System.arraycopy(seqNum, 0, sequenceNum, 0, sequenceNum.length);
|
||||
|
||||
// new encryption key salted with sequence number
|
||||
kcrypt = getHmac(kcrypt, sequenceNum);
|
||||
|
||||
Cipher cipher = Cipher.getInstance("ARCFOUR");
|
||||
SecretKeySpec secretKey = new SecretKeySpec(kcrypt, "ARCFOUR");
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||||
byte[] output = cipher.doFinal(ciphertext, start, len);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// get the salt using key usage
|
||||
private byte[] getSalt(int usage) {
|
||||
int ms_usage = arcfour_translate_usage(usage);
|
||||
byte[] salt = new byte[4];
|
||||
salt[0] = (byte)(ms_usage & 0xff);
|
||||
salt[1] = (byte)((ms_usage >> 8) & 0xff);
|
||||
salt[2] = (byte)((ms_usage >> 16) & 0xff);
|
||||
salt[3] = (byte)((ms_usage >> 24) & 0xff);
|
||||
return salt;
|
||||
}
|
||||
|
||||
// Key usage translation for MS
|
||||
private int arcfour_translate_usage(int usage) {
|
||||
switch (usage) {
|
||||
case 3: return 8;
|
||||
case 9: return 8;
|
||||
case 23: return 13;
|
||||
default: return usage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto.dk;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import javax.crypto.spec.DESedeKeySpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Des3DkCrypto extends DkCrypto {
|
||||
|
||||
private static final byte[] ZERO_IV = new byte[] {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
public Des3DkCrypto() {
|
||||
}
|
||||
|
||||
protected int getKeySeedLength() {
|
||||
return 168; // bits; 3DES key material has 21 bytes
|
||||
}
|
||||
|
||||
public byte[] stringToKey(char[] salt) throws GeneralSecurityException {
|
||||
byte[] saltUtf8 = null;
|
||||
try {
|
||||
saltUtf8 = charToUtf8(salt);
|
||||
return stringToKey(saltUtf8, null);
|
||||
} finally {
|
||||
if (saltUtf8 != null) {
|
||||
Arrays.fill(saltUtf8, (byte)0);
|
||||
}
|
||||
// Caller responsible for clearing its own salt
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] stringToKey(byte[] secretAndSalt, byte[] opaque)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (opaque != null && opaque.length > 0) {
|
||||
throw new RuntimeException("Invalid parameter to stringToKey");
|
||||
}
|
||||
|
||||
byte[] tmpKey = randomToKey(nfold(secretAndSalt, getKeySeedLength()));
|
||||
return dk(tmpKey, KERBEROS_CONSTANT);
|
||||
}
|
||||
|
||||
public byte[] parityFix(byte[] value)
|
||||
throws GeneralSecurityException {
|
||||
// fix key parity
|
||||
setParityBit(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* From RFC 3961.
|
||||
*
|
||||
* The 168 bits of random key data are converted to a protocol key value
|
||||
* as follows. First, the 168 bits are divided into three groups of 56
|
||||
* bits, which are expanded individually into 64 bits as in des3Expand().
|
||||
* Result is a 24 byte (192-bit) key.
|
||||
*/
|
||||
protected byte[] randomToKey(byte[] in) {
|
||||
if (in.length != 21) {
|
||||
throw new IllegalArgumentException("input must be 168 bits");
|
||||
}
|
||||
|
||||
byte[] one = keyCorrection(des3Expand(in, 0, 7));
|
||||
byte[] two = keyCorrection(des3Expand(in, 7, 14));
|
||||
byte[] three = keyCorrection(des3Expand(in, 14, 21));
|
||||
|
||||
byte[] key = new byte[24];
|
||||
System.arraycopy(one, 0, key, 0, 8);
|
||||
System.arraycopy(two, 0, key, 8, 8);
|
||||
System.arraycopy(three, 0, key, 16, 8);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private static byte[] keyCorrection(byte[] key) {
|
||||
// check for weak key
|
||||
try {
|
||||
if (DESKeySpec.isWeak(key, 0)) {
|
||||
key[7] = (byte)(key[7] ^ 0xF0);
|
||||
}
|
||||
} catch (InvalidKeyException ex) {
|
||||
// swallow, since it should never happen
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* From RFC 3961.
|
||||
*
|
||||
* Expands a 7-byte array into an 8-byte array that contains parity bits.
|
||||
* The 56 bits are expanded into 64 bits as follows:
|
||||
* 1 2 3 4 5 6 7 p
|
||||
* 9 10 11 12 13 14 15 p
|
||||
* 17 18 19 20 21 22 23 p
|
||||
* 25 26 27 28 29 30 31 p
|
||||
* 33 34 35 36 37 38 39 p
|
||||
* 41 42 43 44 45 46 47 p
|
||||
* 49 50 51 52 53 54 55 p
|
||||
* 56 48 40 32 24 16 8 p
|
||||
*
|
||||
* (PI,P2,...,P8) are reserved for parity bits computed on the preceding
|
||||
* seven independent bits and set so that the parity of the octet is odd,
|
||||
* i.e., there is an odd number of "1" bits in the octet.
|
||||
*
|
||||
* @param start index of starting byte (inclusive)
|
||||
* @param end index of ending byte (exclusive)
|
||||
*/
|
||||
private static byte[] des3Expand(byte[] input, int start, int end) {
|
||||
if ((end - start) != 7)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid length of DES Key Value:" + start + "," + end);
|
||||
|
||||
byte[] result = new byte[8];
|
||||
byte last = 0;
|
||||
System.arraycopy(input, start, result, 0, 7);
|
||||
byte posn = 0;
|
||||
|
||||
// Fill in last row
|
||||
for (int i = start; i < end; i++) {
|
||||
byte bit = (byte) (input[i]&0x01);
|
||||
if (debug) {
|
||||
System.out.println(i + ": " + Integer.toHexString(input[i]) +
|
||||
" bit= " + Integer.toHexString(bit));
|
||||
}
|
||||
++posn;
|
||||
if (bit != 0) {
|
||||
last |= (bit<<posn);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
System.out.println("last: " + Integer.toHexString(last));
|
||||
}
|
||||
result[7] = last;
|
||||
setParityBit(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parity bit (0th bit) in each byte so that each byte
|
||||
* contains an odd number of 1's.
|
||||
*/
|
||||
private static void setParityBit(byte[] key) {
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
int b = key[i] & 0xfe;
|
||||
b |= (Integer.bitCount(b) & 1) ^ 1;
|
||||
key[i] = (byte) b;
|
||||
}
|
||||
}
|
||||
|
||||
protected Cipher getCipher(byte[] key, byte[] ivec, int mode)
|
||||
throws GeneralSecurityException {
|
||||
// NoSuchAlgorithException
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("desede");
|
||||
|
||||
// InvalidKeyException
|
||||
KeySpec spec = new DESedeKeySpec(key, 0);
|
||||
|
||||
// InvalidKeySpecException
|
||||
SecretKey secretKey = factory.generateSecret(spec);
|
||||
|
||||
// IV
|
||||
if (ivec == null) {
|
||||
ivec = ZERO_IV;
|
||||
}
|
||||
|
||||
// NoSuchAlgorithmException, NoSuchPaddingException
|
||||
// NoSuchProviderException
|
||||
Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
|
||||
IvParameterSpec encIv = new IvParameterSpec(ivec, 0, ivec.length);
|
||||
|
||||
// InvalidKeyException, InvalidAlgorithParameterException
|
||||
cipher.init(mode, secretKey, encIv);
|
||||
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public int getChecksumLength() {
|
||||
return 20; // bytes
|
||||
}
|
||||
|
||||
protected byte[] getHmac(byte[] key, byte[] msg)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
SecretKey keyKi = new SecretKeySpec(key, "HmacSHA1");
|
||||
Mac m = Mac.getInstance("HmacSHA1");
|
||||
m.init(keyKi);
|
||||
return m.doFinal(msg);
|
||||
}
|
||||
}
|
||||
699
jdkSrc/jdk8/sun/security/krb5/internal/crypto/dk/DkCrypto.java
Normal file
699
jdkSrc/jdk8/sun/security/krb5/internal/crypto/dk/DkCrypto.java
Normal file
@@ -0,0 +1,699 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 by the FundsXpress, INC.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Export of this software from the United States of America may require
|
||||
* a specific license from the United States Government. It is the
|
||||
* responsibility of any person or organization contemplating export to
|
||||
* obtain such a license before exporting.
|
||||
*
|
||||
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
||||
* distribute this software and its documentation for any purpose and
|
||||
* without fee is hereby granted, provided that the above copyright
|
||||
* notice appear in all copies and that both that copyright notice and
|
||||
* this permission notice appear in supporting documentation, and that
|
||||
* the name of FundsXpress. not be used in advertising or publicity pertaining
|
||||
* to distribution of the software without specific, written prior
|
||||
* permission. FundsXpress makes no representations about the suitability of
|
||||
* this software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
package sun.security.krb5.internal.crypto.dk;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import sun.misc.HexDumpEncoder;
|
||||
import sun.security.krb5.Confounder;
|
||||
import sun.security.krb5.internal.crypto.KeyUsage;
|
||||
import sun.security.krb5.KrbCryptoException;
|
||||
|
||||
/**
|
||||
* Implements Derive Key cryptography functionality as defined in RFC 3961.
|
||||
* http://www.ietf.org/rfc/rfc3961.txt
|
||||
*
|
||||
* This is an abstract class. Concrete subclasses need to implement
|
||||
* the abstract methods.
|
||||
*/
|
||||
|
||||
public abstract class DkCrypto {
|
||||
|
||||
protected static final boolean debug = false;
|
||||
|
||||
// These values correspond to the ASCII encoding for the string "kerberos"
|
||||
static final byte[] KERBEROS_CONSTANT =
|
||||
{0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73};
|
||||
|
||||
protected abstract int getKeySeedLength(); // in bits
|
||||
|
||||
protected abstract byte[] randomToKey(byte[] in);
|
||||
|
||||
protected abstract Cipher getCipher(byte[] key, byte[] ivec, int mode)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
public abstract int getChecksumLength(); // in bytes
|
||||
|
||||
protected abstract byte[] getHmac(byte[] key, byte[] plaintext)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* From RFC 3961.
|
||||
*
|
||||
* encryption function conf = random string of length c
|
||||
* pad = shortest string to bring confounder
|
||||
* and plaintext to a length that's a
|
||||
* multiple of m
|
||||
* (C1, newIV) = E(Ke, conf | plaintext | pad,
|
||||
* oldstate.ivec)
|
||||
* H1 = HMAC(Ki, conf | plaintext | pad)
|
||||
* ciphertext = C1 | H1[1..h]
|
||||
* newstate.ivec = newIV
|
||||
*
|
||||
* @param ivec initial vector to use when initializing the cipher; if null,
|
||||
* then blocksize number of zeros are used,
|
||||
* @param new_ivec if non-null, it is updated upon return to be the
|
||||
* new ivec to use when calling encrypt next time
|
||||
*/
|
||||
public byte[] encrypt(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
byte[] Ke = null;
|
||||
byte[] Ki = null;
|
||||
|
||||
try {
|
||||
// Derive encryption key
|
||||
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
|
||||
constant[4] = (byte) 0xaa;
|
||||
|
||||
Ke = dk(baseKey, constant);
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
traceOutput("Ke", Ke, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Encrypt
|
||||
// C1 = E(Ke, conf | plaintext | pad, oldivec)
|
||||
Cipher encCipher = getCipher(Ke, ivec, Cipher.ENCRYPT_MODE);
|
||||
int blockSize = encCipher.getBlockSize();
|
||||
byte[] confounder = Confounder.bytes(blockSize);
|
||||
|
||||
int plainSize = roundup(confounder.length + len, blockSize);
|
||||
if (debug) {
|
||||
System.err.println("confounder = " + confounder.length +
|
||||
"; plaintext = " + len + "; padding = " +
|
||||
(plainSize - confounder.length - len) + "; total = " +
|
||||
plainSize);
|
||||
traceOutput("confounder", confounder, 0, confounder.length);
|
||||
}
|
||||
|
||||
byte[] toBeEncrypted = new byte[plainSize];
|
||||
System.arraycopy(confounder, 0, toBeEncrypted,
|
||||
0, confounder.length);
|
||||
System.arraycopy(plaintext, start, toBeEncrypted,
|
||||
confounder.length, len);
|
||||
|
||||
// Set padding bytes to zero
|
||||
Arrays.fill(toBeEncrypted, confounder.length + len, plainSize,
|
||||
(byte)0);
|
||||
|
||||
int cipherSize = encCipher.getOutputSize(plainSize);
|
||||
int ccSize = cipherSize + getChecksumLength(); // cipher | hmac
|
||||
|
||||
byte[] ciphertext = new byte[ccSize];
|
||||
|
||||
encCipher.doFinal(toBeEncrypted, 0, plainSize, ciphertext, 0);
|
||||
|
||||
// Update ivec for next operation
|
||||
// (last blockSize bytes of ciphertext)
|
||||
// newstate.ivec = newIV
|
||||
if (new_ivec != null && new_ivec.length == blockSize) {
|
||||
System.arraycopy(ciphertext, cipherSize - blockSize,
|
||||
new_ivec, 0, blockSize);
|
||||
if (debug) {
|
||||
traceOutput("new_ivec", new_ivec, 0, new_ivec.length);
|
||||
}
|
||||
}
|
||||
|
||||
// Derive integrity key
|
||||
constant[4] = (byte) 0x55;
|
||||
Ki = dk(baseKey, constant);
|
||||
if (debug) {
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("Ki", Ki, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Generate checksum
|
||||
// H1 = HMAC(Ki, conf | plaintext | pad)
|
||||
byte[] hmac = getHmac(Ki, toBeEncrypted);
|
||||
|
||||
if (debug) {
|
||||
traceOutput("hmac", hmac, 0, hmac.length);
|
||||
traceOutput("ciphertext", ciphertext, 0,
|
||||
Math.min(ciphertext.length, 32));
|
||||
}
|
||||
|
||||
// C1 | H1[1..h]
|
||||
System.arraycopy(hmac, 0, ciphertext, cipherSize,
|
||||
getChecksumLength());
|
||||
return ciphertext;
|
||||
} finally {
|
||||
if (Ke != null) {
|
||||
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
|
||||
}
|
||||
if (Ki != null) {
|
||||
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption using given key only; does not add
|
||||
* confounder, padding, or checksum. Incoming data to be encrypted
|
||||
* assumed to have the correct blocksize.
|
||||
* Ignore key usage.
|
||||
*/
|
||||
public byte[] encryptRaw(byte[] baseKey, int usage,
|
||||
byte[] ivec, byte[] plaintext, int start, int len)
|
||||
throws GeneralSecurityException, KrbCryptoException {
|
||||
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("plaintext", plaintext, start, Math.min(len, 32));
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
}
|
||||
|
||||
// Encrypt
|
||||
Cipher encCipher = getCipher(baseKey, ivec, Cipher.ENCRYPT_MODE);
|
||||
int blockSize = encCipher.getBlockSize();
|
||||
|
||||
if ((len % blockSize) != 0) {
|
||||
throw new GeneralSecurityException(
|
||||
"length of data to be encrypted (" + len +
|
||||
") is not a multiple of the blocksize (" + blockSize + ")");
|
||||
}
|
||||
|
||||
int cipherSize = encCipher.getOutputSize(len);
|
||||
byte[] ciphertext = new byte[cipherSize];
|
||||
|
||||
encCipher.doFinal(plaintext, 0, len, ciphertext, 0);
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts data using specified key and initial vector.
|
||||
* @param baseKey encryption key to use
|
||||
* @param ciphertext encrypted data to be decrypted
|
||||
* @param usage ignored
|
||||
*/
|
||||
public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
}
|
||||
|
||||
Cipher decCipher = getCipher(baseKey, ivec, Cipher.DECRYPT_MODE);
|
||||
|
||||
int blockSize = decCipher.getBlockSize();
|
||||
|
||||
if ((len % blockSize) != 0) {
|
||||
throw new GeneralSecurityException(
|
||||
"length of data to be decrypted (" + len +
|
||||
") is not a multiple of the blocksize (" + blockSize + ")");
|
||||
}
|
||||
|
||||
byte[] decrypted = decCipher.doFinal(ciphertext, start, len);
|
||||
|
||||
if (debug) {
|
||||
traceOutput("decrypted", decrypted, 0,
|
||||
Math.min(decrypted.length, 32));
|
||||
}
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param baseKey key from which keys are to be derived using usage
|
||||
* @param ciphertext E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
|
||||
*/
|
||||
public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
|
||||
byte[] ciphertext, int start, int len) throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
byte[] Ke = null;
|
||||
byte[] Ki = null;
|
||||
|
||||
try {
|
||||
// Derive encryption key
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
|
||||
constant[4] = (byte) 0xaa;
|
||||
|
||||
Ke = dk(baseKey, constant); // Encryption key
|
||||
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
if (ivec != null) {
|
||||
traceOutput("old_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
traceOutput("Ke", Ke, 0, Ke.length);
|
||||
}
|
||||
|
||||
Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
|
||||
int blockSize = decCipher.getBlockSize();
|
||||
|
||||
// Decrypt [confounder | plaintext | padding] (without checksum)
|
||||
int cksumSize = getChecksumLength();
|
||||
int cipherSize = len - cksumSize;
|
||||
byte[] decrypted = decCipher.doFinal(ciphertext, start, cipherSize);
|
||||
|
||||
if (debug) {
|
||||
traceOutput("decrypted", decrypted, 0,
|
||||
Math.min(decrypted.length, 32));
|
||||
}
|
||||
|
||||
// decrypted = [confounder | plaintext | padding]
|
||||
|
||||
// Derive integrity key
|
||||
constant[4] = (byte) 0x55;
|
||||
Ki = dk(baseKey, constant); // Integrity key
|
||||
if (debug) {
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("Ki", Ki, 0, Ke.length);
|
||||
}
|
||||
|
||||
// Verify checksum
|
||||
// H1 = HMAC(Ki, conf | plaintext | pad)
|
||||
byte[] calculatedHmac = getHmac(Ki, decrypted);
|
||||
|
||||
if (debug) {
|
||||
traceOutput("calculated Hmac", calculatedHmac, 0,
|
||||
calculatedHmac.length);
|
||||
traceOutput("message Hmac", ciphertext, cipherSize,
|
||||
cksumSize);
|
||||
}
|
||||
|
||||
boolean cksumFailed = false;
|
||||
if (calculatedHmac.length >= cksumSize) {
|
||||
for (int i = 0; i < cksumSize; i++) {
|
||||
if (calculatedHmac[i] != ciphertext[cipherSize+i]) {
|
||||
cksumFailed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cksumFailed) {
|
||||
throw new GeneralSecurityException("Checksum failed");
|
||||
}
|
||||
|
||||
// Prepare decrypted msg and ivec to be returned
|
||||
// Last blockSize bytes of ciphertext without checksum
|
||||
if (ivec != null && ivec.length == blockSize) {
|
||||
System.arraycopy(ciphertext, start + cipherSize - blockSize,
|
||||
ivec, 0, blockSize);
|
||||
if (debug) {
|
||||
traceOutput("new_state.ivec", ivec, 0, ivec.length);
|
||||
}
|
||||
}
|
||||
|
||||
// Get rid of confounder
|
||||
// [plaintext | padding]
|
||||
byte[] plaintext = new byte[decrypted.length - blockSize];
|
||||
System.arraycopy(decrypted, blockSize, plaintext,
|
||||
0, plaintext.length);
|
||||
return plaintext; // padding still there
|
||||
} finally {
|
||||
if (Ke != null) {
|
||||
Arrays.fill(Ke, 0, Ke.length, (byte) 0);
|
||||
}
|
||||
if (Ki != null) {
|
||||
Arrays.fill(Ki, 0, Ki.length, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Round up to the next blocksize
|
||||
int roundup(int n, int blocksize) {
|
||||
return (((n + blocksize - 1) / blocksize) * blocksize);
|
||||
}
|
||||
|
||||
public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
|
||||
int start, int len) throws GeneralSecurityException {
|
||||
|
||||
if (!KeyUsage.isValid(usage)) {
|
||||
throw new GeneralSecurityException("Invalid key usage number: "
|
||||
+ usage);
|
||||
}
|
||||
|
||||
// Derive keys
|
||||
byte[] constant = new byte[5];
|
||||
constant[0] = (byte) ((usage>>24)&0xff);
|
||||
constant[1] = (byte) ((usage>>16)&0xff);
|
||||
constant[2] = (byte) ((usage>>8)&0xff);
|
||||
constant[3] = (byte) (usage&0xff);
|
||||
|
||||
constant[4] = (byte) 0x99;
|
||||
|
||||
byte[] Kc = dk(baseKey, constant); // Checksum key
|
||||
if (debug) {
|
||||
System.err.println("usage: " + usage);
|
||||
traceOutput("input", input, start, Math.min(len, 32));
|
||||
traceOutput("constant", constant, 0, constant.length);
|
||||
traceOutput("baseKey", baseKey, 0, baseKey.length);
|
||||
traceOutput("Kc", Kc, 0, Kc.length);
|
||||
}
|
||||
|
||||
try {
|
||||
// Generate checksum
|
||||
// H1 = HMAC(Kc, input)
|
||||
byte[] hmac = getHmac(Kc, input);
|
||||
if (debug) {
|
||||
traceOutput("hmac", hmac, 0, hmac.length);
|
||||
}
|
||||
if (hmac.length == getChecksumLength()) {
|
||||
return hmac;
|
||||
} else if (hmac.length > getChecksumLength()) {
|
||||
byte[] buf = new byte[getChecksumLength()];
|
||||
System.arraycopy(hmac, 0, buf, 0, buf.length);
|
||||
return buf;
|
||||
} else {
|
||||
throw new GeneralSecurityException("checksum size too short: " +
|
||||
hmac.length + "; expecting : " + getChecksumLength());
|
||||
}
|
||||
} finally {
|
||||
Arrays.fill(Kc, 0, Kc.length, (byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
// DK(Key, Constant) = random-to-key(DR(Key, Constant))
|
||||
byte[] dk(byte[] key, byte[] constant)
|
||||
throws GeneralSecurityException {
|
||||
return randomToKey(dr(key, constant));
|
||||
}
|
||||
|
||||
/*
|
||||
* From RFC 3961.
|
||||
*
|
||||
* DR(Key, Constant) = k-truncate(E(Key, Constant,
|
||||
* initial-cipher-state))
|
||||
*
|
||||
* Here DR is the random-octet generation function described below, and
|
||||
* DK is the key-derivation function produced from it. In this
|
||||
* construction, E(Key, Plaintext, CipherState) is a cipher, Constant is
|
||||
* a well-known constant determined by the specific usage of this
|
||||
* function, and k-truncate truncates its argument by taking the first k
|
||||
* bits. Here, k is the key generation seed length needed for the
|
||||
* encryption system.
|
||||
*
|
||||
* The output of the DR function is a string of bits; the actual key is
|
||||
* produced by applying the cryptosystem's random-to-key operation on
|
||||
* this bitstring.
|
||||
*
|
||||
* If the Constant is smaller than the cipher block size of E, then it
|
||||
* must be expanded with n-fold() so it can be encrypted. If the output
|
||||
* of E is shorter than k bits it is fed back into the encryption as
|
||||
* many times as necessary. The construct is as follows (where |
|
||||
* indicates concatentation):
|
||||
*
|
||||
* K1 = E(Key, n-fold(Constant), initial-cipher-state)
|
||||
* K2 = E(Key, K1, initial-cipher-state)
|
||||
* K3 = E(Key, K2, initial-cipher-state)
|
||||
* K4 = ...
|
||||
*
|
||||
* DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
|
||||
*/
|
||||
private byte[] dr(byte[] key, byte[] constant)
|
||||
throws GeneralSecurityException {
|
||||
|
||||
Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
|
||||
int blocksize = encCipher.getBlockSize();
|
||||
|
||||
if (constant.length != blocksize) {
|
||||
constant = nfold(constant, blocksize * 8);
|
||||
}
|
||||
byte[] toBeEncrypted = constant;
|
||||
|
||||
int keybytes = (getKeySeedLength()>>3); // from bits to bytes
|
||||
byte[] rawkey = new byte[keybytes];
|
||||
int posn = 0;
|
||||
|
||||
/* loop encrypting the blocks until enough key bytes are generated */
|
||||
int n = 0, len;
|
||||
while (n < keybytes) {
|
||||
if (debug) {
|
||||
System.err.println("Encrypting: " +
|
||||
bytesToString(toBeEncrypted));
|
||||
}
|
||||
|
||||
byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
|
||||
if (debug) {
|
||||
System.err.println("K: " + ++posn + " = " +
|
||||
bytesToString(cipherBlock));
|
||||
}
|
||||
|
||||
len = (keybytes - n <= cipherBlock.length ? (keybytes - n) :
|
||||
cipherBlock.length);
|
||||
if (debug) {
|
||||
System.err.println("copying " + len + " key bytes");
|
||||
}
|
||||
System.arraycopy(cipherBlock, 0, rawkey, n, len);
|
||||
n += len;
|
||||
toBeEncrypted = cipherBlock;
|
||||
}
|
||||
return rawkey;
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
|
||||
// From MIT-1.3.1 distribution
|
||||
/*
|
||||
* n-fold(k-bits):
|
||||
* l = lcm(n,k)
|
||||
* r = l/k
|
||||
* s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
|
||||
* compute the 1's complement sum:
|
||||
* n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
|
||||
*/
|
||||
|
||||
/*
|
||||
* representation: msb first, assume n and k are multiples of 8, and
|
||||
* that k>=16. this is the case of all the cryptosystems which are
|
||||
* likely to be used. this function can be replaced if that
|
||||
* assumption ever fails.
|
||||
*/
|
||||
|
||||
/* input length is in bits */
|
||||
static byte[] nfold(byte[] in, int outbits) {
|
||||
|
||||
int inbits = in.length;
|
||||
outbits >>= 3; // count in bytes
|
||||
|
||||
/* first compute lcm(n,k) */
|
||||
int a, b, c, lcm;
|
||||
a = outbits; // n
|
||||
b = inbits; // k
|
||||
|
||||
while (b != 0) {
|
||||
c = b;
|
||||
b = a % b;
|
||||
a = c;
|
||||
}
|
||||
lcm = outbits*inbits/a;
|
||||
|
||||
if (debug) {
|
||||
System.err.println("k: " + inbits);
|
||||
System.err.println("n: " + outbits);
|
||||
System.err.println("lcm: " + lcm);
|
||||
}
|
||||
|
||||
/* now do the real work */
|
||||
byte[] out = new byte[outbits];
|
||||
Arrays.fill(out, (byte)0);
|
||||
|
||||
int thisbyte = 0;
|
||||
int msbit, i, bval, oval;
|
||||
|
||||
// this will end up cycling through k lcm(k,n)/k times, which
|
||||
// is correct
|
||||
for (i = lcm-1; i >= 0; i--) {
|
||||
/* compute the msbit in k which gets added into this byte */
|
||||
msbit = (/* first, start with msbit in the first, unrotated byte */
|
||||
((inbits<<3)-1)
|
||||
/* then, for each byte, shift to right for each repetition */
|
||||
+ (((inbits<<3)+13)*(i/inbits))
|
||||
/* last, pick out correct byte within that shifted repetition */
|
||||
+ ((inbits-(i%inbits)) << 3)) % (inbits << 3);
|
||||
|
||||
/* pull out the byte value itself */
|
||||
// Mask off values using &0xff to get only the lower byte
|
||||
// Use >>> to avoid sign extension
|
||||
bval = ((((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)|
|
||||
(in[((inbits)-(msbit>>>3))%inbits]&0xff))
|
||||
>>>((msbit&7)+1))&0xff;
|
||||
|
||||
/*
|
||||
System.err.println("((" +
|
||||
((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)
|
||||
+ "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")"
|
||||
+ ">>>" + ((msbit&7)+1) + ")&0xff = " + bval);
|
||||
*/
|
||||
|
||||
thisbyte += bval;
|
||||
|
||||
/* do the addition */
|
||||
// Mask off values using &0xff to get only the lower byte
|
||||
oval = (out[i%outbits]&0xff);
|
||||
thisbyte += oval;
|
||||
out[i%outbits] = (byte) (thisbyte&0xff);
|
||||
|
||||
if (debug) {
|
||||
System.err.println("msbit[" + i + "] = " + msbit + "\tbval=" +
|
||||
Integer.toHexString(bval) + "\toval=" +
|
||||
Integer.toHexString(oval)
|
||||
+ "\tsum = " + Integer.toHexString(thisbyte));
|
||||
}
|
||||
|
||||
|
||||
/* keep around the carry bit, if any */
|
||||
thisbyte >>>= 8;
|
||||
|
||||
if (debug) {
|
||||
System.err.println("carry=" + thisbyte);
|
||||
}
|
||||
}
|
||||
|
||||
/* if there's a carry bit left over, add it back in */
|
||||
if (thisbyte != 0) {
|
||||
for (i = outbits-1; i >= 0; i--) {
|
||||
/* do the addition */
|
||||
thisbyte += (out[i]&0xff);
|
||||
out[i] = (byte) (thisbyte&0xff);
|
||||
|
||||
/* keep around the carry bit, if any */
|
||||
thisbyte >>>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Routines used for debugging
|
||||
static String bytesToString(byte[] digest) {
|
||||
// Get character representation of digest
|
||||
StringBuffer digestString = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < digest.length; i++) {
|
||||
if ((digest[i] & 0x000000ff) < 0x10) {
|
||||
digestString.append("0" +
|
||||
Integer.toHexString(digest[i] & 0x000000ff));
|
||||
} else {
|
||||
digestString.append(
|
||||
Integer.toHexString(digest[i] & 0x000000ff));
|
||||
}
|
||||
}
|
||||
return digestString.toString();
|
||||
}
|
||||
|
||||
private static byte[] binaryStringToBytes(String str) {
|
||||
char[] usageStr = str.toCharArray();
|
||||
byte[] usage = new byte[usageStr.length/2];
|
||||
for (int i = 0; i < usage.length; i++) {
|
||||
byte a = Byte.parseByte(new String(usageStr, i*2, 1), 16);
|
||||
byte b = Byte.parseByte(new String(usageStr, i*2 + 1, 1), 16);
|
||||
usage[i] = (byte) ((a<<4)|b);
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
static void traceOutput(String traceTag, byte[] output, int offset,
|
||||
int len) {
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(len);
|
||||
new HexDumpEncoder().encodeBuffer(
|
||||
new ByteArrayInputStream(output, offset, len), out);
|
||||
|
||||
System.err.println(traceTag + ":" + out.toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
// String.getBytes("UTF-8");
|
||||
// Do this instead of using String to avoid making password immutable
|
||||
static byte[] charToUtf8(char[] chars) {
|
||||
Charset utf8 = Charset.forName("UTF-8");
|
||||
|
||||
CharBuffer cb = CharBuffer.wrap(chars);
|
||||
ByteBuffer bb = utf8.encode(cb);
|
||||
int len = bb.limit();
|
||||
byte[] answer = new byte[len];
|
||||
bb.get(answer, 0, len);
|
||||
return answer;
|
||||
}
|
||||
|
||||
static byte[] charToUtf16(char[] chars) {
|
||||
Charset utf8 = Charset.forName("UTF-16LE");
|
||||
|
||||
CharBuffer cb = CharBuffer.wrap(chars);
|
||||
ByteBuffer bb = utf8.encode(cb);
|
||||
int len = bb.limit();
|
||||
byte[] answer = new byte[len];
|
||||
bb.get(answer, 0, len);
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user