Mercurial > hg > release > icedtea7-forest-2.6 > jdk
changeset 9705:1c3c301c99ba
6383200: PBE: need new algorithm support in password based encryption
Reviewed-by: valeriep
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/PBEKeyFactory.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBEKeyFactory.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -55,12 +55,25 @@ } static { - validTypes = new HashSet<String>(4); + validTypes = new HashSet<String>(17); validTypes.add("PBEWithMD5AndDES".toUpperCase()); validTypes.add("PBEWithSHA1AndDESede".toUpperCase()); validTypes.add("PBEWithSHA1AndRC2_40".toUpperCase()); + validTypes.add("PBEWithSHA1AndRC2_128".toUpperCase()); + validTypes.add("PBEWithSHA1AndRC4_40".toUpperCase()); + validTypes.add("PBEWithSHA1AndRC4_128".toUpperCase()); // Proprietary algorithm. validTypes.add("PBEWithMD5AndTripleDES".toUpperCase()); + validTypes.add("PBEWithHmacSHA1AndAES_128".toUpperCase()); + validTypes.add("PBEWithHmacSHA224AndAES_128".toUpperCase()); + validTypes.add("PBEWithHmacSHA256AndAES_128".toUpperCase()); + validTypes.add("PBEWithHmacSHA384AndAES_128".toUpperCase()); + validTypes.add("PBEWithHmacSHA512AndAES_128".toUpperCase()); + validTypes.add("PBEWithHmacSHA1AndAES_256".toUpperCase()); + validTypes.add("PBEWithHmacSHA224AndAES_256".toUpperCase()); + validTypes.add("PBEWithHmacSHA256AndAES_256".toUpperCase()); + validTypes.add("PBEWithHmacSHA384AndAES_256".toUpperCase()); + validTypes.add("PBEWithHmacSHA512AndAES_256".toUpperCase()); } public static final class PBEWithMD5AndDES @@ -84,6 +97,27 @@ } } + public static final class PBEWithSHA1AndRC2_128 + extends PBEKeyFactory { + public PBEWithSHA1AndRC2_128() { + super("PBEWithSHA1AndRC2_128"); + } + } + + public static final class PBEWithSHA1AndRC4_40 + extends PBEKeyFactory { + public PBEWithSHA1AndRC4_40() { + super("PBEWithSHA1AndRC4_40"); + } + } + + public static final class PBEWithSHA1AndRC4_128 + extends PBEKeyFactory { + public PBEWithSHA1AndRC4_128() { + super("PBEWithSHA1AndRC4_128"); + } + } + /* * Private proprietary algorithm for supporting JCEKS. */ @@ -94,6 +128,75 @@ } } + public static final class PBEWithHmacSHA1AndAES_128 + extends PBEKeyFactory { + public PBEWithHmacSHA1AndAES_128() { + super("PBEWithHmacSHA1AndAES_128"); + } + } + + public static final class PBEWithHmacSHA224AndAES_128 + extends PBEKeyFactory { + public PBEWithHmacSHA224AndAES_128() { + super("PBEWithHmacSHA224AndAES_128"); + } + } + + public static final class PBEWithHmacSHA256AndAES_128 + extends PBEKeyFactory { + public PBEWithHmacSHA256AndAES_128() { + super("PBEWithHmacSHA256AndAES_128"); + } + } + + public static final class PBEWithHmacSHA384AndAES_128 + extends PBEKeyFactory { + public PBEWithHmacSHA384AndAES_128() { + super("PBEWithHmacSHA384AndAES_128"); + } + } + + public static final class PBEWithHmacSHA512AndAES_128 + extends PBEKeyFactory { + public PBEWithHmacSHA512AndAES_128() { + super("PBEWithHmacSHA512AndAES_128"); + } + } + + public static final class PBEWithHmacSHA1AndAES_256 + extends PBEKeyFactory { + public PBEWithHmacSHA1AndAES_256() { + super("PBEWithHmacSHA1AndAES_256"); + } + } + + public static final class PBEWithHmacSHA224AndAES_256 + extends PBEKeyFactory { + public PBEWithHmacSHA224AndAES_256() { + super("PBEWithHmacSHA224AndAES_256"); + } + } + + public static final class PBEWithHmacSHA256AndAES_256 + extends PBEKeyFactory { + public PBEWithHmacSHA256AndAES_256() { + super("PBEWithHmacSHA256AndAES_256"); + } + } + + public static final class PBEWithHmacSHA384AndAES_256 + extends PBEKeyFactory { + public PBEWithHmacSHA384AndAES_256() { + super("PBEWithHmacSHA384AndAES_256"); + } + } + + public static final class PBEWithHmacSHA512AndAES_256 + extends PBEKeyFactory { + public PBEWithHmacSHA512AndAES_256() { + super("PBEWithHmacSHA512AndAES_256"); + } + } /** * Generates a <code>SecretKey</code> object from the provided key
--- a/src/share/classes/com/sun/crypto/provider/PBEParameters.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBEParameters.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -57,6 +57,9 @@ // the iteration count private int iCount = 0; + // the cipher parameter + private AlgorithmParameterSpec cipherParam = null; + protected void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException { @@ -66,6 +69,7 @@ } this.salt = ((PBEParameterSpec)paramSpec).getSalt().clone(); this.iCount = ((PBEParameterSpec)paramSpec).getIterationCount(); + this.cipherParam = ((PBEParameterSpec)paramSpec).getParameterSpec(); } protected void engineInit(byte[] encoded) @@ -102,7 +106,8 @@ throws InvalidParameterSpecException { if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) { - return paramSpec.cast(new PBEParameterSpec(this.salt, this.iCount)); + return paramSpec.cast( + new PBEParameterSpec(this.salt, this.iCount, this.cipherParam)); } else { throw new InvalidParameterSpecException ("Inappropriate parameter specification");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2002, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.crypto.provider; + +import java.security.*; +import java.security.spec.*; +import javax.crypto.*; +import javax.crypto.spec.*; + +/** + * This class represents password-based encryption as defined by the PKCS #5 + * standard. + * + * @author Jan Luehe + * + * + * @see javax.crypto.Cipher + */ +final class PBES1Core { + + // the encapsulated DES cipher + private CipherCore cipher; + private MessageDigest md; + private int blkSize; + private String algo = null; + private byte[] salt = null; + private int iCount = 10; + + /** + * Creates an instance of PBE Cipher using the specified CipherSpi + * instance. + * + */ + PBES1Core(String cipherAlg) throws NoSuchAlgorithmException, + NoSuchPaddingException { + algo = cipherAlg; + if (algo.equals("DES")) { + cipher = new CipherCore(new DESCrypt(), + DESConstants.DES_BLOCK_SIZE); + } else if (algo.equals("DESede")) { + + cipher = new CipherCore(new DESedeCrypt(), + DESConstants.DES_BLOCK_SIZE); + } else { + throw new NoSuchAlgorithmException("No Cipher implementation " + + "for PBEWithMD5And" + algo); + } + cipher.setMode("CBC"); + cipher.setPadding("PKCS5Padding"); + // get instance of MD5 + md = MessageDigest.getInstance("MD5"); + } + + /** + * Sets the mode of this cipher. This algorithm can only be run in CBC + * mode. + * + * @param mode the cipher mode + * + * @exception NoSuchAlgorithmException if the requested cipher mode is + * invalid + */ + void setMode(String mode) throws NoSuchAlgorithmException { + cipher.setMode(mode); + } + + /** + * Sets the padding mechanism of this cipher. This algorithm only uses + * PKCS #5 padding. + * + * @param padding the padding mechanism + * + * @exception NoSuchPaddingException if the requested padding mechanism + * is invalid + */ + void setPadding(String paddingScheme) throws NoSuchPaddingException { + cipher.setPadding(paddingScheme); + } + + /** + * Returns the block size (in bytes). + * + * @return the block size (in bytes) + */ + int getBlockSize() { + return DESConstants.DES_BLOCK_SIZE; + } + + /** + * Returns the length in bytes that an output buffer would need to be in + * order to hold the result of the next <code>update</code> or + * <code>doFinal</code> operation, given the input length + * <code>inputLen</code> (in bytes). + * + * <p>This call takes into account any unprocessed (buffered) data from a + * previous <code>update</code> call, and padding. + * + * <p>The actual output length of the next <code>update</code> or + * <code>doFinal</code> call may be smaller than the length returned by + * this method. + * + * @param inputLen the input length (in bytes) + * + * @return the required output buffer size (in bytes) + * + */ + int getOutputSize(int inputLen) { + return cipher.getOutputSize(inputLen); + } + + /** + * Returns the initialization vector (IV) in a new buffer. + * + * <p> This is useful in the case where a random IV has been created + * (see <a href = "#init">init</a>), + * or in the context of password-based encryption or + * decryption, where the IV is derived from a user-supplied password. + * + * @return the initialization vector in a new buffer, or null if the + * underlying algorithm does not use an IV, or if the IV has not yet + * been set. + */ + byte[] getIV() { + return cipher.getIV(); + } + + /** + * Returns the parameters used with this cipher. + * + * <p>The returned parameters may be the same that were used to initialize + * this cipher, or may contain the default set of parameters or a set of + * randomly generated parameters used by the underlying cipher + * implementation (provided that the underlying cipher implementation + * uses a default set of parameters or creates new parameters if it needs + * parameters but was not initialized with any). + * + * @return the parameters used with this cipher, or null if this cipher + * does not use any parameters. + */ + AlgorithmParameters getParameters() { + AlgorithmParameters params = null; + if (salt == null) { + salt = new byte[8]; + SunJCE.RANDOM.nextBytes(salt); + } + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount); + try { + params = AlgorithmParameters.getInstance("PBEWithMD5And" + + (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), + SunJCE.getInstance()); + params.init(pbeSpec); + } catch (NoSuchAlgorithmException nsae) { + // should never happen + throw new RuntimeException("SunJCE called, but not configured"); + } catch (InvalidParameterSpecException ipse) { + // should never happen + throw new RuntimeException("PBEParameterSpec not supported"); + } + return params; + } + + /** + * Initializes this cipher with a key, a set of + * algorithm parameters, and a source of randomness. + * The cipher is initialized for one of the following four operations: + * encryption, decryption, key wrapping or key unwrapping, depending on + * the value of <code>opmode</code>. + * + * <p>If this cipher (including its underlying feedback or padding scheme) + * requires any random bytes, it will get them from <code>random</code>. + * + * @param opmode the operation mode of this cipher (this is one of + * the following: + * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>), + * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) + * @param key the encryption key + * @param params the algorithm parameters + * @param random the source of randomness + * + * @exception InvalidKeyException if the given key is inappropriate for + * initializing this cipher + * @exception InvalidAlgorithmParameterException if the given algorithm + * parameters are inappropriate for this cipher + */ + void init(int opmode, Key key, AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + if (((opmode == Cipher.DECRYPT_MODE) || + (opmode == Cipher.UNWRAP_MODE)) && (params == null)) { + throw new InvalidAlgorithmParameterException("Parameters " + + "missing"); + } + if ((key == null) || + (key.getEncoded() == null) || + !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { + throw new InvalidKeyException("Missing password"); + } + + if (params == null) { + // create random salt and use default iteration count + salt = new byte[8]; + random.nextBytes(salt); + } else { + if (!(params instanceof PBEParameterSpec)) { + throw new InvalidAlgorithmParameterException + ("Wrong parameter type: PBE expected"); + } + salt = ((PBEParameterSpec) params).getSalt(); + // salt must be 8 bytes long (by definition) + if (salt.length != 8) { + throw new InvalidAlgorithmParameterException + ("Salt must be 8 bytes long"); + } + iCount = ((PBEParameterSpec) params).getIterationCount(); + if (iCount <= 0) { + throw new InvalidAlgorithmParameterException + ("IterationCount must be a positive number"); + } + } + + byte[] derivedKey = deriveCipherKey(key); + // use all but the last 8 bytes as the key value + SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0, + derivedKey.length-8, algo); + // use the last 8 bytes as the IV + IvParameterSpec ivSpec = new IvParameterSpec(derivedKey, + derivedKey.length-8, + 8); + // initialize the underlying cipher + cipher.init(opmode, cipherKey, ivSpec, random); + } + + private byte[] deriveCipherKey(Key key) { + + byte[] result = null; + byte[] passwdBytes = key.getEncoded(); + + if (algo.equals("DES")) { + // P || S (password concatenated with salt) + byte[] concat = new byte[CipherCore.addExact(passwdBytes.length, salt.length)]; + System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length); + java.util.Arrays.fill(passwdBytes, (byte)0x00); + System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length); + + // digest P || S with c iterations + byte[] toBeHashed = concat; + for (int i = 0; i < iCount; i++) { + md.update(toBeHashed); + toBeHashed = md.digest(); // this resets the digest + } + java.util.Arrays.fill(concat, (byte)0x00); + result = toBeHashed; + } else if (algo.equals("DESede")) { + // if the 2 salt halves are the same, invert one of them + int i; + for (i=0; i<4; i++) { + if (salt[i] != salt[i+4]) + break; + } + if (i==4) { // same, invert 1st half + for (i=0; i<2; i++) { + byte tmp = salt[i]; + salt[i] = salt[3-i]; + salt[3-i] = tmp; + } + } + + // Now digest each half (concatenated with password). For each + // half, go through the loop as many times as specified by the + // iteration count parameter (inner for loop). + // Concatenate the output from each digest round with the + // password, and use the result as the input to the next digest + // operation. + byte[] kBytes = null; + IvParameterSpec iv = null; + byte[] toBeHashed = null; + result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN + + DESConstants.DES_BLOCK_SIZE]; + for (i = 0; i < 2; i++) { + toBeHashed = new byte[salt.length/2]; + System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0, + toBeHashed.length); + for (int j=0; j < iCount; j++) { + md.update(toBeHashed); + md.update(passwdBytes); + toBeHashed = md.digest(); // this resets the digest + } + System.arraycopy(toBeHashed, 0, result, i*16, + toBeHashed.length); + } + } + return result; + } + + void init(int opmode, Key key, AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + PBEParameterSpec pbeSpec = null; + if (params != null) { + try { + pbeSpec = params.getParameterSpec(PBEParameterSpec.class); + } catch (InvalidParameterSpecException ipse) { + throw new InvalidAlgorithmParameterException("Wrong parameter " + + "type: PBE " + + "expected"); + } + } + init(opmode, key, pbeSpec, random); + } + + /** + * Continues a multiple-part encryption or decryption operation + * (depending on how this cipher was initialized), processing another data + * part. + * + * <p>The first <code>inputLen</code> bytes in the <code>input</code> + * buffer, starting at <code>inputOffset</code>, are processed, and the + * result is stored in a new buffer. + * + * @param input the input buffer + * @param inputOffset the offset in <code>input</code> where the input + * starts + * @param inputLen the input length + * + * @return the new buffer with the result + * + */ + byte[] update(byte[] input, int inputOffset, int inputLen) { + return cipher.update(input, inputOffset, inputLen); + } + + /** + * Continues a multiple-part encryption or decryption operation + * (depending on how this cipher was initialized), processing another data + * part. + * + * <p>The first <code>inputLen</code> bytes in the <code>input</code> + * buffer, starting at <code>inputOffset</code>, are processed, and the + * result is stored in the <code>output</code> buffer, starting at + * <code>outputOffset</code>. + * + * @param input the input buffer + * @param inputOffset the offset in <code>input</code> where the input + * starts + * @param inputLen the input length + * @param output the buffer for the result + * @param outputOffset the offset in <code>output</code> where the result + * is stored + * + * @return the number of bytes stored in <code>output</code> + * + * @exception ShortBufferException if the given output buffer is too small + * to hold the result + */ + int update(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException { + return cipher.update(input, inputOffset, inputLen, + output, outputOffset); + } + + /** + * Encrypts or decrypts data in a single-part operation, + * or finishes a multiple-part operation. + * The data is encrypted or decrypted, depending on how this cipher was + * initialized. + * + * <p>The first <code>inputLen</code> bytes in the <code>input</code> + * buffer, starting at <code>inputOffset</code>, and any input bytes that + * may have been buffered during a previous <code>update</code> operation, + * are processed, with padding (if requested) being applied. + * The result is stored in a new buffer. + * + * <p>The cipher is reset to its initial state (uninitialized) after this + * call. + * + * @param input the input buffer + * @param inputOffset the offset in <code>input</code> where the input + * starts + * @param inputLen the input length + * + * @return the new buffer with the result + * + * @exception IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size + * @exception BadPaddingException if decrypting and padding is chosen, + * but the last input data does not have proper padding bytes. + */ + byte[] doFinal(byte[] input, int inputOffset, int inputLen) + throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(input, inputOffset, inputLen); + } + + /** + * Encrypts or decrypts data in a single-part operation, + * or finishes a multiple-part operation. + * The data is encrypted or decrypted, depending on how this cipher was + * initialized. + * + * <p>The first <code>inputLen</code> bytes in the <code>input</code> + * buffer, starting at <code>inputOffset</code>, and any input bytes that + * may have been buffered during a previous <code>update</code> operation, + * are processed, with padding (if requested) being applied. + * The result is stored in the <code>output</code> buffer, starting at + * <code>outputOffset</code>. + * + * <p>The cipher is reset to its initial state (uninitialized) after this + * call. + * + * @param input the input buffer + * @param inputOffset the offset in <code>input</code> where the input + * starts + * @param inputLen the input length + * @param output the buffer for the result + * @param outputOffset the offset in <code>output</code> where the result + * is stored + * + * @return the number of bytes stored in <code>output</code> + * + * @exception IllegalBlockSizeException if this cipher is a block cipher, + * no padding has been requested (only in encryption mode), and the total + * input length of the data processed by this cipher is not a multiple of + * block size + * @exception ShortBufferException if the given output buffer is too small + * to hold the result + * @exception BadPaddingException if decrypting and padding is chosen, + * but the last input data does not have proper padding bytes. + */ + int doFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return cipher.doFinal(input, inputOffset, inputLen, + output, outputOffset); + } + + /** + * Wrap a key. + * + * @param key the key to be wrapped. + * + * @return the wrapped key. + * + * @exception IllegalBlockSizeException if this cipher is a block + * cipher, no padding has been requested, and the length of the + * encoding of the key to be wrapped is not a + * multiple of the block size. + * + * @exception InvalidKeyException if it is impossible or unsafe to + * wrap the key with this cipher (e.g., a hardware protected key is + * being passed to a software only cipher). + */ + byte[] wrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException { + byte[] result = null; + + try { + byte[] encodedKey = key.getEncoded(); + if ((encodedKey == null) || (encodedKey.length == 0)) { + throw new InvalidKeyException("Cannot get an encoding of " + + "the key to be wrapped"); + } + + result = doFinal(encodedKey, 0, encodedKey.length); + } catch (BadPaddingException e) { + // Should never happen + } + + return result; + } + + /** + * Unwrap a previously wrapped key. + * + * @param wrappedKey the key to be unwrapped. + * + * @param wrappedKeyAlgorithm the algorithm the wrapped key is for. + * + * @param wrappedKeyType the type of the wrapped key. + * This is one of <code>Cipher.SECRET_KEY</code>, + * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>. + * + * @return the unwrapped key. + * + * @exception NoSuchAlgorithmException if no installed providers + * can create keys of type <code>wrappedKeyType</code> for the + * <code>wrappedKeyAlgorithm</code>. + * + * @exception InvalidKeyException if <code>wrappedKey</code> does not + * represent a wrapped key of type <code>wrappedKeyType</code> for + * the <code>wrappedKeyAlgorithm</code>. + */ + Key unwrap(byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException { + byte[] encodedKey; + try { + encodedKey = doFinal(wrappedKey, 0, wrappedKey.length); + } catch (BadPaddingException ePadding) { + throw new InvalidKeyException("The wrapped key is not padded " + + "correctly"); + } catch (IllegalBlockSizeException eBlockSize) { + throw new InvalidKeyException("The wrapped key does not have " + + "the correct length"); + } + return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBES2Core.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.crypto.provider; + +import java.io.UnsupportedEncodingException; +import java.security.*; +import java.security.spec.*; +import javax.crypto.*; +import javax.crypto.interfaces.*; +import javax.crypto.spec.*; + +/** + * This class represents password-based encryption as defined by the PKCS #5 + * standard. + * These algorithms implement PBE with HmacSHA1/HmacSHA2-family and AES-CBC. + * Padding is done as described in PKCS #5. + * + * @author Jan Luehe + * + * + * @see javax.crypto.Cipher + */ +abstract class PBES2Core extends CipherSpi { + + private static final int DEFAULT_SALT_LENGTH = 20; + private static final int DEFAULT_COUNT = 4096; + + // the encapsulated cipher + private final CipherCore cipher; + private final int keyLength; // in bits + private final int blkSize; // in bits + private final PBKDF2Core kdf; + private final String pbeAlgo; + private final String cipherAlgo; + private int iCount = DEFAULT_COUNT; + private byte[] salt = null; + private IvParameterSpec ivSpec = null; + + /** + * Creates an instance of PBE Scheme 2 according to the selected + * password-based key derivation function and encryption scheme. + */ + PBES2Core(String kdfAlgo, String cipherAlgo, int keySize) + throws NoSuchAlgorithmException, NoSuchPaddingException { + + this.cipherAlgo = cipherAlgo; + keyLength = keySize * 8; + pbeAlgo = "PBEWith" + kdfAlgo + "And" + cipherAlgo + "_" + keyLength; + + if (cipherAlgo.equals("AES")) { + blkSize = AESConstants.AES_BLOCK_SIZE; + cipher = new CipherCore(new AESCrypt(), blkSize); + + switch(kdfAlgo) { + case "HmacSHA1": + kdf = new PBKDF2Core.HmacSHA1(); + break; + case "HmacSHA224": + kdf = new PBKDF2Core.HmacSHA224(); + break; + case "HmacSHA256": + kdf = new PBKDF2Core.HmacSHA256(); + break; + case "HmacSHA384": + kdf = new PBKDF2Core.HmacSHA384(); + break; + case "HmacSHA512": + kdf = new PBKDF2Core.HmacSHA512(); + break; + default: + throw new NoSuchAlgorithmException( + "No Cipher implementation for " + kdfAlgo); + } + } else { + throw new NoSuchAlgorithmException("No Cipher implementation for " + + pbeAlgo); + } + cipher.setMode("CBC"); + cipher.setPadding("PKCS5Padding"); + } + + protected void engineSetMode(String mode) throws NoSuchAlgorithmException { + if ((mode != null) && (!mode.equalsIgnoreCase("CBC"))) { + throw new NoSuchAlgorithmException("Invalid cipher mode: " + mode); + } + } + + protected void engineSetPadding(String paddingScheme) + throws NoSuchPaddingException { + if ((paddingScheme != null) && + (!paddingScheme.equalsIgnoreCase("PKCS5Padding"))) { + throw new NoSuchPaddingException("Invalid padding scheme: " + + paddingScheme); + } + } + + protected int engineGetBlockSize() { + return blkSize; + } + + protected int engineGetOutputSize(int inputLen) { + return cipher.getOutputSize(inputLen); + } + + protected byte[] engineGetIV() { + return cipher.getIV(); + } + + protected AlgorithmParameters engineGetParameters() { + AlgorithmParameters params = null; + if (salt == null) { + // generate random salt and use default iteration count + salt = new byte[DEFAULT_SALT_LENGTH]; + SunJCE.RANDOM.nextBytes(salt); + iCount = DEFAULT_COUNT; + } + if (ivSpec == null) { + // generate random IV + byte[] ivBytes = new byte[blkSize]; + SunJCE.RANDOM.nextBytes(ivBytes); + ivSpec = new IvParameterSpec(ivBytes); + } + PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec); + try { + params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE"); + } catch (NoSuchAlgorithmException nsae) { + // should never happen + throw new RuntimeException("SunJCE called, but not configured"); + } catch (NoSuchProviderException nspe) { + // should never happen + throw new RuntimeException("SunJCE called, but not configured"); + } + try { + params.init(pbeSpec); + } catch (InvalidParameterSpecException ipse) { + // should never happen + throw new RuntimeException("PBEParameterSpec not supported"); + } + return params; + } + + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException { + try { + engineInit(opmode, key, (AlgorithmParameterSpec) null, random); + } catch (InvalidAlgorithmParameterException ie) { + InvalidKeyException ike = + new InvalidKeyException("requires PBE parameters"); + ike.initCause(ie); + throw ike; + } + } + + protected void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + + if ((key == null) || + (key.getEncoded() == null) || + !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { + throw new InvalidKeyException("Missing password"); + } + + // TBD: consolidate the salt, ic and IV parameter checks below + + // Extract salt and iteration count from the key, if present + if (key instanceof javax.crypto.interfaces.PBEKey) { + salt = ((javax.crypto.interfaces.PBEKey)key).getSalt(); + if (salt != null && salt.length < 8) { + throw new InvalidAlgorithmParameterException( + "Salt must be at least 8 bytes long"); + } + iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount(); + if (iCount == 0) { + iCount = DEFAULT_COUNT; + } else if (iCount < 0) { + throw new InvalidAlgorithmParameterException( + "Iteration count must be a positive number"); + } + } + + // Extract salt, iteration count and IV from the params, if present + if (params == null) { + if (salt == null) { + // generate random salt and use default iteration count + salt = new byte[DEFAULT_SALT_LENGTH]; + random.nextBytes(salt); + iCount = DEFAULT_COUNT; + } + if ((opmode == Cipher.ENCRYPT_MODE) || + (opmode == Cipher.WRAP_MODE)) { + // generate random IV + byte[] ivBytes = new byte[blkSize]; + random.nextBytes(ivBytes); + ivSpec = new IvParameterSpec(ivBytes); + } + } else { + if (!(params instanceof PBEParameterSpec)) { + throw new InvalidAlgorithmParameterException + ("Wrong parameter type: PBE expected"); + } + // salt and iteration count from the params take precedence + byte[] specSalt = ((PBEParameterSpec) params).getSalt(); + if (specSalt != null && specSalt.length < 8) { + throw new InvalidAlgorithmParameterException( + "Salt must be at least 8 bytes long"); + } + salt = specSalt; + int specICount = ((PBEParameterSpec) params).getIterationCount(); + if (specICount == 0) { + specICount = DEFAULT_COUNT; + } else if (specICount < 0) { + throw new InvalidAlgorithmParameterException( + "Iteration count must be a positive number"); + } + iCount = specICount; + + AlgorithmParameterSpec specParams = + ((PBEParameterSpec) params).getParameterSpec(); + if (specParams != null) { + if (specParams instanceof IvParameterSpec) { + ivSpec = (IvParameterSpec)specParams; + } else { + throw new InvalidAlgorithmParameterException( + "Wrong parameter type: IV expected"); + } + } else if ((opmode == Cipher.ENCRYPT_MODE) || + (opmode == Cipher.WRAP_MODE)) { + // generate random IV + byte[] ivBytes = new byte[blkSize]; + random.nextBytes(ivBytes); + ivSpec = new IvParameterSpec(ivBytes); + } else { + throw new InvalidAlgorithmParameterException( + "Missing parameter type: IV expected"); + } + } + + SecretKeySpec cipherKey = null; + byte[] derivedKey = null; + byte[] passwdBytes = key.getEncoded(); + char[] passwdChars = new char[passwdBytes.length]; + + for (int i=0; i<passwdChars.length; i++) + passwdChars[i] = (char) (passwdBytes[i] & 0x7f); + + PBEKeySpec pbeSpec = + new PBEKeySpec(passwdChars, salt, iCount, blkSize * 8); + // password char[] was cloned in PBEKeySpec constructor, + // so we can zero it out here + java.util.Arrays.fill(passwdChars, ' '); + java.util.Arrays.fill(passwdBytes, (byte)0x00); + + SecretKey s = null; + + try { + s = kdf.engineGenerateSecret(pbeSpec); + + } catch (InvalidKeySpecException ikse) { + InvalidKeyException ike = + new InvalidKeyException("Cannot construct PBE key"); + ike.initCause(ikse); + throw ike; + } + derivedKey = s.getEncoded(); + cipherKey = new SecretKeySpec(derivedKey, cipherAlgo); + + // initialize the underlying cipher + cipher.init(opmode, cipherKey, ivSpec, random); + } + + protected void engineInit(int opmode, Key key, AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + AlgorithmParameterSpec pbeSpec = null; + if (params != null) { + try { + pbeSpec = params.getParameterSpec(PBEParameterSpec.class); + } catch (InvalidParameterSpecException ipse) { + throw new InvalidAlgorithmParameterException( + "Wrong parameter type: PBE expected"); + } + } + engineInit(opmode, key, pbeSpec, random); + } + + protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { + return cipher.update(input, inputOffset, inputLen); + } + + protected int engineUpdate(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException { + return cipher.update(input, inputOffset, inputLen, + output, outputOffset); + } + + protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) + throws IllegalBlockSizeException, BadPaddingException { + return cipher.doFinal(input, inputOffset, inputLen); + } + + protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return cipher.doFinal(input, inputOffset, inputLen, + output, outputOffset); + } + + protected int engineGetKeySize(Key key) throws InvalidKeyException { + return keyLength; + } + + protected byte[] engineWrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException { + return cipher.wrap(key); + } + + protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException { + byte[] encodedKey; + return cipher.unwrap(wrappedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } + + public static final class HmacSHA1AndAES_128 extends PBES2Core { + public HmacSHA1AndAES_128() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA1", "AES", 16); + } + } + + public static final class HmacSHA224AndAES_128 extends PBES2Core { + public HmacSHA224AndAES_128() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA224", "AES", 16); + } + } + + public static final class HmacSHA256AndAES_128 extends PBES2Core { + public HmacSHA256AndAES_128() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA256", "AES", 16); + } + } + + public static final class HmacSHA384AndAES_128 extends PBES2Core { + public HmacSHA384AndAES_128() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA384", "AES", 16); + } + } + + public static final class HmacSHA512AndAES_128 extends PBES2Core { + public HmacSHA512AndAES_128() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA512", "AES", 16); + } + } + + public static final class HmacSHA1AndAES_256 extends PBES2Core { + public HmacSHA1AndAES_256() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA1", "AES", 32); + } + } + + public static final class HmacSHA224AndAES_256 extends PBES2Core { + public HmacSHA224AndAES_256() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA224", "AES", 32); + } + } + + public static final class HmacSHA256AndAES_256 extends PBES2Core { + public HmacSHA256AndAES_256() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA256", "AES", 32); + } + } + + public static final class HmacSHA384AndAES_256 extends PBES2Core { + public HmacSHA384AndAES_256() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA384", "AES", 32); + } + } + + public static final class HmacSHA512AndAES_256 extends PBES2Core { + public HmacSHA512AndAES_256() + throws NoSuchAlgorithmException, NoSuchPaddingException { + super("HmacSHA512", "AES", 32); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBES2Parameters.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.crypto.provider; + +import java.io.*; +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.AlgorithmParametersSpi; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEParameterSpec; +import sun.misc.HexDumpEncoder; +import sun.security.util.*; + +/** + * This class implements the parameter set used with password-based + * encryption scheme 2 (PBES2), which is defined in PKCS#5 as follows: + * + * <pre> + * -- PBES2 + * + * PBES2Algorithms ALGORITHM-IDENTIFIER ::= + * { {PBES2-params IDENTIFIED BY id-PBES2}, ...} + * + * id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} + * + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } + * + * PBES2-KDFs ALGORITHM-IDENTIFIER ::= + * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } + * + * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } + * + * -- PBKDF2 + * + * PBKDF2Algorithms ALGORITHM-IDENTIFIER ::= + * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ...} + * + * id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} + * + * PBKDF2-params ::= SEQUENCE { + * salt CHOICE { + * specified OCTET STRING, + * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} + * }, + * iterationCount INTEGER (1..MAX), + * keyLength INTEGER (1..MAX) OPTIONAL, + * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 + * } + * + * PBKDF2-SaltSources ALGORITHM-IDENTIFIER ::= { ... } + * + * PBKDF2-PRFs ALGORITHM-IDENTIFIER ::= { + * {NULL IDENTIFIED BY id-hmacWithSHA1} | + * {NULL IDENTIFIED BY id-hmacWithSHA224} | + * {NULL IDENTIFIED BY id-hmacWithSHA256} | + * {NULL IDENTIFIED BY id-hmacWithSHA384} | + * {NULL IDENTIFIED BY id-hmacWithSHA512}, ... } + * + * algid-hmacWithSHA1 AlgorithmIdentifier {{PBKDF2-PRFs}} ::= + * {algorithm id-hmacWithSHA1, parameters NULL : NULL} + * + * id-hmacWithSHA1 OBJECT IDENTIFIER ::= {digestAlgorithm 7} + * + * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } + * + * </pre> + */ + +abstract class PBES2Parameters extends AlgorithmParametersSpi { + + private static final int pkcs5PBKDF2[] = + {1, 2, 840, 113549, 1, 5, 12}; + private static final int pkcs5PBES2[] = + {1, 2, 840, 113549, 1, 5, 13}; + private static final int hmacWithSHA1[] = + {1, 2, 840, 113549, 2, 7}; + private static final int hmacWithSHA224[] = + {1, 2, 840, 113549, 2, 8}; + private static final int hmacWithSHA256[] = + {1, 2, 840, 113549, 2, 9}; + private static final int hmacWithSHA384[] = + {1, 2, 840, 113549, 2, 10}; + private static final int hmacWithSHA512[] = + {1, 2, 840, 113549, 2, 11}; + private static final int aes128CBC[] = + {2, 16, 840, 1, 101, 3, 4, 1, 2}; + private static final int aes192CBC[] = + {2, 16, 840, 1, 101, 3, 4, 1, 22}; + private static final int aes256CBC[] = + {2, 16, 840, 1, 101, 3, 4, 1, 42}; + + private static ObjectIdentifier pkcs5PBKDF2_OID; + private static ObjectIdentifier pkcs5PBES2_OID; + private static ObjectIdentifier hmacWithSHA1_OID; + private static ObjectIdentifier hmacWithSHA224_OID; + private static ObjectIdentifier hmacWithSHA256_OID; + private static ObjectIdentifier hmacWithSHA384_OID; + private static ObjectIdentifier hmacWithSHA512_OID; + private static ObjectIdentifier aes128CBC_OID; + private static ObjectIdentifier aes192CBC_OID; + private static ObjectIdentifier aes256CBC_OID; + + static { + try { + pkcs5PBKDF2_OID = new ObjectIdentifier(pkcs5PBKDF2); + pkcs5PBES2_OID = new ObjectIdentifier(pkcs5PBES2); + hmacWithSHA1_OID = new ObjectIdentifier(hmacWithSHA1); + hmacWithSHA224_OID = new ObjectIdentifier(hmacWithSHA224); + hmacWithSHA256_OID = new ObjectIdentifier(hmacWithSHA256); + hmacWithSHA384_OID = new ObjectIdentifier(hmacWithSHA384); + hmacWithSHA512_OID = new ObjectIdentifier(hmacWithSHA512); + aes128CBC_OID = new ObjectIdentifier(aes128CBC); + aes192CBC_OID = new ObjectIdentifier(aes192CBC); + aes256CBC_OID = new ObjectIdentifier(aes256CBC); + } catch (IOException ioe) { + // should not happen + } + } + + // the PBES2 algorithm name + private String pbes2AlgorithmName = null; + + // the salt + private byte[] salt = null; + + // the iteration count + private int iCount = 0; + + // the cipher parameter + private AlgorithmParameterSpec cipherParam = null; + + // the key derivation function (default is HmacSHA1) + private ObjectIdentifier kdfAlgo_OID = hmacWithSHA1_OID; + + // the encryption function + private ObjectIdentifier cipherAlgo_OID = null; + + // the cipher keysize (in bits) + private int keysize = -1; + + PBES2Parameters() { + // KDF, encryption & keysize values are set later, in engineInit(byte[]) + } + + PBES2Parameters(String pbes2AlgorithmName) throws NoSuchAlgorithmException { + int and; + String kdfAlgo = null; + String cipherAlgo = null; + + // Extract the KDF and encryption algorithm names + this.pbes2AlgorithmName = pbes2AlgorithmName; + if (pbes2AlgorithmName.startsWith("PBEWith") && + (and = pbes2AlgorithmName.indexOf("And", 7 + 1)) > 0) { + kdfAlgo = pbes2AlgorithmName.substring(7, and); + cipherAlgo = pbes2AlgorithmName.substring(and + 3); + + // Check for keysize + int underscore; + if ((underscore = cipherAlgo.indexOf('_')) > 0) { + int slash; + if ((slash = cipherAlgo.indexOf('/', underscore + 1)) > 0) { + keysize = + Integer.parseInt(cipherAlgo.substring(underscore + 1, + slash)); + } else { + keysize = + Integer.parseInt(cipherAlgo.substring(underscore + 1)); + } + cipherAlgo = cipherAlgo.substring(0, underscore); + } + } else { + throw new NoSuchAlgorithmException("No crypto implementation for " + + pbes2AlgorithmName); + } + + switch (kdfAlgo) { + case "HmacSHA1": + kdfAlgo_OID = hmacWithSHA1_OID; + break; + case "HmacSHA224": + kdfAlgo_OID = hmacWithSHA224_OID; + break; + case "HmacSHA256": + kdfAlgo_OID = hmacWithSHA256_OID; + break; + case "HmacSHA384": + kdfAlgo_OID = hmacWithSHA384_OID; + break; + case "HmacSHA512": + kdfAlgo_OID = hmacWithSHA512_OID; + break; + default: + throw new NoSuchAlgorithmException( + "No crypto implementation for " + kdfAlgo); + } + + if (cipherAlgo.equals("AES")) { + this.keysize = keysize; + switch (keysize) { + case 128: + cipherAlgo_OID = aes128CBC_OID; + break; + case 256: + cipherAlgo_OID = aes256CBC_OID; + break; + default: + throw new NoSuchAlgorithmException( + "No Cipher implementation for " + keysize + "-bit " + + cipherAlgo); + } + } else { + throw new NoSuchAlgorithmException("No Cipher implementation for " + + cipherAlgo); + } + } + + protected void engineInit(AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException + { + if (!(paramSpec instanceof PBEParameterSpec)) { + throw new InvalidParameterSpecException + ("Inappropriate parameter specification"); + } + this.salt = ((PBEParameterSpec)paramSpec).getSalt().clone(); + this.iCount = ((PBEParameterSpec)paramSpec).getIterationCount(); + this.cipherParam = ((PBEParameterSpec)paramSpec).getParameterSpec(); + } + + protected void engineInit(byte[] encoded) + throws IOException + { + String kdfAlgo = null; + String cipherAlgo = null; + + DerValue pBES2Algorithms = new DerValue(encoded); + if (pBES2Algorithms.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + if (!pkcs5PBES2_OID.equals(pBES2Algorithms.data.getOID())) { + throw new IOException("PBE parameter parsing error: " + + "expecting the object identifier for PBES2"); + } + if (pBES2Algorithms.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + + DerValue pBES2_params = pBES2Algorithms.data.getDerValue(); + if (pBES2_params.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + kdfAlgo = parseKDF(pBES2_params.data.getDerValue()); + + if (pBES2_params.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + cipherAlgo = parseES(pBES2_params.data.getDerValue()); + + pbes2AlgorithmName = new StringBuilder().append("PBEWith") + .append(kdfAlgo).append("And").append(cipherAlgo).toString(); + } + + private String parseKDF(DerValue keyDerivationFunc) throws IOException { + String kdfAlgo = null; + + if (!pkcs5PBKDF2_OID.equals(keyDerivationFunc.data.getOID())) { + throw new IOException("PBE parameter parsing error: " + + "expecting the object identifier for PBKDF2"); + } + if (keyDerivationFunc.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + DerValue pBKDF2_params = keyDerivationFunc.data.getDerValue(); + if (pBKDF2_params.tag != DerValue.tag_Sequence) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 SEQUENCE tag"); + } + DerValue specified = pBKDF2_params.data.getDerValue(); + // the 'specified' ASN.1 CHOICE for 'salt' is supported + if (specified.tag == DerValue.tag_OctetString) { + salt = specified.getOctetString(); + } else { + // the 'otherSource' ASN.1 CHOICE for 'salt' is not supported + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 OCTET STRING tag"); + } + iCount = pBKDF2_params.data.getInteger(); + DerValue keyLength = pBKDF2_params.data.getDerValue(); + if (keyLength.tag == DerValue.tag_Integer) { + keysize = keyLength.getInteger() * 8; // keysize (in bits) + } + if (pBKDF2_params.tag == DerValue.tag_Sequence) { + DerValue prf = pBKDF2_params.data.getDerValue(); + kdfAlgo_OID = prf.data.getOID(); + if (hmacWithSHA1_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA1"; + } else if (hmacWithSHA224_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA224"; + } else if (hmacWithSHA256_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA256"; + } else if (hmacWithSHA384_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA384"; + } else if (hmacWithSHA512_OID.equals(kdfAlgo_OID)) { + kdfAlgo = "HmacSHA512"; + } else { + throw new IOException("PBE parameter parsing error: " + + "expecting the object identifier for a HmacSHA key " + + "derivation function"); + } + if (prf.data.available() != 0) { + // parameter is 'NULL' for all HmacSHA KDFs + DerValue parameter = prf.data.getDerValue(); + if (parameter.tag != DerValue.tag_Null) { + throw new IOException("PBE parameter parsing error: " + + "not an ASN.1 NULL tag"); + } + } + } + + return kdfAlgo; + } + + private String parseES(DerValue encryptionScheme) throws IOException { + String cipherAlgo = null; + + cipherAlgo_OID = encryptionScheme.data.getOID(); + if (aes128CBC_OID.equals(cipherAlgo_OID)) { + cipherAlgo = "AES_128"; + // parameter is AES-IV 'OCTET STRING (SIZE(16))' + cipherParam = + new IvParameterSpec(encryptionScheme.data.getOctetString()); + keysize = 128; + } else if (aes256CBC_OID.equals(cipherAlgo_OID)) { + cipherAlgo = "AES_256"; + // parameter is AES-IV 'OCTET STRING (SIZE(16))' + cipherParam = + new IvParameterSpec(encryptionScheme.data.getOctetString()); + keysize = 256; + } else { + throw new IOException("PBE parameter parsing error: " + + "expecting the object identifier for AES cipher"); + } + + return cipherAlgo; + } + + protected void engineInit(byte[] encoded, String decodingMethod) + throws IOException + { + engineInit(encoded); + } + + protected <T extends AlgorithmParameterSpec> + T engineGetParameterSpec(Class<T> paramSpec) + throws InvalidParameterSpecException + { + if (PBEParameterSpec.class.isAssignableFrom(paramSpec)) { + return paramSpec.cast( + new PBEParameterSpec(this.salt, this.iCount, this.cipherParam)); + } else { + throw new InvalidParameterSpecException + ("Inappropriate parameter specification"); + } + } + + protected byte[] engineGetEncoded() throws IOException { + DerOutputStream out = new DerOutputStream(); + DerOutputStream pBES2Algorithms = new DerOutputStream(); + pBES2Algorithms.putOID(pkcs5PBES2_OID); + + DerOutputStream pBES2_params = new DerOutputStream(); + + DerOutputStream keyDerivationFunc = new DerOutputStream(); + keyDerivationFunc.putOID(pkcs5PBKDF2_OID); + + DerOutputStream pBKDF2_params = new DerOutputStream(); + pBKDF2_params.putOctetString(salt); // choice: 'specified OCTET STRING' + pBKDF2_params.putInteger(iCount); + pBKDF2_params.putInteger(keysize / 8); // derived key length (in octets) + + DerOutputStream prf = new DerOutputStream(); + // algorithm is id-hmacWithSHA1/SHA224/SHA256/SHA384/SHA512 + prf.putOID(kdfAlgo_OID); + // parameters is 'NULL' + prf.putNull(); + pBKDF2_params.write(DerValue.tag_Sequence, prf); + + keyDerivationFunc.write(DerValue.tag_Sequence, pBKDF2_params); + pBES2_params.write(DerValue.tag_Sequence, keyDerivationFunc); + + DerOutputStream encryptionScheme = new DerOutputStream(); + // algorithm is id-aes128-CBC or id-aes256-CBC + encryptionScheme.putOID(cipherAlgo_OID); + // parameters is 'AES-IV ::= OCTET STRING (SIZE(16))' + if (cipherParam != null && cipherParam instanceof IvParameterSpec) { + encryptionScheme.putOctetString( + ((IvParameterSpec)cipherParam).getIV()); + } else { + throw new IOException("Wrong parameter type: IV expected"); + } + pBES2_params.write(DerValue.tag_Sequence, encryptionScheme); + + pBES2Algorithms.write(DerValue.tag_Sequence, pBES2_params); + out.write(DerValue.tag_Sequence, pBES2Algorithms); + + return out.toByteArray(); + } + + protected byte[] engineGetEncoded(String encodingMethod) + throws IOException + { + return engineGetEncoded(); + } + + /* + * Returns a formatted string describing the parameters. + * + * The algorithn name pattern is: "PBEWith<prf>And<encryption>" + * where <prf> is one of: HmacSHA1, HmacSHA224, HmacSHA256, HmacSHA384, + * or HmacSHA512, and <encryption> is AES with a keysize suffix. + */ + protected String engineToString() { + return pbes2AlgorithmName; + } + + public static final class General extends PBES2Parameters { + public General() throws NoSuchAlgorithmException { + super(); + } + } + + public static final class HmacSHA1AndAES_128 extends PBES2Parameters { + public HmacSHA1AndAES_128() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA1AndAES_128"); + } + } + + public static final class HmacSHA224AndAES_128 extends PBES2Parameters { + public HmacSHA224AndAES_128() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA224AndAES_128"); + } + } + + public static final class HmacSHA256AndAES_128 extends PBES2Parameters { + public HmacSHA256AndAES_128() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA256AndAES_128"); + } + } + + public static final class HmacSHA384AndAES_128 extends PBES2Parameters { + public HmacSHA384AndAES_128() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA384AndAES_128"); + } + } + + public static final class HmacSHA512AndAES_128 extends PBES2Parameters { + public HmacSHA512AndAES_128() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA512AndAES_128"); + } + } + + public static final class HmacSHA1AndAES_256 extends PBES2Parameters { + public HmacSHA1AndAES_256() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA1AndAES_256"); + } + } + + public static final class HmacSHA224AndAES_256 extends PBES2Parameters { + public HmacSHA224AndAES_256() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA224AndAES_256"); + } + } + + public static final class HmacSHA256AndAES_256 extends PBES2Parameters { + public HmacSHA256AndAES_256() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA256AndAES_256"); + } + } + + public static final class HmacSHA384AndAES_256 extends PBES2Parameters { + public HmacSHA384AndAES_256() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA384AndAES_256"); + } + } + + public static final class HmacSHA512AndAES_256 extends PBES2Parameters { + public HmacSHA512AndAES_256() throws NoSuchAlgorithmException { + super("PBEWithHmacSHA512AndAES_256"); + } + } +}
--- a/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndDESCipher.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -45,7 +45,7 @@ public final class PBEWithMD5AndDESCipher extends CipherSpi { // the encapsulated DES cipher - private PBECipherCore core; + private PBES1Core core; /** * Creates an instance of this cipher, and initializes its mode (CBC) and @@ -58,7 +58,7 @@ */ public PBEWithMD5AndDESCipher() throws NoSuchAlgorithmException, NoSuchPaddingException { - core = new PBECipherCore("DES"); + core = new PBES1Core("DES"); } /**
--- a/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBEWithMD5AndTripleDESCipher.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -55,7 +55,7 @@ */ public final class PBEWithMD5AndTripleDESCipher extends CipherSpi { - private PBECipherCore core; + private PBES1Core core; /** * Creates an instance of this cipher, and initializes its mode (CBC) and @@ -70,7 +70,7 @@ throws NoSuchAlgorithmException, NoSuchPaddingException { // set the encapsulated cipher to do triple DES - core = new PBECipherCore("DESede"); + core = new PBES1Core("DESede"); } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBKDF2Core.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2005, 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.crypto.provider; + +import java.security.InvalidKeyException; +import java.security.spec.KeySpec; +import java.security.spec.InvalidKeySpecException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactorySpi; +import javax.crypto.spec.PBEKeySpec; + +/** + * This class implements a key factory for PBE keys derived using + * PBKDF2 with HmacSHA1/HmacSHA224/HmacSHA256/HmacSHA384/HmacSHA512 + * pseudo random function (PRF) as defined in PKCS#5 v2.1. + * + * @author Valerie Peng + * + */ +abstract class PBKDF2Core extends SecretKeyFactorySpi { + + private final String prfAlgo; + + PBKDF2Core(String prfAlgo) { + this.prfAlgo = prfAlgo; + } + + /** + * Generates a <code>SecretKey</code> object from the provided key + * specification (key material). + * + * @param keySpec the specification (key material) of the secret key + * + * @return the secret key + * + * @exception InvalidKeySpecException if the given key specification + * is inappropriate for this key factory to produce a public key. + */ + protected SecretKey engineGenerateSecret(KeySpec keySpec) + throws InvalidKeySpecException + { + if (!(keySpec instanceof PBEKeySpec)) { + throw new InvalidKeySpecException("Invalid key spec"); + } + PBEKeySpec ks = (PBEKeySpec) keySpec; + return new PBKDF2KeyImpl(ks, prfAlgo); + } + + /** + * Returns a specification (key material) of the given key + * in the requested format. + * + * @param key the key + * + * @param keySpec the requested format in which the key material shall be + * returned + * + * @return the underlying key specification (key material) in the + * requested format + * + * @exception InvalidKeySpecException if the requested key + * specification is inappropriate for the given key, or the + * given key cannot be processed (e.g., the given key has an + * unrecognized algorithm or format). + */ + protected KeySpec engineGetKeySpec(SecretKey key, Class keySpecCl) + throws InvalidKeySpecException { + if (key instanceof javax.crypto.interfaces.PBEKey) { + // Check if requested key spec is amongst the valid ones + if ((keySpecCl != null) + && PBEKeySpec.class.isAssignableFrom(keySpecCl)) { + javax.crypto.interfaces.PBEKey pKey = + (javax.crypto.interfaces.PBEKey) key; + return new PBEKeySpec + (pKey.getPassword(), pKey.getSalt(), + pKey.getIterationCount(), pKey.getEncoded().length*8); + } else { + throw new InvalidKeySpecException("Invalid key spec"); + } + } else { + throw new InvalidKeySpecException("Invalid key " + + "format/algorithm"); + } + } + + /** + * Translates a <code>SecretKey</code> object, whose provider may be + * unknown or potentially untrusted, into a corresponding + * <code>SecretKey</code> object of this key factory. + * + * @param key the key whose provider is unknown or untrusted + * + * @return the translated key + * + * @exception InvalidKeyException if the given key cannot be processed by + * this key factory. + */ + protected SecretKey engineTranslateKey(SecretKey key) + throws InvalidKeyException { + if ((key != null) && + (key.getAlgorithm().equalsIgnoreCase("PBKDF2With" + prfAlgo)) && + (key.getFormat().equalsIgnoreCase("RAW"))) { + + // Check if key originates from this factory + if (key instanceof com.sun.crypto.provider.PBKDF2KeyImpl) { + return key; + } + // Check if key implements the PBEKey + if (key instanceof javax.crypto.interfaces.PBEKey) { + javax.crypto.interfaces.PBEKey pKey = + (javax.crypto.interfaces.PBEKey) key; + try { + PBEKeySpec spec = + new PBEKeySpec(pKey.getPassword(), + pKey.getSalt(), + pKey.getIterationCount(), + pKey.getEncoded().length*8); + return new PBKDF2KeyImpl(spec, prfAlgo); + } catch (InvalidKeySpecException re) { + InvalidKeyException ike = new InvalidKeyException + ("Invalid key component(s)"); + ike.initCause(re); + throw ike; + } + } + } + throw new InvalidKeyException("Invalid key format/algorithm"); + } + + public static final class HmacSHA1 extends PBKDF2Core { + public HmacSHA1() { + super("HmacSHA1"); + } + } + + public static final class HmacSHA224 extends PBKDF2Core { + public HmacSHA224() { + super("HmacSHA224"); + } + } + + public static final class HmacSHA256 extends PBKDF2Core { + public HmacSHA256() { + super("HmacSHA256"); + } + } + + public static final class HmacSHA384 extends PBKDF2Core { + public HmacSHA384() { + super("HmacSHA384"); + } + } + + public static final class HmacSHA512 extends PBKDF2Core { + public HmacSHA512() { + super("HmacSHA512"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2003, 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.crypto.provider; + +import java.util.Arrays; +import java.nio.ByteBuffer; + +import javax.crypto.MacSpi; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import java.security.*; +import java.security.spec.*; + +/** + * This is an implementation of the PBMAC1 algorithms as defined + * in PKCS#5 v2.1 standard. + */ +abstract class PBMAC1Core extends HmacCore { + + private static final int DEFAULT_SALT_LENGTH = 20; + private static final int DEFAULT_COUNT = 4096; + + private final String kdfAlgo; + private final String hashAlgo; + private final PBKDF2Core kdf; + private final int blockLength; // in octets + + /** + * Creates an instance of PBMAC1 according to the selected + * password-based key derivation function. + */ + PBMAC1Core(String kdfAlgo, String hashAlgo, int blockLength) + throws NoSuchAlgorithmException { + + super(hashAlgo, blockLength); + this.kdfAlgo = kdfAlgo; + this.hashAlgo = hashAlgo; + this.blockLength = blockLength; + + switch(kdfAlgo) { + case "HmacSHA1": + kdf = new PBKDF2Core.HmacSHA1(); + break; + case "HmacSHA224": + kdf = new PBKDF2Core.HmacSHA224(); + break; + case "HmacSHA256": + kdf = new PBKDF2Core.HmacSHA256(); + break; + case "HmacSHA384": + kdf = new PBKDF2Core.HmacSHA384(); + break; + case "HmacSHA512": + kdf = new PBKDF2Core.HmacSHA512(); + break; + default: + throw new NoSuchAlgorithmException( + "No MAC implementation for " + kdfAlgo); + } + } + + /** + * Initializes the HMAC with the given secret key and algorithm parameters. + * + * @param key the secret key. + * @param params the algorithm parameters. + * + * @exception InvalidKeyException if the given key is inappropriate for + * initializing this MAC. + * @exception InvalidAlgorithmParameterException if the given algorithm + * parameters are inappropriate for this MAC. + */ + protected void engineInit(Key key, AlgorithmParameterSpec params) + throws InvalidKeyException, InvalidAlgorithmParameterException { + char[] passwdChars; + byte[] salt = null; + int iCount = 0; + if (key instanceof javax.crypto.interfaces.PBEKey) { + javax.crypto.interfaces.PBEKey pbeKey = + (javax.crypto.interfaces.PBEKey) key; + passwdChars = pbeKey.getPassword(); + salt = pbeKey.getSalt(); // maybe null if unspecified + iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified + } else if (key instanceof SecretKey) { + byte[] passwdBytes = key.getEncoded(); + if ((passwdBytes == null) || + !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { + throw new InvalidKeyException("Missing password"); + } + passwdChars = new char[passwdBytes.length]; + for (int i=0; i<passwdChars.length; i++) { + passwdChars[i] = (char) (passwdBytes[i] & 0x7f); + } + } else { + throw new InvalidKeyException("SecretKey of PBE type required"); + } + if (params == null) { + // generate default for salt and iteration count if necessary + if (salt == null) { + salt = new byte[DEFAULT_SALT_LENGTH]; + SunJCE.RANDOM.nextBytes(salt); + } + if (iCount == 0) iCount = DEFAULT_COUNT; + } else if (!(params instanceof PBEParameterSpec)) { + throw new InvalidAlgorithmParameterException + ("PBEParameterSpec type required"); + } else { + PBEParameterSpec pbeParams = (PBEParameterSpec) params; + // make sure the parameter values are consistent + if (salt != null) { + if (!Arrays.equals(salt, pbeParams.getSalt())) { + throw new InvalidAlgorithmParameterException + ("Inconsistent value of salt between key and params"); + } + } else { + salt = pbeParams.getSalt(); + } + if (iCount != 0) { + if (iCount != pbeParams.getIterationCount()) { + throw new InvalidAlgorithmParameterException + ("Different iteration count between key and params"); + } + } else { + iCount = pbeParams.getIterationCount(); + } + } + // For security purpose, we need to enforce a minimum length + // for salt; just require the minimum salt length to be 8-byte + // which is what PKCS#5 recommends and openssl does. + if (salt.length < 8) { + throw new InvalidAlgorithmParameterException + ("Salt must be at least 8 bytes long"); + } + if (iCount <= 0) { + throw new InvalidAlgorithmParameterException + ("IterationCount must be a positive number"); + } + + PBEKeySpec pbeSpec = + new PBEKeySpec(passwdChars, salt, iCount, blockLength); + // password char[] was cloned in PBEKeySpec constructor, + // so we can zero it out here + java.util.Arrays.fill(passwdChars, ' '); + + SecretKey s = null; + + try { + s = kdf.engineGenerateSecret(pbeSpec); + + } catch (InvalidKeySpecException ikse) { + InvalidKeyException ike = + new InvalidKeyException("Cannot construct PBE key"); + ike.initCause(ikse); + throw ike; + } + byte[] derivedKey = s.getEncoded(); + SecretKey cipherKey = new SecretKeySpec(derivedKey, kdfAlgo); + + super.engineInit(cipherKey, null); + } + + public static final class HmacSHA1 extends PBMAC1Core { + public HmacSHA1() throws NoSuchAlgorithmException { + super("HmacSHA1", "SHA1", 64); + } + } + + public static final class HmacSHA224 extends PBMAC1Core { + public HmacSHA224() throws NoSuchAlgorithmException { + super("HmacSHA224", "SHA-224", 64); + } + } + + public static final class HmacSHA256 extends PBMAC1Core { + public HmacSHA256() throws NoSuchAlgorithmException { + super("HmacSHA256", "SHA-256", 64); + } + } + + public static final class HmacSHA384 extends PBMAC1Core { + public HmacSHA384() throws NoSuchAlgorithmException { + super("HmacSHA384", "SHA-384", 128); + } + } + + public static final class HmacSHA512 extends PBMAC1Core { + public HmacSHA512() throws NoSuchAlgorithmException { + super("HmacSHA512", "SHA-512", 128); + } + } +}
--- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Feb 13 04:21:57 2019 +0000 @@ -34,19 +34,24 @@ /** * This class implements password-base encryption algorithm with - * SHA1 digest and the following Ciphers in CBC mode + * SHA1 digest and the following Ciphers (in CBC mode, where applicable): * - DESede cipher and - * - RC2 Cipher with 40-bit effective key length + * - RC2 Cipher with 40-bit or 128-bit effective key length and + * - RC4 Cipher with 40-bit or 128-bit effective key length * as defined by PKCS #12 version 1.0 standard. * * @author Valerie Peng * @see javax.crypto.CipherSpi */ final class PKCS12PBECipherCore { + + // TBD: replace CipherCore with a CipherSpi object to simplify maintenance + private CipherCore cipher; private int blockSize; private int keySize; private String algo = null; + private String pbeAlgo = null; private byte[] salt = null; private int iCount = 0; @@ -57,8 +62,16 @@ static final int CIPHER_IV = 2; static final int MAC_KEY = 3; + // Uses default hash algorithm (SHA-1) static byte[] derive(char[] chars, byte[] salt, int ic, int n, int type) { + return derive(chars, salt, ic, n, type, "SHA-1", 64); + } + + // Uses supplied hash algorithm + static byte[] derive(char[] chars, byte[] salt, int ic, int n, int type, + String hashAlgo, int blockLength) { + // Add in trailing NULL terminator. Special case: // no terminator if password is "\0". int length = chars.length*2; @@ -74,21 +87,23 @@ passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF); passwd[j+1] = (byte) (chars[i] & 0xFF); } - int v = 512 / 8; - int u = 160 / 8; - int c = roundup(n, u) / u; - byte[] D = new byte[v]; - int s = roundup(salt.length, v); - int p = roundup(passwd.length, v); - byte[] I = new byte[s + p]; byte[] key = new byte[n]; - Arrays.fill(D, (byte)type); - concat(salt, I, 0, s); - concat(passwd, I, s, p); + try { + MessageDigest sha = MessageDigest.getInstance(hashAlgo); - try { - MessageDigest sha = MessageDigest.getInstance("SHA1"); + int v = blockLength; + int u = sha.getDigestLength(); + int c = roundup(n, u) / u; + byte[] D = new byte[v]; + int s = roundup(salt.length, v); + int p = roundup(passwd.length, v); + byte[] I = new byte[s + p]; + + Arrays.fill(D, (byte)type); + concat(salt, I, 0, s); + concat(passwd, I, s, p); + byte[] Ai; byte[] B = new byte[v]; byte[] tmp = new byte[v]; @@ -149,23 +164,30 @@ PKCS12PBECipherCore(String symmCipherAlg, int defKeySize) throws NoSuchAlgorithmException { + algo = symmCipherAlg; - SymmetricCipher symmCipher = null; - if (algo.equals("DESede")) { - symmCipher = new DESedeCrypt(); - } else if (algo.equals("RC2")) { - symmCipher = new RC2Crypt(); + if (algo.equals("RC4")) { + pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8; } else { - throw new NoSuchAlgorithmException("No Cipher implementation " + + SymmetricCipher symmCipher = null; + if (algo.equals("DESede")) { + symmCipher = new DESedeCrypt(); + pbeAlgo = "PBEWithSHA1AndDESede"; + } else if (algo.equals("RC2")) { + symmCipher = new RC2Crypt(); + pbeAlgo = "PBEWithSHA1AndRC2_" + defKeySize * 8; + } else { + throw new NoSuchAlgorithmException("No Cipher implementation " + "for PBEWithSHA1And" + algo); - } - blockSize = symmCipher.getBlockSize(); - cipher = new CipherCore(symmCipher, blockSize); - cipher.setMode("CBC"); - try { - cipher.setPadding("PKCS5Padding"); - } catch (NoSuchPaddingException nspe) { - // should not happen + } + blockSize = symmCipher.getBlockSize(); + cipher = new CipherCore(symmCipher, blockSize); + cipher.setMode("CBC"); + try { + cipher.setPadding("PKCS5Padding"); + } catch (NoSuchPaddingException nspe) { + // should not happen + } } keySize = defKeySize; } @@ -209,8 +231,7 @@ } PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount); try { - params = AlgorithmParameters.getInstance("PBEWithSHA1And" + - (algo.equalsIgnoreCase("RC2")?"RC2_40":algo), SunJCE.getInstance()); + params = AlgorithmParameters.getInstance(pbeAlgo, SunJCE.getInstance()); params.init(pbeSpec); } catch (NoSuchAlgorithmException nsae) { // should never happen @@ -226,6 +247,13 @@ void implInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + implInit(opmode, key, params, random, null); + } + + void implInit(int opmode, Key key, AlgorithmParameterSpec params, + SecureRandom random, CipherSpi cipherImpl) + throws InvalidKeyException, + InvalidAlgorithmParameterException { char[] passwdChars = null; salt = null; iCount = 0; @@ -306,17 +334,29 @@ byte[] derivedKey = derive(passwdChars, salt, iCount, keySize, CIPHER_KEY); SecretKey cipherKey = new SecretKeySpec(derivedKey, algo); - byte[] derivedIv = derive(passwdChars, salt, iCount, 8, + + if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) { + ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random); + + } else { + byte[] derivedIv = derive(passwdChars, salt, iCount, 8, CIPHER_IV); - IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8); + IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8); - // initialize the underlying cipher - cipher.init(opmode, cipherKey, ivSpec, random); + // initialize the underlying cipher + cipher.init(opmode, cipherKey, ivSpec, random); + } } void implInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { + implInit(opmode, key, params, random, null); + } + + void implInit(int opmode, Key key, AlgorithmParameters params, + SecureRandom random, CipherSpi cipherImpl) + throws InvalidKeyException, InvalidAlgorithmParameterException { AlgorithmParameterSpec paramSpec = null; if (params != null) { try { @@ -326,13 +366,19 @@ "requires PBE parameters"); } } - implInit(opmode, key, paramSpec, random); + implInit(opmode, key, paramSpec, random, cipherImpl); } void implInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { + implInit(opmode, key, random, null); + } + + void implInit(int opmode, Key key, SecureRandom random, + CipherSpi cipherImpl) throws InvalidKeyException { try { - implInit(opmode, key, (AlgorithmParameterSpec) null, random); + implInit(opmode, key, (AlgorithmParameterSpec) null, random, + cipherImpl); } catch (InvalidAlgorithmParameterException iape) { throw new InvalidKeyException("requires PBE parameters"); } @@ -523,4 +569,245 @@ return core.implWrap(key); } } + + public static final class PBEWithSHA1AndRC2_128 extends CipherSpi { + private final PKCS12PBECipherCore core; + public PBEWithSHA1AndRC2_128() throws NoSuchAlgorithmException { + core = new PKCS12PBECipherCore("RC2", 16); + } + protected byte[] engineDoFinal(byte[] in, int inOff, int inLen) + throws IllegalBlockSizeException, BadPaddingException { + return core.implDoFinal(in, inOff, inLen); + } + protected int engineDoFinal(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return core.implDoFinal(in, inOff, inLen, out, outOff); + } + protected int engineGetBlockSize() { + return core.implGetBlockSize(); + } + protected byte[] engineGetIV() { + return core.implGetIV(); + } + protected int engineGetKeySize(Key key) throws InvalidKeyException { + return core.implGetKeySize(key); + } + protected int engineGetOutputSize(int inLen) { + return core.implGetOutputSize(inLen); + } + protected AlgorithmParameters engineGetParameters() { + return core.implGetParameters(); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random); + } + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException { + core.implInit(opmode, key, random); + } + protected void engineSetMode(String mode) + throws NoSuchAlgorithmException { + core.implSetMode(mode); + } + protected void engineSetPadding(String paddingScheme) + throws NoSuchPaddingException { + core.implSetPadding(paddingScheme); + } + protected Key engineUnwrap(byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException { + return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } + protected byte[] engineUpdate(byte[] in, int inOff, int inLen) { + return core.implUpdate(in, inOff, inLen); + } + protected int engineUpdate(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException { + return core.implUpdate(in, inOff, inLen, out, outOff); + } + protected byte[] engineWrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException { + return core.implWrap(key); + } + } + + public static final class PBEWithSHA1AndRC4_40 extends CipherSpi { + private static final int RC4_KEYSIZE = 5; + private final PKCS12PBECipherCore core; + private final ARCFOURCipher cipher; + + public PBEWithSHA1AndRC4_40() throws NoSuchAlgorithmException { + core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE); + cipher = new ARCFOURCipher(); + } + protected byte[] engineDoFinal(byte[] in, int inOff, int inLen) + throws IllegalBlockSizeException, BadPaddingException { + return cipher.engineDoFinal(in, inOff, inLen); + } + protected int engineDoFinal(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return cipher.engineDoFinal(in, inOff, inLen, out, outOff); + } + protected int engineGetBlockSize() { + return cipher.engineGetBlockSize(); + } + protected byte[] engineGetIV() { + return cipher.engineGetIV(); + } + protected int engineGetKeySize(Key key) throws InvalidKeyException { + return RC4_KEYSIZE; + } + protected int engineGetOutputSize(int inLen) { + return cipher.engineGetOutputSize(inLen); + } + protected AlgorithmParameters engineGetParameters() { + return core.implGetParameters(); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random, cipher); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random, cipher); + } + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException { + core.implInit(opmode, key, random, cipher); + } + protected void engineSetMode(String mode) + throws NoSuchAlgorithmException { + if (mode.equalsIgnoreCase("ECB") == false) { + throw new NoSuchAlgorithmException("Unsupported mode " + mode); + } + } + protected void engineSetPadding(String paddingScheme) + throws NoSuchPaddingException { + if (paddingScheme.equalsIgnoreCase("NoPadding") == false) { + throw new NoSuchPaddingException("Padding must be NoPadding"); + } + } + protected Key engineUnwrap(byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException { + return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } + protected byte[] engineUpdate(byte[] in, int inOff, int inLen) { + return cipher.engineUpdate(in, inOff, inLen); + } + protected int engineUpdate(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException { + return cipher.engineUpdate(in, inOff, inLen, out, outOff); + } + protected byte[] engineWrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException { + return cipher.engineWrap(key); + } + } + + public static final class PBEWithSHA1AndRC4_128 extends CipherSpi { + private static final int RC4_KEYSIZE = 16; + private final PKCS12PBECipherCore core; + private final ARCFOURCipher cipher; + + public PBEWithSHA1AndRC4_128() throws NoSuchAlgorithmException { + core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE); + cipher = new ARCFOURCipher(); + } + protected byte[] engineDoFinal(byte[] in, int inOff, int inLen) + throws IllegalBlockSizeException, BadPaddingException { + return cipher.engineDoFinal(in, inOff, inLen); + } + protected int engineDoFinal(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + return cipher.engineDoFinal(in, inOff, inLen, out, outOff); + } + protected int engineGetBlockSize() { + return cipher.engineGetBlockSize(); + } + protected byte[] engineGetIV() { + return cipher.engineGetIV(); + } + protected int engineGetKeySize(Key key) throws InvalidKeyException { + return RC4_KEYSIZE; + } + protected int engineGetOutputSize(int inLen) { + return cipher.engineGetOutputSize(inLen); + } + protected AlgorithmParameters engineGetParameters() { + return core.implGetParameters(); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random, cipher); + } + protected void engineInit(int opmode, Key key, + AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException { + core.implInit(opmode, key, params, random, cipher); + } + protected void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException { + core.implInit(opmode, key, random, cipher); + } + protected void engineSetMode(String mode) + throws NoSuchAlgorithmException { + if (mode.equalsIgnoreCase("ECB") == false) { + throw new NoSuchAlgorithmException("Unsupported mode " + mode); + } + } + protected void engineSetPadding(String paddingScheme) + throws NoSuchPaddingException { + if (paddingScheme.equalsIgnoreCase("NoPadding") == false) { + throw new NoSuchPaddingException("Padding must be NoPadding"); + } + } + protected Key engineUnwrap(byte[] wrappedKey, + String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException { + return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } + protected byte[] engineUpdate(byte[] in, int inOff, int inLen) { + return cipher.engineUpdate(in, inOff, inLen); + } + protected int engineUpdate(byte[] in, int inOff, int inLen, + byte[] out, int outOff) + throws ShortBufferException { + return cipher.engineUpdate(in, inOff, inLen, out, outOff); + } + protected byte[] engineWrap(Key key) + throws IllegalBlockSizeException, InvalidKeyException { + return cipher.engineWrap(key); + } + } }
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java Wed Feb 13 04:21:57 2019 +0000 @@ -77,10 +77,14 @@ "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " + "Diffie-Hellman, HMAC)"; + private static final String OID_PKCS12_RC4_128 = "1.2.840.113549.1.12.1.1"; + private static final String OID_PKCS12_RC4_40 = "1.2.840.113549.1.12.1.2"; + private static final String OID_PKCS12_DESede = "1.2.840.113549.1.12.1.3"; + private static final String OID_PKCS12_RC2_128 = "1.2.840.113549.1.12.1.5"; private static final String OID_PKCS12_RC2_40 = "1.2.840.113549.1.12.1.6"; - private static final String OID_PKCS12_DESede = "1.2.840.113549.1.12.1.3"; private static final String OID_PKCS5_MD5_DES = "1.2.840.113549.1.5.3"; private static final String OID_PKCS5_PBKDF2 = "1.2.840.113549.1.5.12"; + private static final String OID_PKCS5_PBES2 = "1.2.840.113549.1.5.13"; private static final String OID_PKCS3 = "1.2.840.113549.1.3.1"; /* Are we debugging? -- for developers */ @@ -142,14 +146,26 @@ put("Cipher.DESedeWrap SupportedPaddings", "NOPADDING"); put("Cipher.DESedeWrap SupportedKeyFormats", "RAW"); + // PBES1 + put("Cipher.PBEWithMD5AndDES", "com.sun.crypto.provider.PBEWithMD5AndDESCipher"); put("Alg.Alias.Cipher.OID."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("Alg.Alias.Cipher."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); + put("Cipher.PBEWithMD5AndTripleDES", "com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher"); + + put("Cipher.PBEWithSHA1AndDESede", + "com.sun.crypto.provider.PKCS12PBECipherCore$" + + "PBEWithSHA1AndDESede"); + put("Alg.Alias.Cipher.OID." + OID_PKCS12_DESede, + "PBEWithSHA1AndDESede"); + put("Alg.Alias.Cipher." + OID_PKCS12_DESede, + "PBEWithSHA1AndDESede"); + put("Cipher.PBEWithSHA1AndRC2_40", "com.sun.crypto.provider.PKCS12PBECipherCore$" + "PBEWithSHA1AndRC2_40"); @@ -157,13 +173,70 @@ "PBEWithSHA1AndRC2_40"); put("Alg.Alias.Cipher." + OID_PKCS12_RC2_40, "PBEWithSHA1AndRC2_40"); - put("Cipher.PBEWithSHA1AndDESede", + + put("Cipher.PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PKCS12PBECipherCore$" + + "PBEWithSHA1AndRC2_128"); + put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + put("Alg.Alias.Cipher." + OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + + put("Cipher.PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PKCS12PBECipherCore$" + + "PBEWithSHA1AndRC4_40"); + put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + put("Alg.Alias.Cipher." + OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + + put("Cipher.PBEWithSHA1AndRC4_128", "com.sun.crypto.provider.PKCS12PBECipherCore$" + - "PBEWithSHA1AndDESede"); - put("Alg.Alias.Cipher.OID." + OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); - put("Alg.Alias.Cipher." + OID_PKCS12_DESede, - "PBEWithSHA1AndDESede"); + "PBEWithSHA1AndRC4_128"); + put("Alg.Alias.Cipher.OID." + OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + put("Alg.Alias.Cipher." + OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + + //PBES2 + + put("Cipher.PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_128"); + + put("Cipher.PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA224AndAES_128"); + + put("Cipher.PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA256AndAES_128"); + + put("Cipher.PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA384AndAES_128"); + + put("Cipher.PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA512AndAES_128"); + + put("Cipher.PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBES2Core$HmacSHA1AndAES_256"); + + put("Cipher.PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA224AndAES_256"); + + put("Cipher.PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA256AndAES_256"); + + put("Cipher.PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA384AndAES_256"); + + put("Cipher.PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBES2Core$" + + "HmacSHA512AndAES_256"); put("Cipher.Blowfish", "com.sun.crypto.provider.BlowfishCipher"); @@ -305,6 +378,7 @@ "DiffieHellman"); put("Alg.Alias.KeyPairGenerator."+OID_PKCS3, "DiffieHellman"); + /* * Algorithm parameter generation engines */ @@ -375,6 +449,64 @@ put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_40, "PBEWithSHA1AndRC2_40"); + put("AlgorithmParameters.PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PBEParameters"); + put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + + put("AlgorithmParameters.PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PBEParameters"); + put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + + put("AlgorithmParameters.PBEWithSHA1AndRC4_128", + "com.sun.crypto.provider.PBEParameters"); + put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + put("Alg.Alias.AlgorithmParameters." + OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + + put("AlgorithmParameters.PBES2", + "com.sun.crypto.provider.PBES2Parameters$General"); + put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_PBES2, + "PBES2"); + put("Alg.Alias.AlgorithmParameters." + OID_PKCS5_PBES2, + "PBES2"); + + put("AlgorithmParameters.PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_128"); + + put("AlgorithmParameters.PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_128"); + + put("AlgorithmParameters.PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_128"); + + put("AlgorithmParameters.PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_128"); + + put("AlgorithmParameters.PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_128"); + + put("AlgorithmParameters.PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA1AndAES_256"); + + put("AlgorithmParameters.PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA224AndAES_256"); + + put("AlgorithmParameters.PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA256AndAES_256"); + + put("AlgorithmParameters.PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA384AndAES_256"); + + put("AlgorithmParameters.PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBES2Parameters$HmacSHA512AndAES_256"); + put("AlgorithmParameters.Blowfish", "com.sun.crypto.provider.BlowfishParameters"); @@ -382,6 +514,7 @@ "com.sun.crypto.provider.AESParameters"); put("Alg.Alias.AlgorithmParameters.Rijndael", "AES"); + put("AlgorithmParameters.RC2", "com.sun.crypto.provider.RC2Parameters"); @@ -397,6 +530,7 @@ put("Alg.Alias.KeyFactory.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.KeyFactory."+OID_PKCS3, "DiffieHellman"); + /* * Secret-key factories */ @@ -445,13 +579,90 @@ put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC2_40, "PBEWithSHA1AndRC2_40"); + put("SecretKeyFactory.PBEWithSHA1AndRC2_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC2_128" + ); + put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC2_128, + "PBEWithSHA1AndRC2_128"); + + put("SecretKeyFactory.PBEWithSHA1AndRC4_40", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_40" + ); + + put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC4_40, + "PBEWithSHA1AndRC4_40"); + + put("SecretKeyFactory.PBEWithSHA1AndRC4_128", + "com.sun.crypto.provider.PBEKeyFactory$PBEWithSHA1AndRC4_128" + ); + + put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + put("Alg.Alias.SecretKeyFactory." + OID_PKCS12_RC4_128, + "PBEWithSHA1AndRC4_128"); + + put("SecretKeyFactory.PBEWithHmacSHA1AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA1AndAES_128"); + + put("SecretKeyFactory.PBEWithHmacSHA224AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA224AndAES_128"); + + put("SecretKeyFactory.PBEWithHmacSHA256AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA256AndAES_128"); + + put("SecretKeyFactory.PBEWithHmacSHA384AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA384AndAES_128"); + + put("SecretKeyFactory.PBEWithHmacSHA512AndAES_128", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA512AndAES_128"); + + put("SecretKeyFactory.PBEWithHmacSHA1AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA1AndAES_256"); + + put("SecretKeyFactory.PBEWithHmacSHA224AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA224AndAES_256"); + + put("SecretKeyFactory.PBEWithHmacSHA256AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA256AndAES_256"); + + put("SecretKeyFactory.PBEWithHmacSHA384AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA384AndAES_256"); + + put("SecretKeyFactory.PBEWithHmacSHA512AndAES_256", + "com.sun.crypto.provider.PBEKeyFactory$" + + "PBEWithHmacSHA512AndAES_256"); + + // PBKDF2 + put("SecretKeyFactory.PBKDF2WithHmacSHA1", - "com.sun.crypto.provider.PBKDF2HmacSHA1Factory"); + "com.sun.crypto.provider.PBKDF2Core$HmacSHA1"); put("Alg.Alias.SecretKeyFactory.OID." + OID_PKCS5_PBKDF2, "PBKDF2WithHmacSHA1"); put("Alg.Alias.SecretKeyFactory." + OID_PKCS5_PBKDF2, "PBKDF2WithHmacSHA1"); + put("SecretKeyFactory.PBKDF2WithHmacSHA224", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA224"); + put("SecretKeyFactory.PBKDF2WithHmacSHA256", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA256"); + put("SecretKeyFactory.PBKDF2WithHmacSHA384", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA384"); + put("SecretKeyFactory.PBKDF2WithHmacSHA512", + "com.sun.crypto.provider.PBKDF2Core$HmacSHA512"); + /* * MAC */ @@ -479,6 +690,19 @@ put("Mac.HmacPBESHA1", "com.sun.crypto.provider.HmacPKCS12PBESHA1"); + // PBMAC1 + + put("Mac.PBEWithHmacSHA1", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA1"); + put("Mac.PBEWithHmacSHA224", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA224"); + put("Mac.PBEWithHmacSHA256", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA256"); + put("Mac.PBEWithHmacSHA384", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA384"); + put("Mac.PBEWithHmacSHA512", + "com.sun.crypto.provider.PBMAC1Core$HmacSHA512"); + put("Mac.SslMacMD5", "com.sun.crypto.provider.SslMacCore$SslMacMD5"); put("Mac.SslMacSHA1", @@ -491,6 +715,10 @@ put("Mac.HmacSHA384 SupportedKeyFormats", "RAW"); put("Mac.HmacSHA512 SupportedKeyFormats", "RAW"); put("Mac.HmacPBESHA1 SupportedKeyFormats", "RAW"); + put("Mac.HmacPBESHA224 SupportedKeyFormats", "RAW"); + put("Mac.HmacPBESHA256 SupportedKeyFormats", "RAW"); + put("Mac.HmacPBESHA384 SupportedKeyFormats", "RAW"); + put("Mac.HmacPBESHA512 SupportedKeyFormats", "RAW"); put("Mac.SslMacMD5 SupportedKeyFormats", "RAW"); put("Mac.SslMacSHA1 SupportedKeyFormats", "RAW");
--- a/src/share/classes/javax/crypto/spec/PBEParameterSpec.java Tue Feb 12 04:25:26 2019 +0000 +++ b/src/share/classes/javax/crypto/spec/PBEParameterSpec.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -41,6 +41,7 @@ private byte[] salt; private int iterationCount; + private AlgorithmParameterSpec paramSpec = null; /** * Constructs a parameter set for password-based encryption as defined in @@ -57,6 +58,25 @@ } /** + * Constructs a parameter set for password-based encryption as defined in + * the PKCS #5 standard. + * + * @param salt the salt. The contents of <code>salt</code> are copied + * to protect against subsequent modification. + * @param iterationCount the iteration count. + * @param paramSpec the cipher algorithm parameter specification. + * @exception NullPointerException if <code>salt</code> is null. + * + * @since 1.8 + */ + public PBEParameterSpec(byte[] salt, int iterationCount, + AlgorithmParameterSpec paramSpec) { + this.salt = salt.clone(); + this.iterationCount = iterationCount; + this.paramSpec = paramSpec; + } + + /** * Returns the salt. * * @return the salt. Returns a new array @@ -74,4 +94,15 @@ public int getIterationCount() { return this.iterationCount; } + + /** + * Returns the cipher algorithm parameter specification. + * + * @return the parameter specification, or null if none was set. + * + * @since 1.8 + */ + public AlgorithmParameterSpec getParameterSpec() { + return this.paramSpec; + } }
--- a/test/com/sun/crypto/provider/Cipher/PBE/PBEInvalidParamsTest.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PBEInvalidParamsTest.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6209660 + * @bug 6209660 6383200 * @summary Ensure that InvalidAlgorithmParameterException is * thrown as javadoc specified when parameters of the wrong * type are used. @@ -38,9 +38,21 @@ private static final char[] PASSWORD = { 'p', 'a', 's', 's' }; private static final String[] PBE_ALGOS = { - "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40" + "PBEWithMD5AndDES", + "PBEWithSHA1AndDESede", + "PBEWithSHA1AndRC2_40", + "PBEWithSHA1AndRC2_128", + "PBEWithSHA1AndRC4_40", + "PBEWithSHA1AndRC4_128", // skip "PBEWithMD5AndTripleDES" since it requires Unlimited // version of JCE jurisdiction policy files. + "PBEWithHmacSHA1AndAES_128", + "PBEWithHmacSHA224AndAES_128", + "PBEWithHmacSHA256AndAES_128", + "PBEWithHmacSHA384AndAES_128", + "PBEWithHmacSHA512AndAES_128" + // skip "PBEWithHmacSHAxxxAndAES_256" since they require Unlimited + // version of JCE jurisdiction policy files. }; private static final IvParameterSpec INVALID_PARAMS =
--- a/test/com/sun/crypto/provider/Cipher/PBE/PBEKeysAlgorithmNames.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PBEKeysAlgorithmNames.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6341599 + * @bug 6341599 6383200 * @summary JCE Reference Guide has recommendations, not requirements, * for algorithm names * @author Brad R. Wetmore @@ -38,8 +38,15 @@ "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40", + "PBEWithSHA1AndRC2_128", + "PBEWithMD5AndTripleDES", + "PBEWithSHA1AndRC4_40", + "PBEWithSHA1AndRC4_128", "PBKDF2WithHmacSHA1", - "PBEWithMD5AndTripleDES" + "PBKDF2WithHmacSHA224", + "PBKDF2WithHmacSHA256", + "PBKDF2WithHmacSHA384", + "PBKDF2WithHmacSHA512" }; public static void main(String[] argv) throws Exception {
--- a/test/com/sun/crypto/provider/Cipher/PBE/PBEParametersTest.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PBEParametersTest.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4944783 + * @bug 4944783 6383200 * @summary ensure that the AlgorithmParameters object returned by * PBE ciphers have the matching algorithm name. * @author Valerie Peng @@ -37,9 +37,21 @@ private static final char[] PASSWORD = { 'p', 'a', 's', 's' }; private static final String[] PBE_ALGOS = { - "PBEWithMD5AndDES", "PBEWithSHA1AndDESede", "PBEWithSHA1AndRC2_40" + "PBEWithMD5AndDES", + "PBEWithSHA1AndDESede", + "PBEWithSHA1AndRC2_40", + "PBEWithSHA1AndRC2_128", + "PBEWithSHA1AndRC4_40", + "PBEWithSHA1AndRC4_128", // skip "PBEWithMD5AndTripleDES" since it requires Unlimited // version of JCE jurisdiction policy files. + "PBEWithHmacSHA1AndAES_128", + "PBEWithHmacSHA224AndAES_128", + "PBEWithHmacSHA256AndAES_128", + "PBEWithHmacSHA384AndAES_128", + "PBEWithHmacSHA512AndAES_128" + // skip "PBEWithHmacSHAxxxAndAES_256" since they require Unlimited + // version of JCE jurisdiction policy files. }; public static void main(String[] args) throws Exception { PBEKeySpec ks = new PBEKeySpec(PASSWORD);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PBES2Test.java Wed Feb 13 04:21:57 2019 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, 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. + */ + +/* + * @test + * @bug 6383200 + * @summary PBE: need new algorithm support in password based encryption + */ +import java.security.*; +import java.util.Arrays; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class PBES2Test { + + private static final String[] algos = { + "PBEWithHmacSHA1AndAES_128", + "PBEWithHmacSHA224AndAES_128", + "PBEWithHmacSHA256AndAES_128", + "PBEWithHmacSHA384AndAES_128", + "PBEWithHmacSHA512AndAES_128" + }; + private static final byte[] ivBytes = { + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, + }; + + public static final void main(String[] args) throws Exception { + for (String algo : algos) { + test(algo, true); // salt, ic, IV supplied by the application + test(algo, false); // salt, ic, IV generated by the implementation + } + } + + private static final void test(String algo, boolean suppliedParams) + throws Exception { + + System.out.println("***********************************************"); + System.out.println(algo + + (suppliedParams ? " [algorithm parameters are supplied]\n" + : " [algorithm parameters are generated]\n")); + int iterationCount = 1000; + byte[] salt = new byte[]{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + + // Create PBE key + PBEKeySpec pbeKeySpec = new PBEKeySpec("mypassword".toCharArray()); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algo); + SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec); + byte[] pbeKeyBytes = pbeKey.getEncoded(); + System.out.println(" key[" + pbeKeyBytes.length + "]: " + + String.format("0x%0" + (pbeKeyBytes.length * 2) + "x", + new java.math.BigInteger(1, pbeKeyBytes))); + + // Create PBE cipher + System.out.println("Encrypting..."); + Cipher pbeCipher = Cipher.getInstance(algo); + if (suppliedParams) { + pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, + new PBEParameterSpec(salt, iterationCount, + new IvParameterSpec(ivBytes))); + } else { + pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey); + } + + // Encrypt + byte[] cleartext = "This is just an example".getBytes(); + System.out.println(" text[" + cleartext.length + "]: " + + String.format("0x%0" + (cleartext.length * 2) + "x", + new java.math.BigInteger(1, cleartext))); + + byte[] ciphertext = pbeCipher.doFinal(cleartext); + System.out.println("c'text[" + ciphertext.length + "]: " + + String.format("0x%0" + (ciphertext.length * 2) + "x", + new java.math.BigInteger(1, ciphertext))); + + AlgorithmParameters aps = pbeCipher.getParameters(); + + byte[] iv; + if (suppliedParams) { + iv = ivBytes; + } else { + PBEParameterSpec pbeSpec = + aps.getParameterSpec(PBEParameterSpec.class); + salt = pbeSpec.getSalt(); + iterationCount = pbeSpec.getIterationCount(); + IvParameterSpec ivSpec = + (IvParameterSpec) pbeSpec.getParameterSpec(); + iv = ivSpec.getIV(); + } + System.out.println(" salt[" + salt.length + "]: " + + String.format("0x%0" + (salt.length * 2) + "x", + new java.math.BigInteger(1, salt))); + System.out.println("iterationCount=" + iterationCount); + System.out.println(" iv[" + iv.length + "]: " + + String.format("0x%0" + (iv.length * 2) + "x", + new java.math.BigInteger(1, iv))); + + // Decrypt + System.out.println("Decrypting..."); + Cipher pbeCipher2 = Cipher.getInstance(algo); + pbeCipher2.init(Cipher.DECRYPT_MODE, pbeKey, aps); + byte[] cleartext2 = pbeCipher2.doFinal(ciphertext); + System.out.println(" text[" + cleartext2.length + "]: " + + String.format("0x%0" + (cleartext2.length * 2) + "x", + new java.math.BigInteger(1, cleartext2))); + + if (Arrays.equals(cleartext, cleartext2)) { + System.out.println( + "\nPass: decrypted ciphertext matches the original text\n"); + } else { + throw new Exception( + "Fail: decrypted ciphertext does NOT match the original text"); + } + } +}
--- a/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Cipher.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -23,9 +23,9 @@ /** * @test - * @bug 4893959 - * @summary basic test for PBEWithSHA1AndDESede and - * PBEWithSHA1AndRC2_40 + * @bug 4893959 6383200 + * @summary basic test for PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40/128 + * and PBEWithSHA1AndRC4_40/128 * @author Valerie Peng */ @@ -87,6 +87,9 @@ System.out.println("Testing provider " + p.getName() + "..."); runTest("PBEWithSHA1AndDESede", input, PASSWD, p); runTest("PBEWithSHA1AndRC2_40", input, PASSWD, p); + runTest("PBEWithSHA1AndRC2_128", input, PASSWD, p); + runTest("PBEWithSHA1AndRC4_40", input, PASSWD, p); + runTest("PBEWithSHA1AndRC4_128", input, PASSWD, p); System.out.println("All tests passed"); long stop = System.currentTimeMillis(); System.out.println("Done (" + (stop - start) + " ms).");
--- a/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Oid.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Cipher/PBE/PKCS12Oid.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -23,9 +23,9 @@ /** * @test - * @bug 4898810 - * @summary ensure PBEWithSHA1AndDESede and PBEWithSHA1AndRC2_40 - * is registered under correct OID. + * @bug 4898810 6383200 + * @summary ensure PBEWithSHA1AndDESede, PBEWithSHA1AndRC2_40/128 + * and PBEWithSHA1AndRC4_40/128 are registered under correct OID. * @author Valerie Peng */ @@ -37,12 +37,20 @@ import javax.crypto.interfaces.PBEKey; public class PKCS12Oid { - private static String OID_PBEWithSHAAnd40BitRC2CBC = "1.2.840.113549.1.12.1.6"; - private static String OID_PBEWithSHAAnd3KeyTripleDESCBC = "1.2.840.113549.1.12.1.3"; + private static String OID_PKCS12 = "1.2.840.113549.1.12.1."; + private static String OID_PBEWithSHAAnd128BitRC4 = OID_PKCS12 + "1"; + private static String OID_PBEWithSHAAnd40BitRC4 = OID_PKCS12 + "2"; + private static String OID_PBEWithSHAAnd3KeyTripleDESCBC = OID_PKCS12 + "3"; + private static String OID_PBEWithSHAAnd128BitRC2CBC = OID_PKCS12 + "5"; + private static String OID_PBEWithSHAAnd40BitRC2CBC = OID_PKCS12 + "6"; public static void main(String[] argv) throws Exception { Cipher c = Cipher.getInstance(OID_PBEWithSHAAnd40BitRC2CBC, "SunJCE"); c = Cipher.getInstance(OID_PBEWithSHAAnd3KeyTripleDESCBC, "SunJCE"); + + c = Cipher.getInstance(OID_PBEWithSHAAnd128BitRC4, "SunJCE"); + c = Cipher.getInstance(OID_PBEWithSHAAnd40BitRC4, "SunJCE"); + c = Cipher.getInstance(OID_PBEWithSHAAnd128BitRC2CBC, "SunJCE"); System.out.println("All tests passed"); } }
--- a/test/com/sun/crypto/provider/Mac/HmacPBESHA1.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Mac/HmacPBESHA1.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -36,34 +36,45 @@ import javax.crypto.spec.*; public class HmacPBESHA1 { - private static final String MAC_ALGO = "HmacPBESHA1"; + private static final String[] MAC_ALGOS = { + "HmacPBESHA1", + "PBEWithHmacSHA1", + "PBEWithHmacSHA224", + "PBEWithHmacSHA256", + "PBEWithHmacSHA384", + "PBEWithHmacSHA512" + }; + private static final int[] MAC_LENGTHS = { 20, 20, 28, 32, 48, 64 }; private static final String KEY_ALGO = "PBE"; private static final String PROVIDER = "SunJCE"; - private SecretKey key = null; + private static SecretKey key = null; public static void main(String argv[]) throws Exception { - HmacPBESHA1 test = new HmacPBESHA1(); - test.run(); - System.out.println("Test Passed"); + for (int i = 0; i < MAC_ALGOS.length; i++) { + runtest(MAC_ALGOS[i], MAC_LENGTHS[i]); + } + System.out.println("\nTest Passed"); } - public void run() throws Exception { + private static void runtest(String algo, int length) throws Exception { + System.out.println("Testing: " + algo); if (key == null) { char[] password = { 't', 'e', 's', 't' }; PBEKeySpec keySpec = new PBEKeySpec(password); - SecretKeyFactory kf = SecretKeyFactory.getInstance(KEY_ALGO, PROVIDER); + SecretKeyFactory kf = + SecretKeyFactory.getInstance(KEY_ALGO, PROVIDER); key = kf.generateSecret(keySpec); } - Mac mac = Mac.getInstance(MAC_ALGO, PROVIDER); + Mac mac = Mac.getInstance(algo, PROVIDER); byte[] plainText = new byte[30]; mac.init(key); mac.update(plainText); byte[] value1 = mac.doFinal(); - if (value1.length != 20) { - throw new Exception("incorrect MAC output length, " + - "expected 20, got " + value1.length); + if (value1.length != length) { + throw new Exception("incorrect MAC output length, expected " + + length + ", got " + value1.length); } mac.update(plainText); byte[] value2 = mac.doFinal();
--- a/test/com/sun/crypto/provider/Mac/HmacSaltLengths.java Tue Feb 12 04:25:26 2019 +0000 +++ b/test/com/sun/crypto/provider/Mac/HmacSaltLengths.java Wed Feb 13 04:21:57 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ -38,6 +38,15 @@ public class HmacSaltLengths { + private static final String[] ALGOS = { + "HmacPBESHA1", + "PBEWithHmacSHA1", + "PBEWithHmacSHA224", + "PBEWithHmacSHA256", + "PBEWithHmacSHA384", + "PBEWithHmacSHA512" + }; + private static void runTest(String alg, byte[] plaintext, char[] password, Provider p) throws Exception { @@ -81,7 +90,9 @@ long start = System.currentTimeMillis(); Provider p = Security.getProvider("SunJCE"); System.out.println("Testing provider " + p.getName() + "..."); - runTest("HmacPBESHA1", input, PASSWD, p); + for (String algo : ALGOS) { + runTest(algo, input, PASSWD, p); + } System.out.println("All tests passed"); long stop = System.currentTimeMillis(); System.out.println("Done (" + (stop - start) + " ms).");