package org.spongycastle.openpgp.operator.jcajce; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.Signature; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.jcajce.JcaJceHelper; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.operator.PGPDataDecryptor; import org.spongycastle.openpgp.operator.PGPDigestCalculator; class OperatorHelper { private JcaJceHelper helper; OperatorHelper(JcaJceHelper helper) { this.helper = helper; } MessageDigest createDigest(int algorithm) throws GeneralSecurityException, PGPException { MessageDigest dig; dig = helper.createDigest(PGPUtil.getDigestName(algorithm)); return dig; } KeyFactory createKeyFactory(String algorithm) throws GeneralSecurityException, PGPException { return helper.createKeyFactory(algorithm); } PGPDataDecryptor createDataDecryptor(boolean withIntegrityPacket, int encAlgorithm, byte[] key) throws PGPException { try { SecretKey secretKey = new SecretKeySpec(key, PGPUtil.getSymmetricCipherName(encAlgorithm)); final Cipher c = createStreamCipher(encAlgorithm, withIntegrityPacket); byte[] iv = new byte[c.getBlockSize()]; c.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv)); return new PGPDataDecryptor() { public InputStream getInputStream(InputStream in) { return new CipherInputStream(in, c); } public int getBlockSize() { return c.getBlockSize(); } public PGPDigestCalculator getIntegrityCalculator() { return new SHA1PGPDigestCalculator(); } }; } catch (PGPException e) { throw e; } catch (Exception e) { throw new PGPException("Exception creating cipher", e); } } Cipher createStreamCipher(int encAlgorithm, boolean withIntegrityPacket) throws PGPException { String mode = (withIntegrityPacket) ? "CFB" : "OpenPGPCFB"; String cName = PGPUtil.getSymmetricCipherName(encAlgorithm) + "/" + mode + "/NoPadding"; return createCipher(cName); } Cipher createCipher(String cipherName) throws PGPException { try { return helper.createCipher(cipherName); } catch (GeneralSecurityException e) { throw new PGPException("cannot create cipher: " + e.getMessage(), e); } } Cipher createPublicKeyCipher(int encAlgorithm) throws PGPException { switch (encAlgorithm) { case PGPPublicKey.RSA_ENCRYPT: case PGPPublicKey.RSA_GENERAL: return createCipher("RSA/ECB/PKCS1Padding"); case PGPPublicKey.ELGAMAL_ENCRYPT: case PGPPublicKey.ELGAMAL_GENERAL: return createCipher("ElGamal/ECB/PKCS1Padding"); case PGPPublicKey.DSA: throw new PGPException("Can't use DSA for encryption."); case PGPPublicKey.ECDSA: throw new PGPException("Can't use ECDSA for encryption."); default: throw new PGPException("unknown asymmetric algorithm: " + encAlgorithm); } } private Signature createSignature(String cipherName) throws PGPException { try { return helper.createSignature(cipherName); } catch (GeneralSecurityException e) { throw new PGPException("cannot create signature: " + e.getMessage(), e); } } public Signature createSignature(int keyAlgorithm, int hashAlgorithm) throws PGPException { String encAlg; switch (keyAlgorithm) { case PublicKeyAlgorithmTags.RSA_GENERAL: case PublicKeyAlgorithmTags.RSA_SIGN: encAlg = "RSA"; break; case PublicKeyAlgorithmTags.DSA: encAlg = "DSA"; break; case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: // in some malformed cases. case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: encAlg = "ElGamal"; break; default: throw new PGPException("unknown algorithm tag in signature:" + keyAlgorithm); } return createSignature(PGPUtil.getDigestName(hashAlgorithm) + "with" + encAlg); } }