blob: 8a13b1000c957a01ab6531a7619a7fee4318bae4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.synapse.securevault;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.securevault.definition.CipherInformation;
import org.apache.synapse.securevault.definition.IdentityKeyStoreInformation;
import org.apache.synapse.securevault.definition.KeyStoreInformation;
import org.apache.synapse.securevault.definition.TrustKeyStoreInformation;
import org.apache.synapse.securevault.keystore.IdentityKeyStoreWrapper;
import org.apache.synapse.securevault.keystore.KeyStoreWrapper;
import org.apache.synapse.securevault.keystore.TrustKeyStoreWrapper;
import org.apache.synapse.securevault.secret.SecretInformation;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
/**
* Wraps the cipher and expose abstraction need for synapse ciphering
*/
public abstract class BaseCipher implements EncryptionProvider, DecryptionProvider {
private CipherInformation cipherInformation;
private KeyStoreInformation keystoreInformation;
private static Log log = LogFactory.getLog(BaseCipher.class);
/* Underlying cipher instance*/
private Cipher cipher;
protected KeyStoreWrapper keyStoreWrapper;
private Key key;
protected BaseCipher(CipherInformation cipherInformation,
KeyStoreInformation keystoreInformation) {
this.cipherInformation = cipherInformation;
this.keystoreInformation = keystoreInformation;
if (keystoreInformation instanceof TrustKeyStoreInformation) {
keyStoreWrapper = new TrustKeyStoreWrapper();
((TrustKeyStoreWrapper) keyStoreWrapper).init(
(TrustKeyStoreInformation) keystoreInformation);
} else {
keyStoreWrapper = new IdentityKeyStoreWrapper();
IdentityKeyStoreInformation identityKeyStore =
(IdentityKeyStoreInformation) keystoreInformation;
SecretInformation secretInformation = identityKeyStore.getKeyPasswordProvider();
if (secretInformation != null) { //TODO validate
((IdentityKeyStoreWrapper) keyStoreWrapper).init(identityKeyStore,
secretInformation.getResolvedSecret());
}
}
init();
}
protected BaseCipher(CipherInformation cipherInformation,
KeyStoreWrapper keyStoreWrapper) {
this.keyStoreWrapper = keyStoreWrapper;
this.cipherInformation = cipherInformation;
init();
}
protected BaseCipher(CipherInformation cipherInformation, Key key) {
this.key = key;
this.cipherInformation = cipherInformation;
init();
}
private void init() {
String algorithm = cipherInformation.getAlgorithm();
CipherOperationMode opMode = cipherInformation.getCipherOperationMode();
if (key == null) {
key = getKey(opMode);
}
if (log.isDebugEnabled()) {
log.debug("Initializing cipher with algorithm " +
"'" + algorithm + "' in mode '" + opMode + "'");
}
try {
String provider = cipherInformation.getProvider();
if (provider != null && !"".equals(provider)) {
try {
cipher = Cipher.getInstance(algorithm, provider.trim());
} catch (NoSuchProviderException e) {
throw new SecureVaultException("Invalid Provider : " + provider, log);
}
} else {
cipher = Cipher.getInstance(algorithm);
}
if (opMode == CipherOperationMode.ENCRYPT) {
cipher.init(Cipher.ENCRYPT_MODE, key);
} else if (opMode == CipherOperationMode.DECRYPT) {
cipher.init(Cipher.DECRYPT_MODE, key);
} else {
throw new SecureVaultException("Invalid mode : " + opMode, log);
}
} catch (NoSuchAlgorithmException e) {
throw new SecureVaultException("There is no algorithm support for " +
"'" + algorithm + "' in the operation mode '" + opMode + "'" + e, log);
} catch (NoSuchPaddingException e) {
throw new SecureVaultException("There is no padding scheme for " +
"'" + algorithm + "' in the operation mode '" + opMode + "'" + e, log);
} catch (InvalidKeyException e) {
throw new SecureVaultException("Invalid key ", e, log);
}
}
public CipherInformation getCipherInformation() {
return cipherInformation;
}
public KeyStoreInformation getKeyStoreInformation() {
return keystoreInformation;
}
/**
* Returns the correct key for correct operation
*
* @param operationMode Ciper operation
* @return A key
*/
public abstract Key getKey(CipherOperationMode operationMode);
/**
* Do cryptographic operation
*
* @param inputStream Input Stream
* @return result
*/
private byte[] doCipherOperation(byte[] inputStream) {
InputStream sourceStream = new ByteArrayInputStream(inputStream);
if (cipherInformation.getInType() != null) {
try {
sourceStream = EncodingHelper.decode(
sourceStream, cipherInformation.getInType());
} catch (IOException e) {
throw new SecureVaultException("IOError when decoding the input " +
"stream for cipher ", e, log);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CipherOutputStream out = new CipherOutputStream(baos, cipher);
byte[] buffer = new byte[64];
int length;
try {
while ((length = sourceStream.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
} catch (IOException e) {
throw new SecureVaultException("IOError when reading the input" +
" stream for cipher ", e, log);
} finally {
try {
sourceStream.close();
out.flush();
out.close();
} catch (IOException ignored) {
// ignore exception
}
}
if (cipherInformation.getOutType() != null) {
return EncodingHelper.encode(baos, cipherInformation.getOutType());
} else {
return baos.toByteArray();
}
}
public byte[] encrypt(byte[] plainText) {
return doCipherOperation(plainText);
}
public byte[] decrypt(byte[] cipherText) {
return doCipherOperation(cipherText);
}
}