package org.bouncycastle.openpgp;

import java.io.InputStream;
import java.security.NoSuchProviderException;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;

import org.bouncycastle.bcpg.BCPGInputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.bcpg.InputStreamPacket;
import org.bouncycastle.bcpg.PacketTags;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyEncSessionPacket;

/**
 * A password based encryption object.
 */
public class PGPPBEEncryptedData
	implements PacketTags, PublicKeyAlgorithmTags, SymmetricKeyAlgorithmTags, HashAlgorithmTags
{
	SymmetricKeyEncSessionPacket	keyData;
	InputStreamPacket						encData;
	
	PGPPBEEncryptedData(
		SymmetricKeyEncSessionPacket	keyData,
		InputStreamPacket						encData)
	{
		this.keyData = keyData;
		this.encData = encData;
	}
	
	/**
	 * Return the raw input stream for the data stream.
	 * 
	 * @return InputStream
	 */
	public InputStream getInputStream()
	{
		return encData.getInputStream();
	}
	
	/**
	 * Return the decrypted input stream, using the passed in passPhrase.
	 * 
	 * @param passPhrase
	 * @param provider
	 * @return InputStream
	 * @throws PGPException
	 * @throws NoSuchProviderException
	 */
	public InputStream getDataStream(
		char[]				passPhrase,
		String				provider)
		throws PGPException, NoSuchProviderException
	{		
		Cipher c;
		
        try
        {
            c = Cipher.getInstance(
                    PGPUtil.getSymmetricCipherName(keyData.getEncAlgorithm())
                        + "/PGPCFBwithIV/NoPadding",
                    provider);
        }
        catch (PGPException e)
        {
        	throw e;
        }
        catch (NoSuchProviderException e)
        {
			throw e;
        }
        catch (Exception e)
        {
			throw new PGPException("exception creating cipher", e);
        }
		
		if (c != null)
		{
			try
			{
				SecretKey	key = PGPUtil.makeKeyFromPassPhrase(keyData.getEncAlgorithm(), keyData.getS2K(), passPhrase, provider);
				
				BCPGInputStream	encStream = encData.getInputStream();
				
				c.init(Cipher.DECRYPT_MODE, key);
				
				return new CipherInputStream(encStream, c);
			}
			catch (Exception e)
			{ 
				throw new PGPException("Exception creating cipher", e);
			}
		}
		else
		{
			return encData.getInputStream();
		}
	}
}
