package org.spongycastle.openpgp.operator.jcajce;
import java.security.Provider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.spongycastle.jcajce.DefaultJcaJceHelper;
import org.spongycastle.jcajce.NamedJcaJceHelper;
import org.spongycastle.jcajce.ProviderJcaJceHelper;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
import org.spongycastle.openpgp.operator.PGPDataDecryptor;
import org.spongycastle.openpgp.operator.PGPDigestCalculatorProvider;
public class JcePBEDataDecryptorFactoryBuilder
{
private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper());
private PGPDigestCalculatorProvider calculatorProvider;
/**
* Base constructor.
*
* @param calculatorProvider a digest calculator provider to provide calculators to support the key generation calculation required.
*/
public JcePBEDataDecryptorFactoryBuilder(PGPDigestCalculatorProvider calculatorProvider)
{
this.calculatorProvider = calculatorProvider;
}
/**
* Set the provider object to use for creating cryptographic primitives in the resulting factory the builder produces.
*
* @param provider provider object for cryptographic primitives.
* @return the current builder.
*/
public JcePBEDataDecryptorFactoryBuilder setProvider(Provider provider)
{
this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider));
return this;
}
/**
* Set the provider name to use for creating cryptographic primitives in the resulting factory the builder produces.
*
* @param providerName the name of the provider to reference for cryptographic primitives.
* @return the current builder.
*/
public JcePBEDataDecryptorFactoryBuilder setProvider(String providerName)
{
this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName));
return this;
}
public PBEDataDecryptorFactory build(char[] passPhrase)
{
return new PBEDataDecryptorFactory(passPhrase, calculatorProvider)
{
public byte[] recoverSessionData(int keyAlgorithm, byte[] key, byte[] secKeyData)
throws PGPException
{
try
{
if (secKeyData != null && secKeyData.length > 0)
{
String cipherName = PGPUtil.getSymmetricCipherName(keyAlgorithm);
Cipher keyCipher = helper.createCipher(cipherName + "/CFB/NoPadding");
keyCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, cipherName), new IvParameterSpec(new byte[keyCipher.getBlockSize()]));
return keyCipher.doFinal(secKeyData);
}
else
{
byte[] keyBytes = new byte[key.length + 1];
keyBytes[0] = (byte)keyAlgorithm;
System.arraycopy(key, 0, keyBytes, 1, key.length);
return keyBytes;
}
}
catch (Exception e)
{
throw new PGPException("Exception recovering session info", e);
}
}
public PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key)
throws PGPException
{
return helper.createDataDecryptor(withIntegrityPacket, encAlgorithm, key);
}
};
}
}