Path: blob/master/test/jdk/javax/crypto/Cipher/ExampleVectors/CheckExampleVectors.java
41153 views
/*1* Copyright (c) 2017, 2018, 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 800625926* @summary Test several modes of operation using vectors from SP 800-38A27* @run main CheckExampleVectors28*/2930import java.io.*;31import java.security.*;32import java.util.*;33import java.util.function.*;34import javax.crypto.*;35import javax.crypto.spec.*;3637public class CheckExampleVectors {3839private enum Mode {40ECB,41CBC,42CFB1,43CFB8,44CFB128,45OFB,46CTR47}4849private enum Operation {50Encrypt,51Decrypt52}5354private static class Block {55private byte[] input;56private byte[] output;5758public Block() {5960}61public Block(String settings) {62String[] settingsParts = settings.split(",");63input = stringToBytes(settingsParts[0]);64output = stringToBytes(settingsParts[1]);65}66public byte[] getInput() {67return input;68}69public byte[] getOutput() {70return output;71}72}7374private static class TestVector {75private Mode mode;76private Operation operation;77private byte[] key;78private byte[] iv;79private List<Block> blocks = new ArrayList<Block>();8081public TestVector(String settings) {82String[] settingsParts = settings.split(",");83mode = Mode.valueOf(settingsParts[0]);84operation = Operation.valueOf(settingsParts[1]);85key = stringToBytes(settingsParts[2]);86if (settingsParts.length > 3) {87iv = stringToBytes(settingsParts[3]);88}89}9091public Mode getMode() {92return mode;93}94public Operation getOperation() {95return operation;96}97public byte[] getKey() {98return key;99}100public byte[] getIv() {101return iv;102}103public void addBlock (Block b) {104blocks.add(b);105}106public Iterable<Block> getBlocks() {107return blocks;108}109}110111private static final String VECTOR_FILE_NAME = "NIST_800_38A_vectors.txt";112private static final Mode[] REQUIRED_MODES = {Mode.ECB, Mode.CBC, Mode.CTR};113private static Set<Mode> supportedModes = new HashSet<Mode>();114115public static void main(String[] args) throws Exception {116checkAllProviders();117checkSupportedModes();118}119120private static byte[] stringToBytes(String v) {121if (v.equals("")) {122return null;123}124return Base64.getDecoder().decode(v);125}126127private static String toModeString(Mode mode) {128return mode.toString();129}130131private static int toCipherOperation(Operation op) {132switch (op) {133case Encrypt:134return Cipher.ENCRYPT_MODE;135case Decrypt:136return Cipher.DECRYPT_MODE;137}138139throw new RuntimeException("Unknown operation: " + op);140}141142private static void log(String str) {143System.out.println(str);144}145146private static void checkVector(String providerName, TestVector test) {147148String modeString = toModeString(test.getMode());149String cipherString = "AES" + "/" + modeString + "/" + "NoPadding";150log("checking: " + cipherString + " on " + providerName);151try {152Cipher cipher = Cipher.getInstance(cipherString, providerName);153SecretKeySpec key = new SecretKeySpec(test.getKey(), "AES");154if (test.getIv() != null) {155IvParameterSpec iv = new IvParameterSpec(test.getIv());156cipher.init(toCipherOperation(test.getOperation()), key, iv);157}158else {159cipher.init(toCipherOperation(test.getOperation()), key);160}161int blockIndex = 0;162for (Block curBlock : test.getBlocks()) {163byte[] blockOutput = cipher.update(curBlock.getInput());164byte[] expectedBlockOutput = curBlock.getOutput();165if (!Arrays.equals(blockOutput, expectedBlockOutput)) {166throw new RuntimeException("Blocks do not match at index "167+ blockIndex);168}169blockIndex++;170}171log("success");172supportedModes.add(test.getMode());173} catch (NoSuchAlgorithmException ex) {174log("algorithm not supported");175} catch (NoSuchProviderException | NoSuchPaddingException176| InvalidKeyException | InvalidAlgorithmParameterException ex) {177throw new RuntimeException(ex);178}179}180181private static boolean isComment(String line) {182return (line != null) && line.startsWith("//");183}184185private static TestVector readVector(BufferedReader in) throws IOException {186String line;187while (isComment(line = in.readLine())) {188// skip comment lines189}190if (line == null || line.isEmpty()) {191return null;192}193194TestVector newVector = new TestVector(line);195String numBlocksStr = in.readLine();196int numBlocks = Integer.parseInt(numBlocksStr);197for (int i = 0; i < numBlocks; i++) {198Block newBlock = new Block(in.readLine());199newVector.addBlock(newBlock);200}201202return newVector;203}204205private static void checkAllProviders() throws IOException {206File dataFile = new File(System.getProperty("test.src", "."),207VECTOR_FILE_NAME);208BufferedReader in = new BufferedReader(new FileReader(dataFile));209List<TestVector> allTests = new ArrayList<>();210TestVector newTest;211while ((newTest = readVector(in)) != null) {212allTests.add(newTest);213}214215for (Provider provider : Security.getProviders()) {216checkProvider(provider.getName(), allTests);217}218}219220private static void checkProvider(String providerName,221List<TestVector> allVectors)222throws IOException {223224for (TestVector curVector : allVectors) {225checkVector(providerName, curVector);226}227}228229/*230* This method helps ensure that the test is working properly by231* verifying that the test was able to check the test vectors for232* some of the modes of operation.233*/234private static void checkSupportedModes() {235for (Mode curMode : REQUIRED_MODES) {236if (!supportedModes.contains(curMode)) {237throw new RuntimeException(238"Mode not supported by any provider: " + curMode);239}240}241242}243244}245246247248