package org.spongycastle.openpgp.operator.jcajce; import java.security.InvalidKeyException; import java.security.Provider; import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; 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.PBESecretKeyEncryptor; import org.spongycastle.openpgp.operator.PGPDigestCalculator; public class JcePBESecretKeyEncryptorBuilder { private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); private int encAlgorithm; private PGPDigestCalculator s2kDigestCalculator; private SecureRandom random; public JcePBESecretKeyEncryptorBuilder(int encAlgorithm) { this(encAlgorithm, new SHA1PGPDigestCalculator()); } public JcePBESecretKeyEncryptorBuilder(int encAlgorithm, PGPDigestCalculator s2kDigestCalculator) { this.encAlgorithm = encAlgorithm; this.s2kDigestCalculator = s2kDigestCalculator; } public JcePBESecretKeyEncryptorBuilder setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); return this; } public JcePBESecretKeyEncryptorBuilder setProvider(String providerName) { this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); return this; } /** * Provide a user defined source of randomness. * * @param random the secure random to be used. * @return the current builder. */ public JcePBESecretKeyEncryptorBuilder setSecureRandom(SecureRandom random) { this.random = random; return this; } public PBESecretKeyEncryptor build(char[] passPhrase) { if (random == null) { random = new SecureRandom(); } return new PBESecretKeyEncryptor(encAlgorithm, s2kDigestCalculator, random, passPhrase) { private Cipher c; private byte[] iv; public byte[] encryptKeyData(byte[] key, byte[] keyData, int keyOff, int keyLen) throws PGPException { try { c = helper.createCipher(PGPUtil.getSymmetricCipherName(this.encAlgorithm) + "/CFB/NoPadding"); c.init(Cipher.ENCRYPT_MODE, PGPUtil.makeSymmetricKey(this.encAlgorithm, key), this.random); iv = c.getIV(); return c.doFinal(keyData, keyOff, keyLen); } catch (IllegalBlockSizeException e) { throw new PGPException("illegal block size: " + e.getMessage(), e); } catch (BadPaddingException e) { throw new PGPException("bad padding: " + e.getMessage(), e); } catch (InvalidKeyException e) { throw new PGPException("invalid key: " + e.getMessage(), e); } } public byte[] getCipherIV() { return iv; } }; } }