org.tramaci.onionmail.PGP.java Source code

Java tutorial

Introduction

Here is the source code for org.tramaci.onionmail.PGP.java

Source

package org.tramaci.onionmail;

/*
 * Copyright (C) 2013 by Tramaci.Org
 * This file is part of OnionMail (http://onionmail.info)
 * 
 * OnionMail is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this source code; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
import java.util.Date;
import java.util.Iterator;

import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;

public class PGP {

    @SuppressWarnings({ "rawtypes", "deprecation" })
    public static byte[] decrypt(byte[] encrypted, InputStream keyIn, char[] password) throws Exception {
        InputStream inb = new ByteArrayInputStream(encrypted);
        InputStream in = PGPUtil.getDecoderStream(inb);

        try {
            PGPObjectFactory pgpF = new PGPObjectFactory(in);
            PGPEncryptedDataList enc = null;
            Object o = pgpF.nextObject();
            if (o == null)
                throw new Exception("@550 No data in message");

            if (o instanceof PGPEncryptedDataList)
                enc = (PGPEncryptedDataList) o;
            else
                enc = (PGPEncryptedDataList) pgpF.nextObject();

            //deadcode: if (o==null) throw new Exception("@550 No dataList in message");

            Iterator it = enc.getEncryptedDataObjects();
            PGPPrivateKey sKey = null;
            PGPPublicKeyEncryptedData pbe = null;
            PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));

            while (sKey == null && it.hasNext()) {
                pbe = (PGPPublicKeyEncryptedData) it.next();
                sKey = findSecretKey(pgpSec, pbe.getKeyID(), password);
            }

            if (sKey == null)
                throw new IllegalArgumentException("@550 SecretKey not found");
            InputStream clear = pbe.getDataStream(sKey, "BC");
            PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
            PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject();
            pgpFact = new PGPObjectFactory(cData.getDataStream());
            PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
            InputStream unc = ld.getInputStream();
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            int ch;
            while ((ch = unc.read()) >= 0) {
                out.write(ch);
            }

            byte[] rs = out.toByteArray();
            try {
                in.close();
            } catch (Exception I) {
            }
            try {
                inb.close();
            } catch (Exception I) {
            }
            out.close();
            return rs;

        } catch (Exception E) {
            try {
                in.close();
            } catch (Exception I) {
            }
            try {
                inb.close();
            } catch (Exception I) {
            }
            throw E;
        }
    }

    @SuppressWarnings({ "deprecation" })
    public static byte[] encrypt(byte[] clearData, PGPPublicKey encKey, String fileName, boolean withIntegrityCheck,
            boolean armor, Date At, int PGPEncryptedDataAlgo) throws Exception {
        if (fileName == null)
            fileName = PGPLiteralData.CONSOLE;
        ByteArrayOutputStream encOut = new ByteArrayOutputStream();

        OutputStream out = encOut;
        if (armor)
            out = new ArmoredOutputStream(out);
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedDataGenerator.ZIP);
        OutputStream cos = comData.open(bOut);
        PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();

        OutputStream pOut = lData.open(cos, PGPLiteralData.BINARY, fileName, clearData.length, At);
        pOut.write(clearData);

        lData.close();
        comData.close();
        if (PGPEncryptedDataAlgo == 0)
            PGPEncryptedDataAlgo = PGPEncryptedData.CAST5;
        PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedDataAlgo, withIntegrityCheck,
                new SecureRandom(), "BC");
        cPk.addMethod(encKey);

        byte[] bytes = bOut.toByteArray();
        OutputStream cOut = cPk.open(out, bytes.length);
        cOut.write(bytes);
        cOut.close();
        out.close();
        return encOut.toByteArray();
    }

    @SuppressWarnings("rawtypes")
    public static PGPPublicKey readPublicKey(InputStream in) throws Exception {
        in = PGPUtil.getDecoderStream(in);
        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in);
        Iterator rIt = pgpPub.getKeyRings();

        while (rIt.hasNext()) {
            PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next();
            Iterator kIt = kRing.getPublicKeys();
            while (kIt.hasNext()) {
                PGPPublicKey k = (PGPPublicKey) kIt.next();
                if (k.isEncryptionKey())
                    return k;
            }
        }
        throw new IllegalArgumentException("@550 No encryption key");
    }

    @SuppressWarnings("deprecation")
    public static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection keyring, long KID, char[] pwl)
            throws Exception {
        PGPSecretKey pgpkey = keyring.getSecretKey(KID);
        if (pgpkey == null)
            return null;
        return pgpkey.extractPrivateKey(pwl, "BC");
    }

    public static String FilterPGPNSAsMarker(String armor, String subst) throws Exception {
        armor = armor.replace("\r\n", "\n");
        armor = armor.replace("\r", "\n");
        armor = armor.trim();
        String[] line = armor.split("\\n");
        String rs = "";
        int cx = line.length;
        boolean asc = false;
        for (int ax = 0; ax < cx; ax++) {
            String s = line[ax].trim();
            if (s.length() == 0)
                asc = true;

            if (asc) {
                rs += s + "\r\n";
                continue;
            }

            String[] tok = s.split("\\:", 2);
            String c = tok[0].trim().toLowerCase();
            if (c.compareTo("comment") == 0)
                continue;
            if (c.compareTo("version") == 0)
                s = tok[0] + ": " + subst.trim();
            rs += s + "\r\n";
        }
        return rs;
    }

    protected static void ZZ_Exceptionale() throws Exception {
        throw new Exception();
    } //Remote version verify
}