Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/CTS/CTSMode.java
41161 views
/*1* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 508325326* @run main CTSMode27* @summary Verify that CTR mode works as expected28* @author Valerie Peng29*/3031import java.util.*;32import java.security.AlgorithmParameters;33import javax.crypto.*;34import javax.crypto.spec.*;3536public class CTSMode {3738private final static byte[] toByteArray(String s) {39char[] c = s.toCharArray();40byte[] t = new byte[c.length / 2];41int n = 0;42int d1 = -1;43int d2 = -1;44for (int i = 0; i < c.length; i++) {45char ch = c[i];46if (d1 == -1) {47d1 = Character.digit(ch, 16);48} else {49d2 = Character.digit(ch, 16);50if (d2 != -1) {51t[n++] = (byte)((d1 << 4) | d2);52d1 = -1;53d2 = -1;54}55}56}57if (d1 != -1) {58throw new RuntimeException();59}60if (n == t.length) {61return t;62}63byte[] b = new byte[n];64System.arraycopy(t, 0, b, 0, n);65return b;66}6768private final static SecretKey KEY1 =69new SecretKeySpec(toByteArray("636869636b656e207465726979616b69"),70"AES");7172private final static IvParameterSpec IV1 =73new IvParameterSpec(new byte[16]);7475/*76* Use test vectors, i.e. PLAIN1 and CIPHER1, from the appendix B77* of RFC 3962 "Advanced Encryption Standard (AES) Encryption for78* Kerberos 5".79*/80private final static byte[][] PLAIN1 = {81toByteArray("4920776f756c64206c696b652074686520"),82toByteArray("4920776f756c64206c696b6520746865" +83"2047656e6572616c20476175277320"),84toByteArray("4920776f756c64206c696b6520746865" +85"2047656e6572616c2047617527732043"),86toByteArray("4920776f756c64206c696b6520746865" +87"2047656e6572616c2047617527732043" +88"6869636b656e2c20706c656173652c"),89toByteArray("4920776f756c64206c696b6520746865" +90"2047656e6572616c2047617527732043" +91"6869636b656e2c20706c656173652c20"),92toByteArray("4920776f756c64206c696b6520746865" +93"2047656e6572616c2047617527732043" +94"6869636b656e2c20706c656173652c20" +95"616e6420776f6e746f6e20736f75702e")96};97private final static byte[][] CIPHER1 = {98toByteArray("c6353568f2bf8cb4d8a580362da7ff7f97"),99toByteArray("fc00783e0efdb2c1d445d4c8eff7ed22" +100"97687268d6ecccc0c07b25e25ecfe5"),101toByteArray("39312523a78662d5be7fcbcc98ebf5a8" +102"97687268d6ecccc0c07b25e25ecfe584"),103toByteArray("97687268d6ecccc0c07b25e25ecfe584" +104"b3fffd940c16a18c1b5549d2f838029e" +105"39312523a78662d5be7fcbcc98ebf5"),106toByteArray("97687268d6ecccc0c07b25e25ecfe584" +107"9dad8bbb96c4cdc03bc103e1a194bbd8" +108"39312523a78662d5be7fcbcc98ebf5a8"),109toByteArray("97687268d6ecccc0c07b25e25ecfe584" +110"39312523a78662d5be7fcbcc98ebf5a8" +111"4807efe836ee89a526730dbc2f7bc840" +112"9dad8bbb96c4cdc03bc103e1a194bbd8"),113};114115private final static byte[] IV2_SRC =116toByteArray("11223344556677880011223344556677");117118private final static String[] ALGORITHMS2 = {119"DES", "DESede", "Blowfish", "AES"120};121private final static int[] KEYSIZES2 = {1228, 24, 16, 16123};124125private static String toString(byte[] b) {126StringBuffer sb = new StringBuffer(b.length * 3);127for (int i = 0; i < b.length; i++) {128int k = b[i] & 0xff;129if (i != 0) {130sb.append(':');131}132sb.append(Character.forDigit(k >> 4, 16));133sb.append(Character.forDigit(k & 0xf, 16));134}135return sb.toString();136}137138public static void main(String[] args) throws Exception {139test1();140test2();141test3();142}143144/**145* Test with the test vectors and see if results match.146*/147private static void test1() throws Exception {148for (int i = 0; i < PLAIN1.length; i++) {149String algo = KEY1.getAlgorithm();150int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);151if (KEY1.getEncoded().length > MAX_KEYSIZE) {152// skip tests using keys whose length exceeds153// what's configured in jce jurisdiction policy files.154continue;155}156System.out.println("Running test1_" + i + " (" + algo + ")");157Cipher cipher = Cipher.getInstance(algo+ "/CTS/NoPadding",158"SunJCE");159byte[] plainText = PLAIN1[i];160byte[] cipherText = CIPHER1[i];161cipher.init(Cipher.ENCRYPT_MODE, KEY1, IV1);162byte[] enc = cipher.doFinal(plainText);163if (Arrays.equals(cipherText, enc) == false) {164System.out.println("plain: " + toString(plainText));165System.out.println("cipher: " + toString(cipherText));166System.out.println("actual: " + toString(enc));167throw new RuntimeException("Encryption failure for test " + i);168}169cipher.init(Cipher.DECRYPT_MODE, KEY1, IV1);170byte[] dec = cipher.doFinal(cipherText);171if (Arrays.equals(plainText, dec) == false) {172System.out.println("cipher: " + toString(cipherText));173System.out.println("plain: " + toString(plainText));174System.out.println("actual: " + toString(enc));175throw new RuntimeException("Decryption failure for test " + i);176}177}178}179180/**181* Test with a combination of update/doFinal calls and make182* sure that same data is recovered after decryption.183*/184private static void test2() throws Exception {185for (int i = 0; i < ALGORITHMS2.length; i++) {186String algo = ALGORITHMS2[i];187System.out.println("Running test2_" + i + " (" + algo + ")");188int keySize = KEYSIZES2[i];189int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);190if (keySize > MAX_KEYSIZE) {191// skip tests using keys whose length exceeds192// what's configured in jce jurisdiction policy files.193continue;194}195Cipher cipher =196Cipher.getInstance(algo+"/CTS/NoPadding", "SunJCE");197int blockSize = cipher.getBlockSize();198SecretKeySpec key = new SecretKeySpec(new byte[keySize], algo);199// Make sure encryption works for inputs with valid length200byte[] plainText = PLAIN1[3];201cipher.init(Cipher.ENCRYPT_MODE, key);202byte[] cipherText = new byte[plainText.length];203int firstPartLen = blockSize + 1;204int processed1 = cipher.update(plainText, 0, firstPartLen,205cipherText, 0);206int processed2 = cipher.doFinal(plainText, firstPartLen,207plainText.length-firstPartLen,208cipherText, processed1);209AlgorithmParameters params = cipher.getParameters();210if ((processed1 + processed2) != plainText.length) {211System.out.println("processed1 = " + processed1);212System.out.println("processed2 = " + processed2);213System.out.println("total length = " + plainText.length);214throw new RuntimeException("Encryption failure for test " + i);215}216// Make sure IllegalBlockSizeException is thrown for inputs217// with less-than-a-block length218try {219cipher.doFinal(new byte[blockSize-1]);220throw new RuntimeException("Expected IBSE is not thrown");221} catch (IllegalBlockSizeException ibse) {222}223// Make sure data is encrypted as in CBC mode for inputs224// which is exactly one block long225IvParameterSpec iv2 = new IvParameterSpec(IV2_SRC, 0, blockSize);226cipher.init(Cipher.ENCRYPT_MODE, key, iv2);227Cipher cipher2 =228Cipher.getInstance(algo+"/CBC/NoPadding", "SunJCE");229cipher2.init(Cipher.ENCRYPT_MODE, key, iv2);230231byte[] eout = cipher.doFinal(IV2_SRC, 0, blockSize);232byte[] eout2 = cipher2.doFinal(IV2_SRC, 0, blockSize);233if (!Arrays.equals(eout, eout2)) {234throw new RuntimeException("Different encryption output " +235"for CBC and CTS");236}237// Make sure decryption works for inputs with valid length238cipher.init(Cipher.DECRYPT_MODE, key, params);239byte[] recoveredText =240new byte[cipher.getOutputSize(cipherText.length)];241processed1 = cipher.update(cipherText, 0, firstPartLen,242recoveredText, 0);243processed2 = cipher.update(cipherText, firstPartLen,244cipherText.length-firstPartLen,245recoveredText, processed1);246int processed3 =247cipher.doFinal(recoveredText, processed1+processed2);248if ((processed1 + processed2 + processed3) != plainText.length) {249System.out.println("processed1 = " + processed1);250System.out.println("processed2 = " + processed2);251System.out.println("processed3 = " + processed3);252System.out.println("total length = " + plainText.length);253throw new RuntimeException("Decryption failure for test " + i);254}255if (Arrays.equals(plainText, recoveredText) == false) {256System.out.println("plain: " + toString(plainText));257System.out.println("recovered: " + toString(recoveredText));258throw new RuntimeException("Decryption failure for test " + i);259}260// Make sure IllegalBlockSizeException is thrown for inputs261// with less-than-a-block length262try {263cipher.doFinal(new byte[blockSize-1]);264throw new RuntimeException("Expected IBSE is not thrown");265} catch (IllegalBlockSizeException ibse) {266}267// Make sure data is decrypted as in CBC mode for inputs268// which is exactly one block long269cipher.init(Cipher.DECRYPT_MODE, key, iv2);270cipher2.init(Cipher.DECRYPT_MODE, key, iv2);271byte[] dout = cipher.doFinal(eout);272byte[] dout2 = cipher2.doFinal(eout2);273if (!Arrays.equals(dout, dout2)) {274throw new RuntimeException("Different decryption output " +275"for CBC and CTS");276}277}278}279280/**281* Test with a shortBuffer and see if encryption/decryption282* still works correctly afterwards.283*/284private static void test3() throws Exception {285// Skip PLAIN1[0, 1, 2] due to their lengths286for (int i = 3; i < PLAIN1.length; i++) {287String algo = KEY1.getAlgorithm();288System.out.println("Running test3_" + i + " (" + algo + ")");289int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);290if (KEY1.getEncoded().length > MAX_KEYSIZE) {291// skip tests using keys whose length exceeds292// what's configured in jce jurisdiction policy files.293continue;294}295Cipher cipher =296Cipher.getInstance(algo+ "/CTS/NoPadding", "SunJCE");297byte[] plainText = PLAIN1[i];298byte[] cipherText = CIPHER1[i];299byte[] enc = new byte[plainText.length];300cipher.init(Cipher.ENCRYPT_MODE, KEY1, IV1);301int halfInput = plainText.length/2;302int processed1 = cipher.update(plainText, 0, halfInput,303enc, 0);304try {305cipher.doFinal(plainText, halfInput,306plainText.length-halfInput,307new byte[1], 0);308throw new RuntimeException("Expected Exception is not thrown");309} catch (ShortBufferException sbe) {310// expected exception thrown; retry311int processed2 =312cipher.doFinal(plainText, halfInput,313plainText.length-halfInput,314enc, processed1);315if ((processed1 + processed2) != enc.length) {316System.out.println("processed1 = " + processed1);317System.out.println("processed2 = " + processed2);318System.out.println("total length = " + enc.length);319throw new RuntimeException("Encryption length check " +320"failed");321}322}323if (Arrays.equals(cipherText, enc) == false) {324System.out.println("plain: " + toString(plainText));325System.out.println("cipher: " + toString(cipherText));326System.out.println("actual: " + toString(enc));327throw new RuntimeException("Encryption failure for test " + i);328}329cipher.init(Cipher.DECRYPT_MODE, KEY1, IV1);330byte[] dec =331new byte[cipher.getOutputSize(cipherText.length)];332processed1 = cipher.update(cipherText, 0, halfInput,333dec, 0);334try {335cipher.update(cipherText, halfInput,336cipherText.length-halfInput,337new byte[1], 0);338throw new RuntimeException("Expected Exception is not thrown");339} catch (ShortBufferException sbe) {340// expected exception thrown; retry341int processed2 = cipher.update(cipherText, halfInput,342cipherText.length-halfInput,343dec, processed1);344int processed3 =345cipher.doFinal(dec, processed1+processed2);346if ((processed1 + processed2 + processed3) != dec.length) {347System.out.println("processed1 = " + processed1);348System.out.println("processed2 = " + processed2);349System.out.println("processed3 = " + processed3);350System.out.println("total length = " + dec.length);351throw new RuntimeException("Decryption length check " +352"failed");353}354}355if (Arrays.equals(plainText, dec) == false) {356System.out.println("cipher: " + toString(cipherText));357System.out.println("plain: " + toString(plainText));358System.out.println("actualD: " + toString(dec));359throw new RuntimeException("Decryption failure for test " + i);360}361}362}363}364365366