/*
* Copyright 2013 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.interop.operations;
import com.google.gson.Gson;
import org.keyczar.Crypter;
import org.keyczar.KeyczarEncryptedReader;
import org.keyczar.KeyczarFileReader;
import org.keyczar.exceptions.Base64DecodingException;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.util.Base64Coder;
import java.io.File;
import java.util.Map;
/**
* Base class for all operations. An operation is a basic
* functionality of keyczar such as encrypting or signing
* that can be verified. All operations will have a generate
* function that will generate output that can tested using
* the test function.
*/
public abstract class Operation {
public final String keyPath;
public final String testData;
public static Operation getOperationByName(String name, String keyPath, String testData)
throws KeyczarException {
if (name.equals("unversioned")){
return new UnversionedSignOperation(keyPath, testData);
} else if (name.equals("signedSession")){
return new SignedSessionOperation(keyPath, testData);
} else if (name.equals("attached")){
return new AttachedSignOperation(keyPath, testData);
} else if (name.equals("sign")){
return new SignOperation(keyPath, testData);
} else if (name.equals("encrypt")){
return new EncryptOperation(keyPath, testData);
} else {
throw new KeyczarException("Operation does not exist");
}
}
/**
* Sets up the path where keys are stored.
* @return
*/
protected Operation(String keyPath, String testData) {
this.keyPath = keyPath;
this.testData = testData;
}
/**
* Generates output that will later be saved to file and
* tested using the test function in this and other
* implementations of keyczar. An example is the encrypt
* operation which will return the ciphertext.
*
* @param algorithm: name of key algorithm with size
*
* @param *options: additional parameters listed in children
*
* @raise NotImplementedError: If the child class does not implement
*/
public abstract byte[] generate(String algorithm, Map<String, String> generateParams)
throws KeyczarException;
/**
* Will return without error if the input is valid.
*
* Will verify that the data generated by generate
* works correctly. For example in the case of the encrypt
* operation this will decrypt the ciphertext and check if
* the value is equal to what was input as plaintext.
*
* @param algorithm: name of key algorithm with size
* @type algorithm: string
*
* @param chosenParams: list of option names chosen for generate
* @type chosenParams: list of strings
*
* @param *testOptions: additional parameters listed in children
*
* @raise AssertionError: If the test fails
* @raise NotImplementedError: If the child class does not implement
* @param output
* @param algorithm
*/
public abstract void test(
Map<String, String> output, String algorithm,
Map<String, String> generateParams, Map<String, String> testParams)
throws KeyczarException;
/**
* Gets the path of keys for a specific algorithm
* @param algorithm
* @return
*/
public String getKeyPath(String algorithm) {
File file1 = new File(keyPath);
File file2 = new File(file1, algorithm);
return file2.getPath();
}
/**
* Gets a reader to be used by keyczar for the appropriate parameters
* @param algorithm
* @param crypterAlgorithm
* @param pubKey
* @return KeyczarReader
* @throws KeyczarException
*/
public KeyczarReader getReader(
String algorithm, String crypterAlgorithm, String pubKey) throws KeyczarException {
String keysetName = algorithm + crypterAlgorithm;
if (pubKey != null) {
keysetName += pubKey;
}
KeyczarReader reader = new KeyczarFileReader(getKeyPath(keysetName));
if (!crypterAlgorithm.equals("")) {
Crypter crypter = new Crypter(getKeyPath(crypterAlgorithm));
reader = new KeyczarEncryptedReader(reader, crypter);
}
return reader;
}
/**
* Object for gson formatting of output data
*/
static class Output {
public final String output;
public Output(byte[] output) {
this.output = Base64Coder.encodeWebSafe(output);
}
}
/**
* Takes a byte array and returns a json formatted string with output
* @param output
* @return
*/
public String formatOutput(byte[] output){
Gson gson = new Gson();
return gson.toJson(new Output(output));
}
/**
* Undoes formatting of formatOutput (takes in json string returns bytes)
* @param output
* @return
* @throws Base64DecodingException
*/
public byte[] readOutput(Map<String, String> output) throws Base64DecodingException{
return Base64Coder.decodeWebSafe(output.get("output"));
}
}