Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/PBE/PBMacDoFinalVsUpdate.java
41161 views
/*1* Copyright (c) 2012, 2014, 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 java.security.InvalidKeyException;24import java.security.NoSuchAlgorithmException;25import java.security.SecureRandom;26import java.security.spec.InvalidKeySpecException;27import javax.crypto.Mac;28import javax.crypto.SecretKey;29import javax.crypto.SecretKeyFactory;30import javax.crypto.spec.PBEKeySpec;3132/**33* @test34* @bug 804178735* @summary Check if doFinal and update operation result in same PBMac36* @author Alexander Fomin37* @run main PBMacDoFinalVsUpdate38*/39public class PBMacDoFinalVsUpdate {4041public static void main(String[] args) {42String[] PBMAC1Algorithms = {43"HmacPBESHA1",44"PBEWithHmacSHA1",45"PBEWithHmacSHA224",46"PBEWithHmacSHA256",47"PBEWithHmacSHA384",48"PBEWithHmacSHA512"49};5051String[] PBKDF2Algorithms = {52"PBKDF2WithHmacSHA1",53"PBKDF2WithHmacSHA224",54"PBKDF2WithHmacSHA256",55"PBKDF2WithHmacSHA384",56"PBKDF2WithHmacSHA512"57};5859PBMacDoFinalVsUpdate testRunner = new PBMacDoFinalVsUpdate();60boolean failed = false;6162for (String thePBMacAlgo : PBMAC1Algorithms) {6364for (String thePBKDF2Algo : PBKDF2Algorithms) {6566System.out.println("Running test with " + thePBMacAlgo67+ " and " + thePBKDF2Algo + ":");68try {69if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {70failed = true;71}72} catch (NoSuchAlgorithmException | InvalidKeyException |73InvalidKeySpecException e) {74failed = true;75e.printStackTrace(System.out);76System.out.println("Test FAILED.");77}78}79}8081if (failed) {82throw new RuntimeException("One or more tests failed....");83}84}8586/**87* Uses a random generator to initialize a message, instantiate a Mac object88* according to the given PBMAC1 algorithm, initialize the object with a89* SecretKey derived using PBKDF2 algorithm (see PKCS #5 v21, chapter 7.1),90* feed the message into the Mac object all at once and get the output MAC91* as result1. Reset the Mac object, chop the message into three pieces,92* feed into the Mac object sequentially, and get the output MAC as result2.93* Finally, compare result1 and result2 and see if they are the same.94*95* @param theMacAlgo PBMAC algorithm to test96* @param thePBKDF2Algo PBKDF2 algorithm to test97* @return true - the test is passed; false - otherwise.98* @throws NoSuchAlgorithmException99* @throws InvalidKeyException100* @throws InvalidKeySpecException101*/102protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)103throws NoSuchAlgorithmException, InvalidKeyException,104InvalidKeySpecException {105int OFFSET = 5;106107// Some message for which a MAC result will be calculated108byte[] plain = new byte[25];109new SecureRandom().nextBytes(plain);110111// Form tail - is one of the three pieces112byte[] tail = new byte[plain.length - OFFSET];113System.arraycopy(plain, OFFSET, tail, 0, tail.length);114115// Obtain a SecretKey using PBKDF2116SecretKey key = getSecretKey(thePBKDF2Algo);117118// Instantiate Mac object and init it with a SecretKey and calc result1119Mac theMac = Mac.getInstance(theMacAlgo);120theMac.init(key);121byte[] result1 = theMac.doFinal(plain);122123if (!isMacLengthExpected(theMacAlgo, result1.length)) {124return false;125}126127// Reset Mac and calculate result2128theMac.reset();129theMac.update(plain[0]);130theMac.update(plain, 1, OFFSET - 1);131byte[] result2 = theMac.doFinal(tail);132133// Return result134if (!java.util.Arrays.equals(result1, result2)) {135System.out.println("result1 and result2 are not the same:");136System.out.println("result1: " + dumpByteArray(result1));137System.out.println("result2: " + dumpByteArray(result2));138return false;139} else {140System.out.println("Resulted MAC with update and doFinal is same");141}142143return true;144}145146/**147* Get SecretKey for the given PBKDF2 algorithm.148*149* @param thePBKDF2Algorithm - PBKDF2 algorithm150* @return SecretKey according to thePBKDF2Algorithm151* @throws NoSuchAlgorithmException152* @throws InvalidKeySpecException153*/154protected SecretKey getSecretKey(String thePBKDF2Algorithm)155throws NoSuchAlgorithmException, InvalidKeySpecException {156// Prepare salt157byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation158new SecureRandom().nextBytes(salt);159160// Generate secret key161PBEKeySpec pbeKeySpec = new PBEKeySpec(162"A #pwd# implied to be hidden!".toCharArray(),163salt, 1000, 128);164SecretKeyFactory keyFactory165= SecretKeyFactory.getInstance(thePBKDF2Algorithm);166return keyFactory.generateSecret(pbeKeySpec);167}168169/**170* Check if the lengthToCheck is expected length for the given MACAlgo.171*172* @param MACAlgo PBMAC algorithm173* @param lengthToCheck the length of MAC need to check174* @return true - lengthToCheck is expected length for the MACAlgo; false -175* otherwise.176*/177protected boolean isMacLengthExpected(String MACAlgo, int lengthToCheck) {178java.util.regex.Pattern p = java.util.regex.Pattern.compile("(\\d+)",179java.util.regex.Pattern.CASE_INSENSITIVE);180java.util.regex.Matcher m = p.matcher(MACAlgo);181int val = 0;182183if (m.find()) {184val = Integer.parseInt(m.group(1));185}186187// HmacPBESHA1 should return MAC 20 byte length188if ((val == 1) && (lengthToCheck == 20)) {189return true;190}191192return (val / 8) == lengthToCheck;193}194195/**196* An utility method to dump a byte array for debug output.197*198* @param theByteArray the byte array to dump199* @return string representation of the theByteArray in Hex.200*/201protected String dumpByteArray(byte[] theByteArray) {202StringBuilder buf = new StringBuilder();203204for (byte b : theByteArray) {205buf.append(Integer.toHexString(b));206}207208return buf.toString();209}210211}212213214