Package com.google.dataconnector.util

Source Code of com.google.dataconnector.util.SessionEncryption$Parse

// Copyright 2010 Google Inc. All Rights Reserved.

package com.google.dataconnector.util;

import com.google.common.base.Preconditions;
import com.google.dataconnector.protocol.FramingException;
import com.google.dataconnector.protocol.proto.SdcFrame.FrameInfo;
import com.google.protobuf.ByteString;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.InvalidProtocolBufferException;

import org.apache.log4j.Logger;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

/**
* Support for session encryption of fetch and socket protocol. This class
* encapsulates the server-generated session encryption key and decrypts fetch
* and socket messages from the server.
*
* @author dchung@google.com (David Chung)
*
*/
public class SessionEncryption {

  /**
   * Default algorithm for session encryption.  For local testing.  This is
   * determined by the server.
   */
  public static final String JCE_ALGO = "DES";

  private static final Logger LOG = Logger.getLogger(SessionEncryption.class);

 
  private final String sessionId;
  private final String algorithm;
  private final byte[] encryptionKey;
  private final Cipher decryptingCipher;
  private final Cipher encryptingCipher;
 
  SessionEncryption()
  throws AgentConfigurationException {
    this(UUID.randomUUID().toString(), JCE_ALGO, newKeyBytes());
  }

  SessionEncryption(String sessionId, String algorithm, byte[] encryptionKey)
    throws AgentConfigurationException {
    Preconditions.checkNotNull(encryptionKey);
    this.sessionId = sessionId;
    this.algorithm = algorithm;
    this.encryptionKey = encryptionKey;
    try {
      SecretKeySpec spec = new SecretKeySpec(this.encryptionKey, this.algorithm);
      this.decryptingCipher = Cipher.getInstance(this.algorithm);
      this.decryptingCipher.init(Cipher.DECRYPT_MODE, spec);
      this.encryptingCipher = Cipher.getInstance(this.algorithm);
      this.encryptingCipher.init(Cipher.ENCRYPT_MODE, spec);
    } catch (NoSuchAlgorithmException e) {
      LOG.fatal("No support for session encryption! ", e);
      throw new AgentConfigurationException(e);
    } catch (NoSuchPaddingException e) {
      LOG.fatal("No support for session encryption! ", e);
      throw new AgentConfigurationException(e);
    } catch (InvalidKeyException e) {
      LOG.fatal("No support for session encryption! ", e);
      throw new AgentConfigurationException(e);
    }
  }

  public String getSessionId() {
    return this.sessionId;
  }
 
  public String getAlgorithm() {
    return this.algorithm;
  }
 
  public byte[] getEncryptionKey() {
    return this.encryptionKey;
  }
 
  public ByteString encrypt(ByteString payload)
    throws AgentConfigurationException {
    String message = "no encrypting cipher";
    if (encryptingCipher != null) {
      try {
        byte[] encrypted = encryptingCipher.doFinal(payload.toByteArray());
        return ByteString.copyFrom(encrypted);
      } catch (BadPaddingException e) {
        message = e.getMessage();
      } catch (IllegalBlockSizeException e) {
        message = e.getMessage();
      }
    }
    throw new AgentConfigurationException("Unable to encrypt: " + message);
  }
 
  public ByteString decrypt(ByteString payload)
    throws AgentConfigurationException {
    String message = "no decrypting cipher";
    if (decryptingCipher != null) {
      try {
        byte[] decrypted = decryptingCipher.doFinal(payload.toByteArray());
        return ByteString.copyFrom(decrypted);
      } catch (BadPaddingException e) {
        message = e.getMessage();
      } catch (IllegalBlockSizeException e) {
        message = e.getMessage();
      }
    }
    throw new AgentConfigurationException("Unable to decrypt: " + message);
  }
 
  public interface Parse<M> {
    public M parse(ByteString s) throws InvalidProtocolBufferException;
  }
 
  public <M> M getFrom(FrameInfo frameInfo, Parse<M> p)
    throws FramingException, InvalidProtocolBufferException {
    Preconditions.checkNotNull(frameInfo);
    String message = "";
    if (!frameInfo.hasPayload()) {
      message = ("No payload in received FrameInfo: " + frameInfo);
      throw new FramingException(message);
    }
    if (!frameInfo.hasSessionId()) {
      message = "Session id missing in fetch protocol.";
      throw new FramingException(message);
    }

    if (!frameInfo.getSessionId().equals(getSessionId())) {
      LOG.warn("Mismatched session id.");
      return null;
    }

    ByteString decrypted = null;
    try {
      long start = System.currentTimeMillis();
      decrypted = decrypt(frameInfo.getPayload());
      long dt = System.currentTimeMillis() - start;

      LOG.debug("Decrypted payload " + decrypted.size() + " bytes in " + dt + " msec.");
    } catch (AgentConfigurationException e) {
      LOG.warn("Cannot decrypt message for fetch protocol:" + e);
      return null;
    }
    return p.parse(decrypted);
  }

  public <M extends GeneratedMessage> FrameInfo toFrameInfo(FrameInfo.Type type, M reply) {
    ByteString encrypted = null;
    try {
      long start = System.currentTimeMillis();
      encrypted = encrypt(reply.toByteString());
      long dt = System.currentTimeMillis() - start;
     
      LOG.debug("Encrypted payload " + encrypted.size() + " bytes in " + dt + " msec.");
    } catch (AgentConfigurationException e) {
      LOG.warn("Cannot encrypt message for fetch protocol:", e);
      return null;
    }

    FrameInfo frame = (FrameInfo.newBuilder()
        .setType(type)
        .setPayload(encrypted)
        .setSessionId(getSessionId())
        .build());
    return frame;
  }

  /**
   * Generates a new key.
   * @return The generated key, in base64 encoding.
   */
  public static byte[] newKeyBytes() {
    try {
      KeyGenerator kg = KeyGenerator.getInstance(JCE_ALGO);
      return kg.generateKey().getEncoded();
    } catch (NoSuchAlgorithmException e) {
    }
    return null;
  }

}
TOP

Related Classes of com.google.dataconnector.util.SessionEncryption$Parse

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.