Package org.keyczar

Source Code of org.keyczar.Encrypter

/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.keyczar;

import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.NoPrimaryKeyException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.EncryptingStream;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.util.Base64Coder;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

/**
* Encrypters are used strictly to encrypt data. Typically, Encrypters will read
* sets of public keys, although may also be instantiated with sets of symmetric
* keys.
*
* {@link Crypter} objects should be used with symmetric or private key sets to
* decrypt data.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Encrypter extends Keyczar {
  private static final Logger LOG =
    Logger.getLogger(Encrypter.class);
  private static final int ENCRYPT_CHUNK_SIZE = 1024;
  private final StreamQueue<EncryptingStream> ENCRYPT_QUEUE =
    new StreamQueue<EncryptingStream>();

  /**
   * Initialize a new Encrypter with a KeyczarReader. The corresponding key set
   * must have a purpose of either
   * {@link org.keyczar.enums.KeyPurpose#ENCRYPT} or
   * {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
   *
   * @param reader A reader to read keys from
   * @throws KeyczarException In the event of an IO error reading keys or if the
   * key set does not have the appropriate purpose.
   */
  public Encrypter(KeyczarReader reader) throws KeyczarException {
    super(reader);
  }

  /**
   * Initialize a new Encrypter with a key set location. This will attempt to
   * read the keys using a KeyczarFileReader. The corresponding key set
   * must have a purpose of either
   * {@link org.keyczar.enums.KeyPurpose#ENCRYPT} or
   * {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}
   *
   * @param fileLocation Directory containing a key set
   * @throws KeyczarException In the event of an IO error reading keys or if the
   * key set does not have the appropriate purpose.
   */
  public Encrypter(String fileLocation) throws KeyczarException {
    super(fileLocation);
  }
 
  /**
   * Returns the size of the ciphertext output that would result from encrypting
   * an input of the given length.
   *
   * @param inputLength The length of the input.
   * @return Length of the ciphertext that would be produced.
   * @throws KeyczarException If the key set contains no primary encrypting key.
   */
  public int ciphertextSize(int inputLength) throws KeyczarException {
    EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
    if (cryptStream == null) {
      KeyczarKey encryptingKey = getPrimaryKey();
      if (encryptingKey == null) {
        throw new NoPrimaryKeyException();
      }
      cryptStream = (EncryptingStream) encryptingKey.getStream();
    }
    SigningStream signStream = cryptStream.getSigningStream();

    int outputSize = HEADER_SIZE + cryptStream.maxOutputSize(inputLength) +
        signStream.digestSize();
    ENCRYPT_QUEUE.add(cryptStream);
    return outputSize;
  }

  /**
   * Encrypt the given input byte array.
   *
   * @param input The input to encrypt
   * @return The encrypted ciphertext
   * @throws KeyczarException If there is a JCE exception or the key set does
   * not contain a primary encrypting key.
   */
  public byte[] encrypt(byte[] input) throws KeyczarException {
    ByteBuffer output = ByteBuffer.allocate(ciphertextSize(input.length));
    encrypt(ByteBuffer.wrap(input), output);
    output.reset();
    byte[] outputBytes = new byte[output.remaining()];
    output.get(outputBytes);
    return outputBytes;
  }

  /**
   * Encrypt the given input ByteBuffer.
   *
   * @param input The input buffer to encrypt. Will not be modified
   * @param output The buffer to write the output ciphertext to.
   * @throws KeyczarException If there is a JCE exception, the key set does
   * not contain a primary encrypting key, or the output buffer is too small.
   */
  public void encrypt(ByteBuffer input, ByteBuffer output)
      throws KeyczarException {
    LOG.debug(Messages.getString("Encrypter.Encrypting", input.remaining()));
    KeyczarKey encryptingKey = getPrimaryKey();
    if (encryptingKey == null) {
      throw new NoPrimaryKeyException() ;
    }
    EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
    if (cryptStream == null) {
      cryptStream = (EncryptingStream) encryptingKey.getStream();
    }
    // Initialize the signing stream
    SigningStream signStream = cryptStream.getSigningStream();
    signStream.initSign();

    // Write the key header
    output.mark();
    ByteBuffer outputToSign = output.asReadOnlyBuffer();
    encryptingKey.copyHeader(output);

    // Write the IV. May be an empty array of zero length
    cryptStream.initEncrypt(output);

    ByteBuffer inputCopy = input.asReadOnlyBuffer();
    while (inputCopy.remaining() > ENCRYPT_CHUNK_SIZE) {
      ByteBuffer inputChunk = inputCopy.slice();
      inputChunk.limit(ENCRYPT_CHUNK_SIZE);
      cryptStream.updateEncrypt(inputChunk, output);
      inputCopy.position(inputCopy.position() + ENCRYPT_CHUNK_SIZE);

      outputToSign.limit(output.position());
      signStream.updateSign(outputToSign);
      outputToSign.position(output.position());
    }

    // Sign any remaining plaintext
    cryptStream.doFinalEncrypt(inputCopy, output);
    output.limit(output.position() + signStream.digestSize());

    // Set the limit on the output to sign
    outputToSign.limit(output.position());
    signStream.updateSign(outputToSign);
    // Sign the final block of ciphertext output
    signStream.sign(output);
    ENCRYPT_QUEUE.add(cryptStream);
  }

  /**
   * Encrypt a String and return a web-safe Base64 encoded ciphertext.
   *
   * @param input An String to encrypt.
   * @return A web-safe Base64 encoded ciphertext.
   * @throws KeyczarException If there is a JCE exception or the key set does
   * not contain a primary encrypting key.
   */
  public String encrypt(String input) throws KeyczarException {
    try {
      return Base64Coder.encode(encrypt(input.getBytes(DEFAULT_ENCODING)));
    } catch (UnsupportedEncodingException e) {
      throw new KeyczarException(e);
    }
  }

  @Override
  boolean isAcceptablePurpose(KeyPurpose purpose) {
    return purpose == KeyPurpose.ENCRYPT
        || purpose == KeyPurpose.DECRYPT_AND_ENCRYPT;
  }
}
TOP

Related Classes of org.keyczar.Encrypter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.