Created
April 10, 2015 07:08
-
-
Save wangweij/49d98745a461f12c1f54 to your computer and use it in GitHub Desktop.
Verifying Test Vectors in https://tools.ietf.org/html/draft-ietf-kitten-aes-cts-hmac-sha2-06
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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