diff options
Diffstat (limited to 'pg/src/main/jdk1.1/org/spongycastle')
3 files changed, 561 insertions, 0 deletions
diff --git a/pg/src/main/jdk1.1/org/spongycastle/openpgp/examples/DetachedSignatureProcessor.java b/pg/src/main/jdk1.1/org/spongycastle/openpgp/examples/DetachedSignatureProcessor.java new file mode 100644 index 00000000..eca9f352 --- /dev/null +++ b/pg/src/main/jdk1.1/org/spongycastle/openpgp/examples/DetachedSignatureProcessor.java @@ -0,0 +1,199 @@ +package org.spongycastle.openpgp.examples; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.SignatureException; +import java.security.Security; + +import org.spongycastle.bcpg.ArmoredOutputStream; +import org.spongycastle.bcpg.BCPGOutputStream; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.openpgp.PGPCompressedData; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyRingCollection; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPSignature; +import org.spongycastle.openpgp.PGPSignatureGenerator; +import org.spongycastle.openpgp.PGPSignatureList; +import org.spongycastle.openpgp.PGPUtil; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider; +import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; + +/** + * A simple utility class that creates seperate signatures for files and verifies them. + * <p> + * To sign a file: DetachedSignatureProcessor -s [-a] fileName secretKey passPhrase.<br> + * If -a is specified the output file will be "ascii-armored". + * <p> + * To decrypt: DetachedSignatureProcessor -v fileName signatureFile publicKeyFile. + * <p> + * Note: this example will silently overwrite files. + * It also expects that a single pass phrase + * will have been used. + */ +public class DetachedSignatureProcessor +{ + private static void verifySignature( + String fileName, + String inputFileName, + String keyFileName) + throws GeneralSecurityException, IOException, PGPException, SignatureException + { + InputStream in = new BufferedInputStream(new FileInputStream(inputFileName)); + InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName)); + + verifySignature(fileName, in, keyIn); + + keyIn.close(); + in.close(); + } + + /* + * verify the signature in in against the file fileName. + */ + private static void verifySignature( + String fileName, + InputStream in, + InputStream keyIn) + throws GeneralSecurityException, IOException, PGPException, SignatureException + { + in = PGPUtil.getDecoderStream(in); + + PGPObjectFactory pgpFact = new PGPObjectFactory(in); + PGPSignatureList p3; + + Object o = pgpFact.nextObject(); + if (o instanceof PGPCompressedData) + { + PGPCompressedData c1 = (PGPCompressedData)o; + + pgpFact = new PGPObjectFactory(c1.getDataStream()); + + p3 = (PGPSignatureList)pgpFact.nextObject(); + } + else + { + p3 = (PGPSignatureList)o; + } + + PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn)); + + + InputStream dIn = new BufferedInputStream(new FileInputStream(fileName)); + + PGPSignature sig = p3.get(0); + PGPPublicKey key = pgpPubRingCollection.getPublicKey(sig.getKeyID()); + + sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider("SC"), key); + + int ch; + while ((ch = dIn.read()) >= 0) + { + sig.update((byte)ch); + } + + dIn.close(); + + if (sig.verify()) + { + System.out.println("signature verified."); + } + else + { + System.out.println("signature verification failed."); + } + } + + private static void createSignature( + String inputFileName, + String keyFileName, + String outputFileName, + char[] pass, + boolean armor) + throws GeneralSecurityException, IOException, PGPException, SignatureException + { + InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName)); + OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName)); + + createSignature(inputFileName, keyIn, out, pass, armor); + + out.close(); + keyIn.close(); + } + + private static void createSignature( + String fileName, + InputStream keyIn, + OutputStream out, + char[] pass, + boolean armor) + throws GeneralSecurityException, IOException, PGPException, SignatureException + { + if (armor) + { + out = new ArmoredOutputStream(out); + } + + PGPSecretKey pgpSec = PGPExampleUtil.readSecretKey(keyIn); + PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("SC").build(pass)); + PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setProvider("SC")); + + sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey); + + BCPGOutputStream bOut = new BCPGOutputStream(out); + + InputStream fIn = new BufferedInputStream(new FileInputStream(fileName)); + + int ch; + while ((ch = fIn.read()) >= 0) + { + sGen.update((byte)ch); + } + + fIn.close(); + + sGen.generate().encode(bOut); + + if (armor) + { + out.close(); + } + } + + public static void main( + String[] args) + throws Exception + { + Security.addProvider(new BouncyCastleProvider()); + + if (args[0].equals("-s")) + { + if (args[1].equals("-a")) + { + createSignature(args[2], args[3], args[2] + ".asc", args[4].toCharArray(), true); + } + else + { + createSignature(args[1], args[2], args[1] + ".bpg", args[3].toCharArray(), false); + } + } + else if (args[0].equals("-v")) + { + verifySignature(args[1], args[2], args[3]); + } + else + { + System.err.println("usage: DetachedSignatureProcessor [-s [-a] file keyfile passPhrase]|[-v file sigFile keyFile]"); + } + } +} diff --git a/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/JcaPGPContentSignerBuilder.java b/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/JcaPGPContentSignerBuilder.java new file mode 100644 index 00000000..a5dc297d --- /dev/null +++ b/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/JcaPGPContentSignerBuilder.java @@ -0,0 +1,142 @@ +package org.spongycastle.openpgp.operator.jcajce; + +import java.io.OutputStream; +import java.security.InvalidKeyException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; + +import org.spongycastle.jcajce.util.DefaultJcaJceHelper; +import org.spongycastle.jcajce.util.NamedJcaJceHelper; +import org.spongycastle.jcajce.util.ProviderJcaJceHelper; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.openpgp.PGPPrivateKey; +import org.spongycastle.openpgp.operator.PGPContentSigner; +import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; +import org.spongycastle.openpgp.operator.PGPDigestCalculator; +import org.spongycastle.util.io.TeeOutputStream; + +public class JcaPGPContentSignerBuilder + implements PGPContentSignerBuilder +{ + private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); + private JcaPGPDigestCalculatorProviderBuilder digestCalculatorProviderBuilder = new JcaPGPDigestCalculatorProviderBuilder(); + private JcaPGPKeyConverter keyConverter = new JcaPGPKeyConverter(); + private int hashAlgorithm; + private SecureRandom random; + private int keyAlgorithm; + + public JcaPGPContentSignerBuilder(int keyAlgorithm, int hashAlgorithm) + { + this.keyAlgorithm = keyAlgorithm; + this.hashAlgorithm = hashAlgorithm; + } + + public JcaPGPContentSignerBuilder setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public JcaPGPContentSignerBuilder setProvider(Provider provider) + { + this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); + keyConverter.setProvider(provider); + digestCalculatorProviderBuilder.setProvider(provider); + + return this; + } + + public JcaPGPContentSignerBuilder setProvider(String providerName) + { + this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); + keyConverter.setProvider(providerName); + digestCalculatorProviderBuilder.setProvider(providerName); + + return this; + } + + public JcaPGPContentSignerBuilder setDigestProvider(Provider provider) + { + digestCalculatorProviderBuilder.setProvider(provider); + + return this; + } + + public JcaPGPContentSignerBuilder setDigestProvider(String providerName) + { + digestCalculatorProviderBuilder.setProvider(providerName); + + return this; + } + + public PGPContentSigner build(final int signatureType, final PGPPrivateKey privateKey) + throws PGPException + { + final PGPDigestCalculator digestCalculator = digestCalculatorProviderBuilder.build().get(hashAlgorithm); + final Signature signature = helper.createSignature(keyAlgorithm, hashAlgorithm); + + try + { + if (random != null) + { + signature.initSign(keyConverter.getPrivateKey(privateKey)); + } + else + { + signature.initSign(keyConverter.getPrivateKey(privateKey)); + } + } + catch (InvalidKeyException e) + { + throw new PGPException("invalid key.", e); + } + + return new PGPContentSigner() + { + public int getType() + { + return signatureType; + } + + public int getHashAlgorithm() + { + return hashAlgorithm; + } + + public int getKeyAlgorithm() + { + return keyAlgorithm; + } + + public long getKeyID() + { + return privateKey.getKeyID(); + } + + public OutputStream getOutputStream() + { + return new TeeOutputStream(new SignatureOutputStream(signature), digestCalculator.getOutputStream()); + } + + public byte[] getSignature() + { + try + { + return signature.sign(); + } + catch (SignatureException e) + { // TODO: need a specific runtime exception for PGP operators. + throw new IllegalStateException("unable to create signature"); + } + } + + public byte[] getDigest() + { + return digestCalculator.getDigest(); + } + }; + } +} diff --git a/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/OperatorHelper.java b/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/OperatorHelper.java new file mode 100644 index 00000000..dc20e0c3 --- /dev/null +++ b/pg/src/main/jdk1.1/org/spongycastle/openpgp/operator/jcajce/OperatorHelper.java @@ -0,0 +1,220 @@ +package org.spongycastle.openpgp.operator.jcajce; + +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +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.bcpg.SymmetricKeyAlgorithmTags; +import org.spongycastle.jcajce.util.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; + + try + { + dig = helper.createDigest(PGPUtil.getDigestName(algorithm)); + } + catch (NoSuchAlgorithmException e) + { + throw new PGPException("cannot find provider: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new PGPException("cannot find provider: " + e.getMessage(), e); + } + + return dig; + } + + KeyFactory createKeyFactory(String algorithm) + throws GeneralSecurityException, PGPException + { + try + { + return helper.createKeyFactory(algorithm); + } + catch (NoSuchAlgorithmException e) + { + throw new PGPException("cannot find provider: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new PGPException("cannot find provider: " + e.getMessage(), e); + } + } + + 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 (Exception 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); + } + } + + Cipher createKeyWrapper(int encAlgorithm) + throws PGPException + { + try + { + switch (encAlgorithm) + { + case SymmetricKeyAlgorithmTags.AES_128: + case SymmetricKeyAlgorithmTags.AES_192: + case SymmetricKeyAlgorithmTags.AES_256: + return helper.createCipher("AESWrap"); + default: + throw new PGPException("unknown wrap algorithm: " + encAlgorithm); + } + } + catch (Exception e) + { + throw new PGPException("cannot create cipher: " + e.getMessage(), e); + } + } + + private Signature createSignature(String cipherName) + throws PGPException + { + try + { + return helper.createSignature(cipherName); + } + catch (Exception 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; + case PublicKeyAlgorithmTags.ECDSA: + encAlg = "ECDSA"; + break; + default: + throw new PGPException("unknown algorithm tag in signature:" + keyAlgorithm); + } + + return createSignature(PGPUtil.getDigestName(hashAlgorithm) + "with" + encAlg); + } +} |