Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/TestCipher.java
41159 views
/*1* Copyright (c) 2015, 2016, 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*/2223import static java.lang.System.out;2425import java.security.InvalidAlgorithmParameterException;26import java.security.InvalidKeyException;27import java.security.NoSuchAlgorithmException;28import java.security.NoSuchProviderException;29import java.security.spec.AlgorithmParameterSpec;3031import javax.crypto.BadPaddingException;32import javax.crypto.Cipher;33import javax.crypto.IllegalBlockSizeException;34import javax.crypto.KeyGenerator;35import javax.crypto.NoSuchPaddingException;36import javax.crypto.SecretKey;37import javax.crypto.ShortBufferException;38import javax.crypto.spec.IvParameterSpec;39import javax.crypto.spec.SecretKeySpec;4041/**42* This is a abstract class used to test various ciphers43*/44public abstract class TestCipher {4546private final String SUNJCE = "SunJCE";47private final String ALGORITHM;48private final String[] MODES;49private final String[] PADDINGS;5051/* Used to test variable-key-length ciphers:52Key size tested is increment of KEYCUTTER from minKeySize53to min(maxKeySize, Cipher.getMaxAllowedKeyLength(algo)).54*/55private final int KEYCUTTER = 8;56private final int minKeySize;57private final int maxKeySize;5859// Used to assert that Encryption/Decryption works with same buffer60// TEXT_LEN is multiple of blocks in order to work against ciphers w/ NoPadding61private final int TEXT_LEN = 800;62private final int ENC_OFFSET = 6;63private final int STORAGE_OFFSET = 3;64private final int PAD_BYTES = 16;6566private final byte[] IV;67private final byte[] INPUT_TEXT;6869// for variable-key-length ciphers70TestCipher(String algo, String[] modes, String[] paddings,71int minKeySize, int maxKeySize) throws NoSuchAlgorithmException {72ALGORITHM = algo;73MODES = modes;74PADDINGS = paddings;75this.minKeySize = minKeySize;76int maxAllowedKeySize = Cipher.getMaxAllowedKeyLength(ALGORITHM);77if (maxKeySize > maxAllowedKeySize) {78maxKeySize = maxAllowedKeySize;79}80this.maxKeySize = maxKeySize;81IV = generateBytes(8);82INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);83}8485// for fixed-key-length ciphers86TestCipher(String algo, String[] modes, String[] paddings) {87ALGORITHM = algo;88MODES = modes;89PADDINGS = paddings;90this.minKeySize = this.maxKeySize = 0;9192IV = generateBytes(8);93INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);94}9596private static byte[] generateBytes(int length) {97byte[] bytes = new byte[length];98for (int i = 0; i < length; i++) {99bytes[i] = (byte) (i & 0xff);100}101return bytes;102}103104private boolean isMultipleKeyLengthSupported() {105return (maxKeySize != minKeySize);106}107108public void runAll() throws InvalidKeyException,109NoSuchPaddingException, InvalidAlgorithmParameterException,110ShortBufferException, IllegalBlockSizeException,111BadPaddingException, NoSuchAlgorithmException,112NoSuchProviderException {113114for (String mode : MODES) {115for (String padding : PADDINGS) {116if (!isMultipleKeyLengthSupported()) {117runTest(mode, padding, minKeySize);118} else {119int keySize = maxKeySize;120while (keySize >= minKeySize) {121out.println("With Key Strength: " + keySize);122runTest(mode, padding, keySize);123keySize -= KEYCUTTER;124}125}126}127}128}129130private void runTest(String mo, String pad, int keySize)131throws NoSuchPaddingException, BadPaddingException,132ShortBufferException, IllegalBlockSizeException,133InvalidAlgorithmParameterException, InvalidKeyException,134NoSuchAlgorithmException, NoSuchProviderException {135136String TRANSFORMATION = ALGORITHM + "/" + mo + "/" + pad;137out.println("Testing: " + TRANSFORMATION);138139// Initialization140Cipher ci = Cipher.getInstance(TRANSFORMATION, SUNJCE);141KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, SUNJCE);142if (keySize != 0) {143kg.init(keySize);144}145146SecretKey key = kg.generateKey();147SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), ALGORITHM);148149AlgorithmParameterSpec aps = new IvParameterSpec(IV);150if (mo.equalsIgnoreCase("ECB")) {151ci.init(Cipher.ENCRYPT_MODE, key);152} else {153ci.init(Cipher.ENCRYPT_MODE, key, aps);154}155156// Encryption157byte[] plainText = INPUT_TEXT.clone();158159// Generate cipher and save to separate buffer160byte[] cipherText = ci.doFinal(INPUT_TEXT, ENC_OFFSET, TEXT_LEN);161162// Generate cipher and save to same buffer163int enc_bytes = ci.update(164INPUT_TEXT, ENC_OFFSET, TEXT_LEN, INPUT_TEXT, STORAGE_OFFSET);165enc_bytes += ci.doFinal(INPUT_TEXT, enc_bytes + STORAGE_OFFSET);166167if (!equalsBlock(168INPUT_TEXT, STORAGE_OFFSET, enc_bytes,169cipherText, 0, cipherText.length)) {170throw new RuntimeException(171"Different ciphers generated with same buffer");172}173174// Decryption175if (mo.equalsIgnoreCase("ECB")) {176ci.init(Cipher.DECRYPT_MODE, skeySpec);177} else {178ci.init(Cipher.DECRYPT_MODE, skeySpec, aps);179}180181// Recover text from cipher and save to separate buffer182byte[] recoveredText = ci.doFinal(cipherText, 0, cipherText.length);183184if (!equalsBlock(185plainText, ENC_OFFSET, TEXT_LEN,186recoveredText, 0, recoveredText.length)) {187throw new RuntimeException(188"Recovered text not same as plain text");189} else {190out.println("Recovered and plain text are same");191}192193// Recover text from cipher and save to same buffer194int dec_bytes = ci.update(195INPUT_TEXT, STORAGE_OFFSET, enc_bytes, INPUT_TEXT, ENC_OFFSET);196dec_bytes += ci.doFinal(INPUT_TEXT, dec_bytes + ENC_OFFSET);197198if (!equalsBlock(199plainText, ENC_OFFSET, TEXT_LEN,200INPUT_TEXT, ENC_OFFSET, dec_bytes)) {201throw new RuntimeException(202"Recovered text not same as plain text with same buffer");203} else {204out.println("Recovered and plain text are same with same buffer");205}206207out.println("Test Passed.");208}209210private static boolean equalsBlock(byte[] b1, int off1, int len1,211byte[] b2, int off2, int len2) {212if (len1 != len2) {213return false;214}215for (int i = off1, j = off2, k = 0; k < len1; i++, j++, k++) {216if (b1[i] != b2[j]) {217return false;218}219}220return true;221}222}223224225