PKCS12PBECipherCore(String symmCipherAlg, int defKeySize) throws NoSuchAlgorithmException { algo = symmCipherAlg; if (algo.equals("RC4")) { pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8; } else { 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 } } keySize = defKeySize; }
int implGetOutputSize(int inLen) { return cipher.getOutputSize(inLen); }
/** * 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-provided 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. */ protected byte[] engineGetIV() { return core.getIV(); }
/** * Sets the padding mechanism of this cipher. * * @param padding the padding mechanism * @exception NoSuchPaddingException if the requested padding mechanism does not exist */ protected void engineSetPadding(String paddingScheme) throws NoSuchPaddingException { core.setPadding(paddingScheme); }
byte[] implDoFinal(byte[] in, int inOff, int inLen) throws IllegalBlockSizeException, BadPaddingException { return cipher.doFinal(in, inOff, inLen); }
byte[] implWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { return cipher.wrap(key); }
/** * 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 this cipher is in decryption mode, and (un)padding has been * requested, but the decrypted data is not bounded by the appropriate padding bytes */ protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { return core.doFinal(input, inputOffset, inputLen); }
byte[] implUpdate(byte[] in, int inOff, int inLen) { return cipher.update(in, inOff, inLen); }
/** * 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 * @exception IllegalStateException if this cipher is in a wrong state (e.g., has not been * initialized) */ protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { return core.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 */ protected int engineUpdate( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { return core.update(input, inputOffset, inputLen, output, outputOffset); }
protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { core.init(opmode, key, params, random); }
/** * Initializes this cipher with a key and a source of randomness. * * <p>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 requires an initialization vector (IV), it will get it from <code>random * </code>. This behaviour should only be used in encryption or key wrapping mode, however. When * initializing a cipher that requires an IV for decryption or key unwrapping, the IV (same IV * that was used for encryption or key wrapping) must be provided explicitly as a parameter, in * order to get the correct result. * * <p>This method also cleans existing buffer and other related state information. * * @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 secret key * @param random the source of randomness * @exception InvalidKeyException if the given key is inappropriate for initializing this cipher */ protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { core.init(opmode, key, random); }
/** * 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. */ protected AlgorithmParameters engineGetParameters() { return core.getParameters("DES"); }
byte[] implGetIV() { return cipher.getIV(); }
/** * 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 this cipher is in decryption mode, and (un)padding has been * requested, but the decrypted data is not bounded by the appropriate padding bytes */ protected int engineDoFinal( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws IllegalBlockSizeException, ShortBufferException, BadPaddingException { return core.doFinal(input, inputOffset, inputLen, output, outputOffset); }
void implInit( int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random, CipherSpi cipherImpl) throws InvalidKeyException, InvalidAlgorithmParameterException { char[] passwdChars = null; salt = null; 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 (((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher.UNWRAP_MODE)) && ((params == null) && ((salt == null) || (iCount == 0)))) { throw new InvalidAlgorithmParameterException("Parameters missing"); } if (params == null) { // generate default for salt and iteration count if necessary if (salt == null) { salt = new byte[DEFAULT_SALT_LENGTH]; if (random != null) { random.nextBytes(salt); } else { SunJCE.getRandom().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(); } } // salt is recommended to be ideally as long as the output // of the hash function. However, it may be too strict to // force this; so instead, we'll 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"); } byte[] derivedKey = derive(passwdChars, salt, iCount, keySize, CIPHER_KEY); SecretKey cipherKey = new SecretKeySpec(derivedKey, algo); 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); // initialize the underlying cipher cipher.init(opmode, cipherKey, ivSpec, random); } }
/** * 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). */ protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { return core.wrap(key); }
int implUpdate(byte[] in, int inOff, int inLen, byte[] out, int outOff) throws ShortBufferException { return cipher.update(in, inOff, inLen, out, outOff); }
/** * 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>. */ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { return core.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType); }
int implDoFinal(byte[] in, int inOff, int inLen, byte[] out, int outOff) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { return cipher.doFinal(in, inOff, inLen, out, outOff); }
/** * Sets the mode of this cipher. * * @param mode the cipher mode * @exception NoSuchAlgorithmException if the requested cipher mode does not exist */ protected void engineSetMode(String mode) throws NoSuchAlgorithmException { core.setMode(mode); }
Key implUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { return cipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType); }
/** * 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) */ protected int engineGetOutputSize(int inputLen) { return core.getOutputSize(inputLen); }