1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
/*
* Copyright (c) 2012, 2022, 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 java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
/**
* @test
* @bug 8041787 8288050
* @summary verify that Mac.update works with different size ByteBuffer
* @author Alexander Fomin
* @run main PBMacBuffer
*/
public class PBMacBuffer {
private final int LARGE_SIZE = 500000;
public static void main(String[] args) {
String[] PBMAC1Algorithms = {
"HmacPBESHA1",
"PBEWithHmacSHA1",
"PBEWithHmacSHA224",
"PBEWithHmacSHA256",
"PBEWithHmacSHA384",
"PBEWithHmacSHA512",
"PBEWithHmacSHA512/224",
"PBEWithHmacSHA512/256",
};
String[] PBKDF2Algorithms = {
"PBKDF2WithHmacSHA1",
"PBKDF2WithHmacSHA224",
"PBKDF2WithHmacSHA256",
"PBKDF2WithHmacSHA384",
"PBKDF2WithHmacSHA512",
"PBKDF2WithHmacSHA512/224",
"PBKDF2WithHmacSHA512/256",
};
PBMacBuffer testRunner = new PBMacBuffer();
boolean failed = false;
for (String thePBMacAlgo : PBMAC1Algorithms) {
for (String thePBKDF2Algo : PBKDF2Algorithms) {
System.out.println("Running test with " + thePBMacAlgo
+ " and " + thePBKDF2Algo + ":");
try {
if (!testRunner.doTest(thePBMacAlgo, thePBKDF2Algo)) {
failed = true;
}
} catch (NoSuchAlgorithmException | InvalidKeyException |
InvalidKeySpecException e) {
failed = true;
e.printStackTrace(System.out);
System.out.println("Test FAILED.");
}
}
}
if (failed) {
throw new RuntimeException("One or more tests failed....");
}
}
/**
* Tests Mac.update(ByteBuffer input) method. Three test cases are
* performed: - large ByteBuffer test case to test if the update() method
* process a large ByteBuffer correctly; - empty ByteBuffer test case to
* test if the update() method process an empty ByteBuffer correctly; - NULL
* ByteBuffer test case to test if the update() method throws expected
* IllegalArgumentException exception.
*
* @param theMacAlgo PBMAC algorithm to test
* @param thePBKDF2Algo PBKDF2 algorithm to test
* @return true - test passed; false - otherwise.
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
* @see javax.crypto.Mac
*/
protected boolean doTest(String theMacAlgo, String thePBKDF2Algo)
throws NoSuchAlgorithmException, InvalidKeyException,
InvalidKeySpecException {
// obtain a SecretKey using PBKDF2
SecretKey key = getSecretKey(thePBKDF2Algo);
// Instantiate Mac object and init it with a SecretKey
Mac theMac = Mac.getInstance(theMacAlgo);
theMac.init(key);
// Do large ByteBuffer test case
if (!largeByteBufferTest(theMac)) {
System.out.println("Large ByteBuffer test case failed.");
return false;
}
// Do empty ByteBuffer test case
if (!emptyByteBufferTest(theMac)) {
System.out.println("Empty ByteBuffer test case failed.");
return false;
}
// Do null ByteBuffer test case
if (!nullByteBufferTest(theMac)) {
System.out.println("NULL ByteBuffer test case failed.");
return false;
}
return true;
}
/**
* Large ByteBuffer test case. Generate random ByteBuffer of LARGE_SIZE
* size. Performs MAC operation with the given Mac object (theMac
* parameter).Verifies the assertion "Upon return, the buffer's position
* will be equal to its limit; its limit will not have changed".
*
* @param theMac MAC object to test.
* @return true - test case passed; false - otherwise;
*/
protected boolean largeByteBufferTest(Mac theMac) {
ByteBuffer buf = generateRandomByteBuffer(LARGE_SIZE);
int limitBefore = buf.limit();
theMac.update(buf);
theMac.doFinal();
int limitAfter = buf.limit();
int positonAfter = buf.position();
if (limitAfter != limitBefore) {
System.out.println("FAIL: Buffer's limit has been chenged.");
return false;
}
if (positonAfter != limitAfter) {
System.out.println("FAIL: "
+ "Buffer's position isn't equal to its limit");
return false;
}
return true;
}
/**
* Empty ByteBuffer test case. Generates an empty ByteBuffer. Perform MAC
* operation. No exceptions are expected.
*
* @param theMac
* @return true - test case pass; exception otherwise
*/
protected boolean emptyByteBufferTest(Mac theMac) {
ByteBuffer buf = generateRandomByteBuffer(0);
theMac.update(buf);
theMac.doFinal();
return true;
}
/**
* NULL ByteBuffer test case. Pass NULL ByteBuffer to Mac.update(ByteBuffer
* buffer) method. An IllegalArgumentException expected.
*
* @param theMac Mac object to test.
* @return true - test case pass; false - otherwise.
*/
protected boolean nullByteBufferTest(Mac theMac) {
try {
ByteBuffer buf = null;
theMac.update(buf);
theMac.doFinal();
} catch (IllegalArgumentException e) {
// expected exception has been thrown
return true;
}
System.out.println("FAIL: "
+ "IllegalArgumentException hasn't been thrown as expected");
return false;
}
/**
* Get SecretKey for the given PBKDF2 algorithm.
*
* @param thePBKDF2Algorithm - PBKDF2 algorithm
* @return SecretKey according to thePBKDF2Algorithm
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
protected SecretKey getSecretKey(String thePBKDF2Algorithm)
throws NoSuchAlgorithmException, InvalidKeySpecException {
// Prepare salt
byte[] salt = new byte[64]; // PKCS #5 v2.1 recommendation
new SecureRandom().nextBytes(salt);
// Generate secret key
PBEKeySpec pbeKeySpec = new PBEKeySpec(
"A #pwd# implied to be hidden!".toCharArray(),
salt, 1000, 128);
SecretKeyFactory keyFactory
= SecretKeyFactory.getInstance(thePBKDF2Algorithm);
return keyFactory.generateSecret(pbeKeySpec);
}
/**
* An utility method to generate a random ByteBuffer of the requested size.
*
* @param size size of the ByteBuffer.
* @return ByteBuffer populated random data;
*/
private ByteBuffer generateRandomByteBuffer(int size) {
// generate randome byte array
byte[] data = new byte[size];
new Random().nextBytes(data);
// create ByteBuffer
ByteBuffer bb = ByteBuffer.wrap(data);
return bb;
}
}
|