JceCipher.java

  1.  /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.commons.crypto.cipher;

  19. import java.nio.ByteBuffer;
  20. import java.security.GeneralSecurityException;
  21. import java.security.InvalidAlgorithmParameterException;
  22. import java.security.InvalidKeyException;
  23. import java.security.Key;
  24. import java.security.spec.AlgorithmParameterSpec;
  25. import java.util.Objects;
  26. import java.util.Properties;

  27. import javax.crypto.BadPaddingException;
  28. import javax.crypto.Cipher;
  29. import javax.crypto.IllegalBlockSizeException;
  30. import javax.crypto.ShortBufferException;

  31. /**
  32.  * Implements the {@link CryptoCipher} using JCE provider.
  33.  * <p>
  34.  * This class is not public/protected so does not appear in the main Javadoc. Please ensure that property use is documented in the enum
  35.  * CryptoRandomFactory.RandomProvider
  36.  * </p>
  37.  */
  38. class JceCipher implements CryptoCipher {
  39.     private final Cipher cipher;

  40.     /**
  41.      * Constructs a {@link CryptoCipher} based on JCE Cipher {@link Cipher}.
  42.      *
  43.      * @param props  properties for JCE cipher (only uses {@link CryptoCipherFactory#JCE_PROVIDER_KEY})
  44.      * @param transformation  transformation for JCE cipher (algorithm/mode/padding)
  45.      * @throws GeneralSecurityException if JCE cipher initialize failed
  46.      */
  47.     public JceCipher(final Properties props, final String transformation)
  48.             throws GeneralSecurityException {
  49.         final String provider = props.getProperty(CryptoCipherFactory.JCE_PROVIDER_KEY, "");
  50.         cipher = provider.isEmpty() ? Cipher.getInstance(transformation) : Cipher.getInstance(transformation, provider);
  51.     }

  52.     /**
  53.      * Closes Jce cipher.
  54.      */
  55.     @Override
  56.     public void close() {
  57.         // Do nothing
  58.     }

  59.     /**
  60.      * Encrypts or decrypts data in a single-part operation, or finishes a
  61.      * multiple-part operation.
  62.      *
  63.      * @param input the input byte array
  64.      * @param inputOffset the offset in input where the input starts
  65.      * @param inputLen the input length
  66.      * @param output the byte array for the result
  67.      * @param outputOffset the offset in output where the result is stored
  68.      * @return the number of bytes stored in output
  69.      * @throws ShortBufferException if the given output byte array is too small
  70.      *         to hold the result
  71.      * @throws BadPaddingException if this cipher is in decryption mode, and
  72.      *         (un)padding has been requested, but the decrypted data is not
  73.      *         bounded by the appropriate padding bytes
  74.      * @throws IllegalBlockSizeException if this cipher is a block cipher, no
  75.      *         padding has been requested (only in encryption mode), and the
  76.      *         total input length of the data processed by this cipher is not a
  77.      *         multiple of block size; or if this encryption algorithm is unable
  78.      *         to process the input data provided.
  79.      */
  80.     @Override
  81.     public int doFinal(final byte[] input, final int inputOffset, final int inputLen,
  82.             final byte[] output, final int outputOffset) throws ShortBufferException,
  83.             IllegalBlockSizeException, BadPaddingException {
  84.         return cipher.doFinal(input, inputOffset, inputLen, output,
  85.                 outputOffset);
  86.     }

  87.     /**
  88.      * Encrypts or decrypts data in a single-part operation, or finishes a
  89.      * multiple-part operation. The data is encrypted or decrypted, depending on
  90.      * how this cipher was initialized.
  91.      *
  92.      * @param inBuffer the input ByteBuffer
  93.      * @param outBuffer the output ByteBuffer
  94.      * @return int number of bytes stored in {@code output}
  95.      * @throws BadPaddingException if this cipher is in decryption mode, and
  96.      *         (un)padding has been requested, but the decrypted data is not
  97.      *         bounded by the appropriate padding bytes
  98.      * @throws IllegalBlockSizeException if this cipher is a block cipher, no
  99.      *         padding has been requested (only in encryption mode), and the
  100.      *         total input length of the data processed by this cipher is not a
  101.      *         multiple of block size; or if this encryption algorithm is unable
  102.      *         to process the input data provided.
  103.      * @throws ShortBufferException if the given output buffer is too small to
  104.      *         hold the result
  105.      */
  106.     @Override
  107.     public int doFinal(final ByteBuffer inBuffer, final ByteBuffer outBuffer)
  108.             throws ShortBufferException, IllegalBlockSizeException,
  109.             BadPaddingException {
  110.         return cipher.doFinal(inBuffer, outBuffer);
  111.     }

  112.     /**
  113.      * Returns the algorithm name of this {@code CryptoCipher} object.
  114.      *
  115.      * <p>
  116.      * This is the same name that was specified in one of the
  117.      * {@code CryptoCipherFactory#getInstance} calls that created this
  118.      * {@code CryptoCipher} object..
  119.      * </p>
  120.      *
  121.      * @return the algorithm name of this {@code CryptoCipher} object.
  122.      */
  123.     @Override
  124.     public String getAlgorithm() {
  125.         return cipher.getAlgorithm();
  126.     }

  127.     /**
  128.      * Returns the block size (in bytes).
  129.      *
  130.      * @return the block size (in bytes), or 0 if the underlying algorithm is
  131.      * not a block cipher
  132.      */
  133.     @Override
  134.     public final int getBlockSize() {
  135.         return cipher.getBlockSize();
  136.     }

  137.     /**
  138.      * Initializes the cipher with mode, key and iv.
  139.      *
  140.      * @param mode {@link Cipher#ENCRYPT_MODE} or {@link Cipher#DECRYPT_MODE}
  141.      * @param key crypto key for the cipher
  142.      * @param params the algorithm parameters
  143.      * @throws InvalidAlgorithmParameterException if the given algorithm
  144.      *         parameters are inappropriate for this cipher, or this cipher
  145.      *         requires algorithm parameters and {@code params} is null, or
  146.      *         the given algorithm parameters imply a cryptographic strength
  147.      *         that would exceed the legal limits (as determined from the
  148.      *         configured jurisdiction policy files).
  149.      */
  150.     @Override
  151.     public void init(final int mode, final Key key, final AlgorithmParameterSpec params)
  152.             throws InvalidKeyException, InvalidAlgorithmParameterException {
  153.         Objects.requireNonNull(key, "key");
  154.         Objects.requireNonNull(params, "params");

  155.         // Jce uses the javax.crypto.Cipher modes; no need to convert the input
  156.         cipher.init(mode, key, params);
  157.     }

  158.     /**
  159.      * Continues a multiple-part encryption/decryption operation. The data is
  160.      * encrypted or decrypted, depending on how this cipher was initialized.
  161.      *
  162.      * @param input the input byte array
  163.      * @param inputOffset the offset in input where the input starts
  164.      * @param inputLen the input length
  165.      * @param output the byte array for the result
  166.      * @param outputOffset the offset in output where the result is stored
  167.      * @return the number of bytes stored in output
  168.      * @throws ShortBufferException if there is insufficient space in the output
  169.      *         byte array
  170.      */
  171.     @Override
  172.     public int update(final byte[] input, final int inputOffset, final int inputLen,
  173.             final byte[] output, final int outputOffset) throws ShortBufferException {
  174.         return cipher
  175.                 .update(input, inputOffset, inputLen, output, outputOffset);
  176.     }


  177.     /**
  178.      * Continues a multiple-part encryption/decryption operation. The data is
  179.      * encrypted or decrypted, depending on how this cipher was initialized.
  180.      *
  181.      * @param inBuffer the input ByteBuffer
  182.      * @param outBuffer the output ByteBuffer
  183.      * @return int number of bytes stored in {@code output}
  184.      * @throws ShortBufferException if there is insufficient space in the output
  185.      *         buffer
  186.      */
  187.     @Override
  188.     public int update(final ByteBuffer inBuffer, final ByteBuffer outBuffer)
  189.             throws ShortBufferException {
  190.         return cipher.update(inBuffer, outBuffer);
  191.     }

  192.     /**
  193.      * Continues a multi-part update of the Additional Authentication
  194.      * Data (AAD).
  195.      * <p>
  196.      * Calls to this method provide AAD to the cipher when operating in
  197.      * modes such as AEAD (GCM/CCM).  If this cipher is operating in
  198.      * either GCM or CCM mode, all AAD must be supplied before beginning
  199.      * operations on the ciphertext (via the {@code update} and
  200.      * {@code doFinal} methods).
  201.      * </p>
  202.      *
  203.      * @param aad the buffer containing the Additional Authentication Data
  204.      *
  205.      * @throws IllegalArgumentException if the {@code aad}
  206.      * byte array is null
  207.      * @throws IllegalStateException if this cipher is in a wrong state
  208.      * (e.g., has not been initialized), does not accept AAD, or if
  209.      * operating in either GCM or CCM mode and one of the {@code update}
  210.      * methods has already been called for the active
  211.      * encryption/decryption operation
  212.      * @throws UnsupportedOperationException if JCE's implementation does not
  213.      * support such operation
  214.      */
  215.     @Override
  216.     public void updateAAD(final byte[] aad) {
  217.         cipher.updateAAD(aad);
  218.     }


  219.     /**
  220.      * Continues a multi-part update of the Additional Authentication
  221.      * Data (AAD).
  222.      * <p>
  223.      * Calls to this method provide AAD to the cipher when operating in
  224.      * modes such as AEAD (GCM/CCM).  If this cipher is operating in
  225.      * either GCM or CCM mode, all AAD must be supplied before beginning
  226.      * operations on the ciphertext (via the {@code update} and
  227.      * {@code doFinal} methods).
  228.      * </p>
  229.      *
  230.      * @param aad the buffer containing the Additional Authentication Data
  231.      *
  232.      * @throws IllegalArgumentException if the {@code aad}
  233.      * byte array is null
  234.      * @throws IllegalStateException if this cipher is in a wrong state
  235.      * (e.g., has not been initialized), does not accept AAD, or if
  236.      * operating in either GCM or CCM mode and one of the {@code update}
  237.      * methods has already been called for the active
  238.      * encryption/decryption operation
  239.      * @throws UnsupportedOperationException if JCE's implementation does not
  240.      * support such operation
  241.      */
  242.     @Override
  243.     public void updateAAD(final ByteBuffer aad) {
  244.         cipher.updateAAD(aad);
  245.     }
  246. }