Skip to content

Instantly share code, notes, and snippets.

@wangweij
Created April 10, 2015 07:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wangweij/49d98745a461f12c1f54 to your computer and use it in GitHub Desktop.
Save wangweij/49d98745a461f12c1f54 to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import sun.security.krb5.PrincipalName;
public class KerberosAesSha2 {
public static String AES128_SHA2 = "aes128-cts-hmac-sha256-128";
public static String AES256_SHA2 = "aes256-cts-hmac-sha384-192";
public static void main(String[] args) throws Exception {
SecretKey tkey;
Mac mac;
byte[] out;
// Sample results for string-to-key conversion:
PrincipalName princ = new PrincipalName("raeburn@ATHENA.MIT.EDU");
byte[] random = hex("10 DF 9D D7 83 E5 BC 8A CE A1 73 0E 74 35 5F 61");
byte[] salt = salt(AES128_SHA2, random, princ);
tkey = PBKDF2("password".toCharArray(), salt, 32768, 128);
byte[] baseKey = dk(tkey, "kerberos".getBytes());
check(salt, hex(
" 61 65 73 31 32 38 2D 63 74 73 2D 68 6D 61 63 2D\n" +
" 73 68 61 32 35 36 2D 31 32 38 00 10 DF 9D D7 83\n" +
" E5 BC 8A CE A1 73 0E 74 35 5F 61 41 54 48 45 4E\n" +
" 41 2E 4D 49 54 2E 45 44 55 72 61 65 62 75 72 6E"));
check(baseKey, hex("08 9B CA 48 B1 05 EA 6E A7 7C A5 D2 F3 9D C5 E7"));
salt = salt(AES256_SHA2, random, princ);
tkey = PBKDF2("password".toCharArray(), salt, 32768, 256);
baseKey = dk(tkey, "kerberos".getBytes());
check(salt, hex(
" 61 65 73 32 35 36 2D 63 74 73 2D 68 6D 61 63 2D\n" +
" 73 68 61 33 38 34 2D 31 39 32 00 10 DF 9D D7 83\n" +
" E5 BC 8A CE A1 73 0E 74 35 5F 61 41 54 48 45 4E\n" +
" 41 2E 4D 49 54 2E 45 44 55 72 61 65 62 75 72 6E"
));
check(baseKey, hex(
" 45 BD 80 6D BF 6A 83 3A 9C FF C1 C9 45 89 A2 22\n" +
" 36 7A 79 BC 21 C4 13 71 89 06 E9 F5 78 A7 84 67"));
// Sample results for key derivation:
tkey = new SecretKeySpec(
hex("37 05 D9 60 80 C1 77 28 A0 E8 00 EA B6 E0 D2 3C"), "AES");
check(dk(tkey, 2, (byte) 0x99),
hex("B3 1A 01 8A 48 F5 47 76 F4 03 E9 A3 96 32 5D C3"));
check(dk(tkey, 2, (byte) 0xaa),
hex("9B 19 7D D1 E8 C5 60 9D 6E 67 C3 E3 7C 62 C7 2E"));
check(dk(tkey, 2, (byte) 0x55),
hex("9F DA 0E 56 AB 2D 85 E1 56 9A 68 86 96 C2 6A 6C"));
check(dk(tkey, "prf".getBytes()),
hex("9C 66 77 98 08 4F 16 82 1E 77 15 DD 5A A6 EB 71"));
tkey = new SecretKeySpec(hex(
" 6D 40 4D 37 FA F7 9F 9D F0 D3 35 68 D3 20 66 98\n" +
" 00 EB 48 36 47 2E A8 A0 26 D1 6B 71 82 46 0C 52"), "AES");
check(dk(tkey, 2, (byte) 0x99), hex(
" EF 57 18 BE 86 CC 84 96 3D 8B BB 50 31 E9 F5 C4\n" +
" BA 41 F2 8F AF 69 E7 3D"));
check(dk(tkey, 2, (byte) 0xaa), hex(
" 56 AB 22 BE E6 3D 82 D7 BC 52 27 F6 77 3F 8E A7\n" +
" A5 EB 1C 82 51 60 C3 83 12 98 0C 44 2E 5C 7E 49"));
check(dk(tkey, 2, (byte) 0x55), hex(
" 69 B1 65 14 E3 CD 8E 56 B8 20 10 D5 C7 30 12 B6\n" +
" 22 C4 D0 0F FC 23 ED 1F"));
check(dk(tkey, "prf".getBytes()), hex(
" 5D 63 0D B7 EF DE 37 DE 9C 92 03 C5 2B D9 6C 77\n" +
" 31 BE 1C 5B DD 50 DC 75 44 D9 60 AF F3 CC 23 04"));
// Sample pseudorandom function (PRF) invocations:
tkey = new SecretKeySpec(
hex("9C 66 77 98 08 4F 16 82 1E 77 15 DD 5A A6 EB 71"), "AES");
mac = Mac.getInstance("HmacSHA256");
mac.init(tkey);
check(Arrays.copyOf(mac.doFinal("test".getBytes()), 16),
hex("3A CA 18 6C C1 26 56 76 5C FE B1 D2 2D 1C B1 36"));
tkey = new SecretKeySpec(hex(
" 5D 63 0D B7 EF DE 37 DE 9C 92 03 C5 2B D9 6C 77\n" +
" 31 BE 1C 5B DD 50 DC 75 44 D9 60 AF F3 CC 23 04"), "AES");
mac = Mac.getInstance("HmacSHA384");
mac.init(tkey);
check(Arrays.copyOf(mac.doFinal("test".getBytes()), 32), hex(
" 01 72 03 F2 90 CD 16 6C D6 B2 BB 4F 18 7D 16 23\n" +
" 6B 9A 4E D7 66 19 D8 11 6C 64 06 A3 37 E7 F9 08"));
// Sample encryptions (all using the default cipher state):
byte[] confounder, cipherState, out1;
SecretKey aes, mkey;
Cipher cipher;
IvParameterSpec encIv;
confounder = hex("7E 58 95 EA F2 67 24 35 BA D8 17 F5 45 A3 71 48");
aes = new SecretKeySpec(
hex("9B 19 7D D1 E8 C5 60 9D 6E 67 C3 E3 7C 62 C7 2E"), "AES");
mkey = new SecretKeySpec(
hex("9F DA 0E 56 AB 2D 85 E1 56 9A 68 86 96 C2 6A 6C"), "AES");
cipherState = new byte[16];
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
out = cipher.doFinal(confounder);
check(out, hex("EF 85 FB 89 0B B8 47 2F 4D AB 20 39 4D CA 78 1D"));
mac = Mac.getInstance("HmacSHA256");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 16);
check(out, hex("AD 87 7E DA 39 D5 0C 87 0C 0D 5A 0A 8E 48 C7 18"));
confounder = hex("7B CA 28 5E 2F D4 13 0F B5 5B 1A 5C 83 BC 5B 24");
aes = new SecretKeySpec(
hex("4E FD A6 52 4E 6B 56 B4 F2 12 61 FB FC 93 21 AB"), "AES");
mkey = new SecretKeySpec(
hex("29 1B 0C 37 73 D7 6E E6 BA 2C CF 1E 03 93 F6 3E"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(hex("00 01 02 03 04 05"));
check(out, hex(
" AB 70 F4 BA 9D 76 55 AF 24 B5 76 E4 6E FB 7A 98\n" +
" F1 4B 93 65 9D 1B"));
mac = Mac.getInstance("HmacSHA256");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 16);
check(out, hex("A0 C5 F4 7C AA 84 42 19 F9 08 AD ED EF 52 5B 71"));
confounder = hex("56 AB 21 71 3F F6 2C 0A 14 57 20 0F 6F A9 94 8F");
aes = new SecretKeySpec(
hex("FF 82 40 42 4B CC BA 05 56 50 C0 39 3B 83 DF 3B"), "AES");
mkey = new SecretKeySpec(
hex("ED 15 62 8B 45 35 8C BF 7F 50 E7 64 C2 6B 8A 1A"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(
hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
check(out, hex(
" E7 34 8E 74 86 E5 A7 87 0F 51 2E 65 CA C8 65 75\n" +
" 78 26 FF C0 EA 5B 28 A8 B9 60 8B B3 08 CD E2 CC"));
mac = Mac.getInstance("HmacSHA256");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 16);
check(out, hex("C1 85 4E F2 F3 4D 02 35 4E C7 AA 53 BE 03 BE D5"));
confounder = hex("A7 A4 E2 9A 47 28 CE 10 66 4F B6 4E 49 AD 3F AC");
aes = new SecretKeySpec(
hex("B5 9B 88 75 AD 5D CA FF F7 79 4D 93 F8 19 9D 79"), "AES");
mkey = new SecretKeySpec(
hex("0A 42 1D 72 2F 8F C2 D6 84 8B 1C DA D1 5A 49 C9"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(hex(
" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
" 10 11 12 13 14"));
check(out, hex(
" C3 53 72 86 FF 9C FE 49 8D 2E FC FC 99 6D AC 2D\n" +
" 52 CA 56 03 B3 E8 68 EA 1E 9C 54 E8 2A E5 CE 7A\n" +
" 79 3E 21 09 7D"));
mac = Mac.getInstance("HmacSHA256");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 16);
check(out, hex("5B 03 5D 78 A7 E9 84 75 EC 91 0C E3 7A A0 2A 7D"));
confounder = hex("F7 64 E9 FA 15 C2 76 47 8B 2C 7D 0C 4E 5F 58 E4");
aes = new SecretKeySpec(hex(
" 0F A2 0D 7D 03 33 EE 65 16 2C DA 67 E7 AD 0D 3C\n" +
" 5E 03 1F 3B 66 70 E0 31 28 2F AC C2 87 9C 21 C7"), "AES");
mkey = new SecretKeySpec(hex(
" 53 BF 30 6A 68 33 A3 25 18 FC B8 5F 63 1D 03 D5\n" +
" 2E E3 1B 39 75 2F 57 ED"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(hex(""));
check(out, hex("FE 6A 55 14 F3 99 7C 8C AA F2 2D 8E EE 28 6D 7D"));
mac = Mac.getInstance("HmacSHA384");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 24);
check(out, hex(
" 81 1E AD AE DA 7F B9 75 AD 96 C0 07 5A 98 83 F9\n" +
" AC 3A AB 06 97 FC E8 5A"));
confounder = hex("B8 0D 32 51 C1 F6 47 14 94 25 6F FE 71 2D 0B 9A");
aes = new SecretKeySpec(hex(
" 47 DA 4C A2 8B D1 C1 14 D5 50 7E 55 81 86 CA 4F\n" +
" DB A0 DA E5 B2 4F 6D 68 89 D5 3A FB F1 D0 B8 36"), "AES");
mkey = new SecretKeySpec(hex(
" 13 6B 5C 83 C9 53 AE 29 E2 C2 31 6A 7B 34 B8 C2\n" +
" AD 26 E4 66 7F AB 42 6E"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(hex("00 01 02 03 04 05"));
check(out, hex(
" 14 78 CF 26 BA 5E 7D 3A 9D C7 99 7A 80 10 76 2C\n" +
" 74 3B D4 BC 22 EC"));
mac = Mac.getInstance("HmacSHA384");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 24);
check(out, hex(
" 17 2A B2 BB 12 B0 0D BE C2 BF E6 29 CF DD 62 EC\n" +
" 3E 45 83 8F A9 FB AE 6E"));
confounder = hex("53 BF 8A 0D 10 52 65 D4 E2 76 42 86 24 CE 5E 63");
aes = new SecretKeySpec(hex(
" 5E A6 16 D8 FD A2 33 F1 B4 99 79 A4 B9 FA 01 D3\n" +
" 21 B1 3D 6F BD 6E 3B B7 2E 54 B4 85 E2 36 AF 23"), "AES");
mkey = new SecretKeySpec(hex(
" AD D3 8D C9 86 83 C5 CC 14 E3 C7 37 EA A7 06 47\n" +
" B3 19 71 0E 87 6A 38 77"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(
hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"));
check(out, hex(
" B6 0B 6A A6 00 C2 D8 4B 03 A6 1C 18 DD A7 05 F0\n" +
" FE 90 B9 36 B8 8C 4F EA 06 D7 1A 99 35 75 28 60"));
mac = Mac.getInstance("HmacSHA384");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 24);
check(out, hex(
" 2F E5 BD 6E 41 78 17 D6 2A D2 C9 CF 50 8D FA E1\n" +
" B3 C9 6F 4B 45 C1 9B 77"));
confounder = hex("76 3E 65 36 7E 86 4F 02 F5 51 53 C7 E3 B5 8A F1");
aes = new SecretKeySpec(hex(
" B3 A8 02 E3 40 61 3E F1 E0 EC E9 1A 15 7C 59 12\n" +
" 6F BD C4 B8 C2 4C 8D 0B 2E 5A 30 F0 1E 7E 34 88"), "AES");
mkey = new SecretKeySpec(hex(
" FC 0B 49 9B 83 55 A3 2A C3 C9 AC B6 64 93 63 EB\n" +
" 5D BB A4 25 1A 75 B2 0A"), "AES");
cipher = Cipher.getInstance("AES/CTS/NoPadding");
encIv = new IvParameterSpec(cipherState, 0, cipherState.length);
cipher.init(Cipher.ENCRYPT_MODE, aes, encIv);
cipher.update(confounder);
out = cipher.doFinal(hex(
" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
" 10 11 12 13 14"));
check(out, hex(
" 4C F9 8B 5E DA 0D 94 9F B3 8E CD 67 DE 80 0F 79\n" +
" 46 19 F9 EA CB 30 54 33 50 6B 9A D4 48 4B D9 5B\n" +
" E0 55 F5 69 EB"));
mac = Mac.getInstance("HmacSHA384");
mac.init(mkey);
mac.update(cipherState);
out = Arrays.copyOf(mac.doFinal(out), 24);
check(out, hex(
" 7C F8 36 70 75 8C BF DA 31 3C FE F8 74 2B 11 74\n" +
" 14 A7 DD 12 B4 96 64 2E"));
// Sample checksums:
mkey = new SecretKeySpec(
hex("B3 1A 01 8A 48 F5 47 76 F4 03 E9 A3 96 32 5D C3"), "AES");
mac = Mac.getInstance("HmacSHA256");
mac.init(mkey);
out = mac.doFinal(hex(
" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
" 10 11 12 13 14"));
out = Arrays.copyOf(out, 16);
check(out, hex("D7 83 67 18 66 43 D6 7B 41 1C BA 91 39 FC 1D EE"));
mkey = new SecretKeySpec(hex(
" EF 57 18 BE 86 CC 84 96 3D 8B BB 50 31 E9 F5 C4\n" +
" BA 41 F2 8F AF 69 E7 3D"), "HMAC");
mac = Mac.getInstance("HmacSHA384");
mac.init(mkey);
out = mac.doFinal(hex(
" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" +
" 10 11 12 13 14"));
out = Arrays.copyOf(out, 24);
check(out, hex(
" 45 EE 79 15 67 EE FC A3 7F 4A C1 E0 22 2D E8 0D\n" +
" 43 C3 BF A0 66 99 67 2A"));
}
private static byte[] salt(String etype, byte[] random, PrincipalName p) {
byte[] name = p.getSalt().getBytes();
byte[] e = etype.getBytes();
int elen = e.length;
int len = elen + 1 + 16 + name.length;
byte[] result = Arrays.copyOf(e, len);
result[elen] = 0;
System.arraycopy(random, 0, result, elen+1, 16);
System.arraycopy(name, 0, result, elen+17, name.length);
return result;
}
private static SecretKey PBKDF2(
char[] passphrase, byte[] salt, int iterCount, int keyLength)
throws Exception {
SecretKeyFactory skf = keyLength == 128 ?
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"):
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA384");
return skf.generateSecret(
new PBEKeySpec(passphrase, salt, iterCount, keyLength));
}
private static byte[] dk(SecretKey tkey, int usage, byte type)
throws Exception{
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] = type;
return dk(tkey, constant);
}
private static byte[] dk(SecretKey tkey, byte[] constant) throws Exception {
byte[] result;
int resultLen;
byte[] input = new byte[constant.length + 9];
input[3] = 1;
System.arraycopy(constant, 0, input, 4, constant.length);
if (tkey.getEncoded().length == 16) {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(tkey);
input[input.length-1] = (byte)0x80;
result = mac.doFinal(input);
resultLen = 16;
} else {
Mac mac = Mac.getInstance("HmacSHA384");
mac.init(tkey);
byte last = constant[constant.length-1];
if (last == (byte)0x99 || last == (byte)0x55) {
input[input.length-1] = (byte)0xC0;
resultLen = 24;
} else {
input[input.length-2] = 1;
resultLen = 32;
}
result = mac.doFinal(input);
}
return Arrays.copyOf(result, resultLen);
}
private static byte[] hex(String var) {
var = var.replaceAll("\\s", "");
byte[] data = new byte[var.length()/2];
for (int i=0; i<data.length; i++) {
data[i] = Integer.valueOf(var.substring(2*i,2*i+2), 16).byteValue();
}
return data;
}
private static void check(byte[] b1, byte[] b2) throws Exception {
if (!Arrays.equals(b1, b2)) {
throw new Exception("Failure");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment