* derived from the public key in the given certificate, the underlying * cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an <code> * InvalidKeyException</code> if it is being initialized for decryption or * key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the * <code>SecureRandom</code> * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @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 certificate the certificate * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate) throws InvalidKeyException { init(opmode, certificate, JceSecurity.RANDOM); } /** * Initializes this cipher with the public key from the given certificate * 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 the certificate is of type X.509 and has a <i>key usage</i> * extension field marked as critical, and the value of the <i>key usage</i> * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for the operation represented by the value of * <code>opmode</code>, * an <code>InvalidKeyException</code> * is thrown. * * <p>If this cipher requires any algorithm parameters that cannot be * derived from the public key in the given <code>certificate</code>, * the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * <code>InvalidKeyException</code> if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from <code>random</code>. * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @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 certificate the certificate * @param random the source of randomness * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher * requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate, SecureRandom random) throws InvalidKeyException { initialized = false; checkOpmode(opmode); // Check key usage if the certificate is of // type X.509. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. X509Certificate cert = (X509Certificate)certificate; Set critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains(KEY_USAGE_EXTENSION_OID)) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[2] is for keyEncipherment; // keyUsageInfo[3] is for dataEncipherment. if ((keyUsageInfo != null) && (((opmode == Cipher.ENCRYPT_MODE) && (keyUsageInfo.length > 3) && (keyUsageInfo[3] == false)) || ((opmode == Cipher.WRAP_MODE) && (keyUsageInfo.length > 2) && (keyUsageInfo[2] == false)))) { throw new InvalidKeyException("Wrong key usage"); } } } PublicKey publicKey = (certificate==null? null:certificate.getPublicKey()); if (spi != null) { checkCryptoPerm(spi, publicKey); spi.engineInit(opmode, publicKey, random); } else { try { chooseProvider(I_CERT, opmode, publicKey, null, null, random); } catch (InvalidAlgorithmParameterException e) { // should never occur throw new InvalidKeyException(e); } } initialized = true; this.opmode = opmode; } /** * Ensures that Cipher is in a valid state for update() and doFinal() * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE. * @throws IllegalStateException if Cipher object is not in valid state. */ private void checkCipherState() { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) { throw new IllegalStateException("Cipher not initialized " + "for encryption/decryption"); } } } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * * <p>The bytes in the <code>input</code> buffer are processed, and the * result is stored in a new buffer. * * <p>If <code>input</code> has a length of zero, this method returns * <code>null</code>. * * @param input the input buffer * * @return the new buffer with the result, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input) { checkCipherState(); // Input sanity check if (input == null) { throw new IllegalArgumentException("Null input buffer"); } chooseFirstProvider(); if (input.length == 0) { return null; } return spi.engineUpdate(input, 0, input.length); } /** * 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> inclusive, are processed, * and the result is stored in a new buffer. * * <p>If <code>inputLen</code> is zero, this method returns * <code>null</code>. * * @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, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input, int inputOffset, int inputLen) { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return null; } return spi.engineUpdate(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> inclusive, are processed, * and the result is stored in the <code>output</code> buffer. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>If <code>inputLen</code> is zero, this method returns * a length of zero. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @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 * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, 0); } /** * 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> inclusive, are processed, * and the result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>If <code>inputLen</code> is zero, this method returns * a length of zero. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @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 IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0 || outputOffset < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, outputOffset); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * * <p>All <code>input.remaining()</code> bytes starting at * <code>input.position()</code> are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * * <p>If <code>output.remaining()</code> bytes are insufficient to * hold the result, a <code>ShortBufferException</code> is thrown. * In this case, repeat this call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same block of memory and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input ByteBuffer * @param output the output ByteByffer * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalArgumentException if input and output are the * same object * @exception ReadOnlyBufferException if the output buffer is read-only * @exception ShortBufferException if there is insufficient space in the * output buffer * @since 1.5 */ public final int update(ByteBuffer input, ByteBuffer output) throws ShortBufferException { checkCipherState(); if ((input == null) || (output == null)) { throw new IllegalArgumentException("Buffers must not be null"); } if (input == output) { throw new IllegalArgumentException("Input and output buffers must " + "not be the same object, consider using buffer.duplicate()"); } if (output.isReadOnly()) { throw new ReadOnlyBufferException(); } chooseFirstProvider(); return spi.engineUpdate(input, output); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * * <p>Input data that may have been buffered during a previous * <code>update</code> operation is processed, with padding (if requested) * being applied. * If an AEAD mode such as GCM/CCM is being used, the authentication * tag is appended in the case of encryption, or verified in the * case of decryption. * The result is stored in a new buffer. * * <p>Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to <code>init</code>. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * <code>init</code>) more data. * * <p>Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @return the new buffer with the result * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @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; or if this encryption algorithm is unable to * process the input data provided. * @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 * @exception AEADBadTagException if this cipher is decrypting in an * AEAD mode (such as GCM/CCM), and the received authentication tag * does not match the calculated value */ public final byte[] doFinal() throws IllegalBlockSizeException, BadPaddingException { checkCipherState(); chooseFirstProvider(); return spi.engineDoFinal(null, 0, 0); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * * <p>Input data that may have been buffered during a previous * <code>update</code> operation is processed, with padding (if requested) * being applied. * If an AEAD mode such as GCM/CCM is being used, the authentication * tag is appended in the case of encryption, or verified in the * case of decryption. * The result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to <code>init</code>. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * <code>init</code>) more data. * * <p>Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param output the buffer for the resultLines 1501–2000 of 2677. Previous lines Load more
* derived from the public key in the given certificate, the underlying * cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an <code> * InvalidKeyException</code> if it is being initialized for decryption or * key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the * <code>SecureRandom</code> * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @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 certificate the certificate * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate) throws InvalidKeyException { init(opmode, certificate, JceSecurity.RANDOM); } /** * Initializes this cipher with the public key from the given certificate * 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 the certificate is of type X.509 and has a <i>key usage</i> * extension field marked as critical, and the value of the <i>key usage</i> * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for the operation represented by the value of * <code>opmode</code>, * an <code>InvalidKeyException</code> * is thrown. * * <p>If this cipher requires any algorithm parameters that cannot be * derived from the public key in the given <code>certificate</code>, * the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * <code>InvalidKeyException</code> if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * * <p>If this cipher requires algorithm parameters that cannot be * derived from the input parameters, and there are no reasonable * provider-specific default values, initialization will * necessarily fail. * * <p>If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from <code>random</code>. * * <p>Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @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 certificate the certificate * @param random the source of randomness * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher * requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate, SecureRandom random) throws InvalidKeyException { initialized = false; checkOpmode(opmode); // Check key usage if the certificate is of // type X.509. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. X509Certificate cert = (X509Certificate)certificate; Set critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains(KEY_USAGE_EXTENSION_OID)) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[2] is for keyEncipherment; // keyUsageInfo[3] is for dataEncipherment. if ((keyUsageInfo != null) && (((opmode == Cipher.ENCRYPT_MODE) && (keyUsageInfo.length > 3) && (keyUsageInfo[3] == false)) || ((opmode == Cipher.WRAP_MODE) && (keyUsageInfo.length > 2) && (keyUsageInfo[2] == false)))) { throw new InvalidKeyException("Wrong key usage"); } } } PublicKey publicKey = (certificate==null? null:certificate.getPublicKey()); if (spi != null) { checkCryptoPerm(spi, publicKey); spi.engineInit(opmode, publicKey, random); } else { try { chooseProvider(I_CERT, opmode, publicKey, null, null, random); } catch (InvalidAlgorithmParameterException e) { // should never occur throw new InvalidKeyException(e); } } initialized = true; this.opmode = opmode; } /** * Ensures that Cipher is in a valid state for update() and doFinal() * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE. * @throws IllegalStateException if Cipher object is not in valid state. */ private void checkCipherState() { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) { throw new IllegalStateException("Cipher not initialized " + "for encryption/decryption"); } } } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * * <p>The bytes in the <code>input</code> buffer are processed, and the * result is stored in a new buffer. * * <p>If <code>input</code> has a length of zero, this method returns * <code>null</code>. * * @param input the input buffer * * @return the new buffer with the result, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input) { checkCipherState(); // Input sanity check if (input == null) { throw new IllegalArgumentException("Null input buffer"); } chooseFirstProvider(); if (input.length == 0) { return null; } return spi.engineUpdate(input, 0, input.length); } /** * 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> inclusive, are processed, * and the result is stored in a new buffer. * * <p>If <code>inputLen</code> is zero, this method returns * <code>null</code>. * * @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, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input, int inputOffset, int inputLen) { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return null; } return spi.engineUpdate(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> inclusive, are processed, * and the result is stored in the <code>output</code> buffer. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>If <code>inputLen</code> is zero, this method returns * a length of zero. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @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 * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, 0); } /** * 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> inclusive, are processed, * and the result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>If <code>inputLen</code> is zero, this method returns * a length of zero. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @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 IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0 || outputOffset < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, outputOffset); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * * <p>All <code>input.remaining()</code> bytes starting at * <code>input.position()</code> are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * * <p>If <code>output.remaining()</code> bytes are insufficient to * hold the result, a <code>ShortBufferException</code> is thrown. * In this case, repeat this call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>Note: this method should be copy-safe, which means the * <code>input</code> and <code>output</code> buffers can reference * the same block of memory and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input ByteBuffer * @param output the output ByteByffer * * @return the number of bytes stored in <code>output</code> * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalArgumentException if input and output are the * same object * @exception ReadOnlyBufferException if the output buffer is read-only * @exception ShortBufferException if there is insufficient space in the * output buffer * @since 1.5 */ public final int update(ByteBuffer input, ByteBuffer output) throws ShortBufferException { checkCipherState(); if ((input == null) || (output == null)) { throw new IllegalArgumentException("Buffers must not be null"); } if (input == output) { throw new IllegalArgumentException("Input and output buffers must " + "not be the same object, consider using buffer.duplicate()"); } if (output.isReadOnly()) { throw new ReadOnlyBufferException(); } chooseFirstProvider(); return spi.engineUpdate(input, output); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * * <p>Input data that may have been buffered during a previous * <code>update</code> operation is processed, with padding (if requested) * being applied. * If an AEAD mode such as GCM/CCM is being used, the authentication * tag is appended in the case of encryption, or verified in the * case of decryption. * The result is stored in a new buffer. * * <p>Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to <code>init</code>. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * <code>init</code>) more data. * * <p>Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @return the new buffer with the result * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @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; or if this encryption algorithm is unable to * process the input data provided. * @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 * @exception AEADBadTagException if this cipher is decrypting in an * AEAD mode (such as GCM/CCM), and the received authentication tag * does not match the calculated value */ public final byte[] doFinal() throws IllegalBlockSizeException, BadPaddingException { checkCipherState(); chooseFirstProvider(); return spi.engineDoFinal(null, 0, 0); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * * <p>Input data that may have been buffered during a previous * <code>update</code> operation is processed, with padding (if requested) * being applied. * If an AEAD mode such as GCM/CCM is being used, the authentication * tag is appended in the case of encryption, or verified in the * case of decryption. * The result is stored in the <code>output</code> buffer, starting at * <code>outputOffset</code> inclusive. * * <p>If the <code>output</code> buffer is too small to hold the result, * a <code>ShortBufferException</code> is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * <p>Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to <code>init</code>. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * <code>init</code>) more data. * * <p>Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param output the buffer for the result