PGP加密文件和解密文件

首先,需要jar包如下:
cryptix-jce-api.jar
cryptix-jce-provider.jar
cryptix-message-api.jar
cryptix-openpgp-provider.jar
cryptix-pki-api.jar

然后需要写两个class,一个是PGP加密解密功能的类,一个是给其他类使用的工具类。
使用的时候调用工具类PGPEncryptDecrypt就好了。

工具类PGPEncryptDecrypt :

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import cryptix.pki.KeyBundle;

public class PGPEncryptDecrypt {

    //解密文件路径
    private static String decryptFilePath = "";
    //解密后新生成的文件
    private static String decrypt_New = "";
    //解密后生成的新文件
    private static File decryptFile_New = null;
    //须解密文件
    private static File decryptFile = null;
    //须解密文件名
    private static String decryptFileName = "";

    //须加密文件
    private static File encryptFile = null;
    //加密后生成的新文件
    private static File encryptFile_New = null;
    //公钥证书
    private static File pubKey = null;
    // 私钥证书
    private static File prikey = null;
    // 证书密码
    private static String password = "";
    //原始文件路径
    private  static String plaintextPath = "";
    //原始文件文件名
    private static String plaintextFileName = "";
    //加密文件路径
    private static String encryptFilePath = "";
    //加密后新生成的文件
    private static String encrypt_newFileName = "";
    //证书文件路径
    private static String certFilePath = "";
    //公钥名
    private static String publicKeyFileName = "";
    //私钥名
    private static String privateKeyFileName = "";

    //将日期以 yyyyMMdd 的格式输出
    private static final SimpleDateFormat compactDateFormatter = new SimpleDateFormat("yyyyMMdd");
    private static String formatCompactDate(Date date) {
        if(date==null){
            return "";
        }
        return compactDateFormatter.format(date);
    }

    ///////////////////////////////////////////加密用////////////////////////////////////////////////

    //签名并加密文件,并且将签名加密后的文件内容写入到新的文件中
    public static void signEncrypt(String pswd,String orifilepath,String orifilename,String encryfilepath,String encryptnewFileName,String certpath,String pubkeyname,String prikeyname){
        System.out.println("encrypt--------------------");
        password = pswd;
        plaintextPath = orifilepath;
        plaintextFileName = orifilename;
        encryptFilePath = encryfilepath;
        encrypt_newFileName = encryptnewFileName;
        certFilePath = certpath;
        publicKeyFileName = pubkeyname;
        privateKeyFileName = prikeyname;
        encryptFile = new File(plaintextPath,plaintextFileName);
        pubKey = new File(certFilePath,publicKeyFileName);
        prikey = new File(certFilePath,privateKeyFileName);
        encryptFile_New = new File(encryptFilePath,encrypt_newFileName);

        if(!encryptFile.exists()){
            System.out.println("Encrypt file is not exists!");
            throw new RuntimeException("Encrypt file is not exists!");
        }
        String encode = getFilecharset(new File(plaintextPath,plaintextFileName));
        System.out.println("encode=>"+encode);
        System.out.println("++++++++++++++++++"+plaintextPath+plaintextFileName);
        System.out.println("++++++++++++++++++"+encryptFilePath+encrypt_newFileName);
        byte [] encrypts = pgpEncryptAndSign(IOUtil.read((plaintextPath+plaintextFileName) ,encode), pubKey, prikey, password);
        IOUtil.writeAsText( (encryptFilePath+encrypt_newFileName), new String(encrypts),encode);
    }

    /** 使用PGP证书签名和加密原始文件
     * 
     * @param plain
     *            原始文件
     * @param publicFile
     *            公钥
     * @param privateFile
     *            私钥
     * @param password
     *            私钥密码
     * @return 返回签名加密后的密文
     */
    private static byte[] pgpEncryptAndSign(byte[] plain, File publicKeyFile,File privateKeyFile, String password) {
        try {
            InputStream pubInputStream = new FileInputStream(publicKeyFile);
            InputStream priInputStream = new FileInputStream(privateKeyFile);
            // 将公钥文件转换为PGP的KeyBundle(加密需要使用KeyBundle)
            KeyBundle publicKey = PGPUtil.streamToKeyBundle(pubInputStream);
            // 将私钥文件转换为PGP的KeyBundle(签名需要使用KeyBundle)
            KeyBundle privateKey = PGPUtil.streamToKeyBundle(priInputStream);
            // 返回加密后的密文
            return PGPUtil.signAndEncrypt(plain, privateKey, password,
                    publicKey);
        } catch (Exception e) {
            System.out.println("Use PGP Sign And Encrypt Fail!  excepted:"+ e);
            throw new RuntimeException();
        }
    }

    ///////////////////////////////////////////加密用////////////////////////////////////////////////

    ///////////////////////////////////////////解密用////////////////////////////////////////////////


    /**
     * 解密并验签文件
     * 并且将解密的内容写入到指定的文件中
     */
    public static void decryptVerify(String decrypt_pswd,String decrypt_filepath , String decrypt_filename , String decryptnewfilename,String decrypt_certpath,String decrypt_pubkeyname,String decrypt_prikeyname){
        System.out.println("decrypt--------------------");
        password = decrypt_pswd;
        certFilePath = decrypt_certpath;
        publicKeyFileName = decrypt_pubkeyname;
        privateKeyFileName = decrypt_prikeyname;
        decryptFilePath = decrypt_filepath;
        decryptFileName = decrypt_filename;
        decrypt_New = decryptnewfilename;

        decryptFile = new File(decryptFilePath,decryptFileName);
        decryptFile_New = new File(decryptFilePath,decrypt_New);
        pubKey = new File(certFilePath,publicKeyFileName);
        prikey = new File(certFilePath,privateKeyFileName);

        if(!decryptFile.exists()){
            System.out.println("Decrypt file is not exists!");
            throw new RuntimeException("Decrypt file is not exists!");
        }
        String encode = getFilecharset(new File(plaintextPath,plaintextFileName));
        System.out.println("++++++++++++++++++"+plaintextPath+plaintextFileName);
        System.out.println("++++++++++++++++++"+decryptFilePath+decryptFileName);
        byte [] decrypts = pgpDecryptCryptograph(IOUtil.read((decryptFilePath+decryptFileName),encode), pubKey, prikey, password);
        IOUtil.writeAsText( (decryptFilePath+decrypt_New), new String(decrypts),encode);
    }

    /**
     * 使用PGP私钥对密文解密
     * 
     * @param cryptograph
     *            密文内容
     * @param publicFile
     *            公钥文件
     * @param privateFile
     *            私钥文件
     * @param password
     *            私钥密码
     * @return 返回解密验签后明文
     */
    private static byte[] pgpDecryptCryptograph(byte [] cryptograph,File publicKeyFile,File privateKeyFile,String password){
        try {
            InputStream pubInputStream  = new FileInputStream(publicKeyFile);
            InputStream priInputStream = new FileInputStream(privateKeyFile);
            //将私钥文件转换为PGP的KeyBundle(签名需要使用KeyBundle)
            KeyBundle privateKey = PGPUtil.streamToKeyBundle(priInputStream);
            //将公钥文件转换为PGP的KeyBundle(加密需要使用KeyBundle)
            KeyBundle publicKey = PGPUtil.streamToKeyBundle(pubInputStream);

            return PGPUtil.decryptVerify(cryptograph, privateKey, password, publicKey);

        } catch (Exception e) {
            System.out.println("Use PGP Decrypt Verify Fail!  exception:"+e);
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    ///////////////////////////////////////////解密用////////////////////////////////////////////////

    //判断编码格式方法  
    private static  String getFilecharset(File sourceFile) {  
        String charset = "GBK";  
        byte[] first3Bytes = new byte[3];  
        try {  
            boolean checked = false;  
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));  
            bis.mark(0);  
            int read = bis.read(first3Bytes, 0, 3);  
            if (read == -1) {  
                return charset; //文件编码为 ANSI  
            } else if (first3Bytes[0] == (byte) 0xFF  
                    && first3Bytes[1] == (byte) 0xFE) {  
                charset = "UTF-16LE"; //文件编码为 Unicode  
                checked = true;  
            } else if (first3Bytes[0] == (byte) 0xFE  
                    && first3Bytes[1] == (byte) 0xFF) {  
                charset = "UTF-16BE"; //文件编码为 Unicode big endian  
                checked = true;  
            } else if (first3Bytes[0] == (byte) 0xEF  
                    && first3Bytes[1] == (byte) 0xBB  
                    && first3Bytes[2] == (byte) 0xBF) {  
                charset = "UTF-8"; //文件编码为 UTF-8  
                checked = true;  
            }  
            bis.reset();  
            if (!checked) {  
                int loc = 0;  
                while ((read = bis.read()) != -1) {  
                    loc++;  
                    if (read >= 0xF0)  
                        break;  
                    if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的,也算是GBK  
                        break;  
                    if (0xC0 <= read && read <= 0xDF) {  
                        read = bis.read();  
                        if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)  
                            // (0x80  
                            // - 0xBF),也可能在GB编码内  
                            continue;  
                        else  
                            break;  
                    } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错,但是几率较小  
                        read = bis.read();  
                        if (0x80 <= read && read <= 0xBF) {  
                            read = bis.read();  
                            if (0x80 <= read && read <= 0xBF) {  
                                charset = "UTF-8";  
                                break;  
                            } else  
                                break;  
                        } else  
                            break;  
                    }  
                }  
            }  
            bis.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return charset;  
    } 
}

功能类PGPUtil:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


import cryptix.message.EncryptedMessage;
import cryptix.message.EncryptedMessageBuilder;
import cryptix.message.KeyBundleMessage;
import cryptix.message.LiteralMessage;
import cryptix.message.LiteralMessageBuilder;
import cryptix.message.Message;
import cryptix.message.MessageException;
import cryptix.message.MessageFactory;
import cryptix.message.NotEncryptedToParameterException;
import cryptix.message.SignedMessage;
import cryptix.message.SignedMessageBuilder;
import cryptix.openpgp.PGPArmouredMessage;
import cryptix.pki.KeyBundle;

public class PGPUtil {

    //这个一定要有 不然会报这个错java.security.NoSuchAlgorithmException: Algorithm not found.
    static{
        Security.addProvider(new cryptix.jce.provider.CryptixCrypto());
        Security.addProvider(new cryptix.openpgp.provider.CryptixOpenPGP() );
    }

    ///////////////////////////////////////////加密用////////////////////////////////////////////////

    /**
     * 流转换为PGP KeuBundle 对象
     * @param inputStream   Key
     * @return  转换后的 KeuBundle
     * @throws MessageException
     * @throws IOException
     */
    public static KeyBundle streamToKeyBundle(InputStream inputStream) throws MessageException, IOException {
        MessageFactory messageFactory = null;
        try {
            messageFactory = MessageFactory.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        Collection msgs = messageFactory.generateMessages(inputStream);
        KeyBundleMessage keybm = (KeyBundleMessage)msgs.iterator().next();

        return keybm.getKeyBundle();
    }
    /**
     * 签名加密
     * @param plain         明文  
     * @param privateKey    私钥  
     * @param keypass       私钥密码
     * @param recipientKeys 公钥
     * @return              返回签名加密后的数据
     * @throws UnrecoverableKeyException
     * @throws MessageException
     */
    public static byte [] signAndEncrypt(byte[] plain,KeyBundle privateKey,String keypass,List recipientKeys) throws UnrecoverableKeyException, MessageException{
        return PGPUtil.encrypt(PGPUtil.sign(plain, privateKey, keypass),recipientKeys);
    }
    /**
     * 签名加密
     * @param plain         明文  
     * @param privateKey    私钥  
     * @param keypass       私钥密码
     * @param recipientKeys 公钥
     * @return              返回签名加密后的数据
     * @throws UnrecoverableKeyException
     * @throws MessageException
     */
    public static byte [] signAndEncrypt(byte[] plain,KeyBundle privateKey,String keypass,KeyBundle publicKey) throws UnrecoverableKeyException, MessageException{
        return PGPUtil.encrypt(PGPUtil.sign(plain, privateKey, keypass),publicKey);
    }
    /**
     * 使用多个公钥对明文加密
     * @param plain         明文
     * @param recipientKeys 公钥集合
     * @return              加密后的明文
     * @throws MessageException
     */
    public static byte[] encrypt(byte[] plain,List recipientKeys) throws MessageException{
        LiteralMessage literal = buildLiteralMessage(plain);

        EncryptedMessageBuilder emb = null;
        try {
            emb = EncryptedMessageBuilder.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        emb.init(literal);


        //添加接受者
        for(KeyBundle key : recipientKeys){
            emb.addRecipient(key);
        }
        //压缩
        emb.setAttribute("compressed", "true");

        //得到加密信息
        Message msg = emb.build();
        PGPArmouredMessage pgpMsg = new PGPArmouredMessage(msg);
        return pgpMsg.getEncoded();
    }
    /**
     * 使用单张公钥加密
     * @param plain     明文  
     * @param publicKey 公钥
     * @return  返回加密后的密文
     * @throws MessageException
     */
    public static byte[] encrypt(byte[] plain,KeyBundle publicKey) throws MessageException{
        List list = new ArrayList();
        list.add(publicKey);

        return encrypt(plain,list);
    }
    /**
     * 使用私钥和密码对明文签名
     * @param plain         明文
     * @param privateKey    私钥
     * @param keypass       私钥密码
     * @return              签名后的明文
     * @throws MessageException
     * @throws UnrecoverableKeyException
     */
    public static byte[] sign(byte[] plain,KeyBundle privateKey,String keypass)throws MessageException,UnrecoverableKeyException{
        SignedMessageBuilder smb = null;
        try {
            smb = SignedMessageBuilder.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        // SignedMessageBuilder smb = SignedMessageBuilder.getInstance("OpenPGP/V3");

        LiteralMessage literal = buildLiteralMessage(plain);
        smb.init(literal);
        smb.addSigner(privateKey, keypass.toCharArray());

        Message msg = smb.build();
        PGPArmouredMessage armoured = new PGPArmouredMessage(msg);
        return armoured.getEncoded();
    }
    private static LiteralMessage buildLiteralMessage(byte[] message) throws MessageException{
        LiteralMessageBuilder lmb = null;

        try {
            lmb = LiteralMessageBuilder.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        lmb.init(message);
        LiteralMessage literal = (LiteralMessage)lmb.build();
        return literal;
    }

    ///////////////////////////////////////////加密用////////////////////////////////////////////////

    ///////////////////////////////////////////解密用////////////////////////////////////////////////

    /**
     * 解密验签
     * @param encrypted     密文  
     * @param privateKey    私钥
     * @param keypass       私钥密码
     * @param publicKey     公钥
     * @return              返回明文
     * @throws UnrecoverableKeyException
     * @throws MessageException
     * @throws IOException
     * @throws NotEncryptedToParameterException
     */
    public static byte[] decryptVerify(byte[] encrypted,KeyBundle privateKey,String keypass,KeyBundle publicKey) throws UnrecoverableKeyException, MessageException, IOException, NotEncryptedToParameterException{
        return PGPUtil.verify(PGPUtil.decrypt(encrypted, privateKey, keypass), publicKey);
    }
    /**
     * 使用私钥和密码解密加密后的数据
     * @param encrypted     PGP加密过的数据
     * @param privateKey    私钥
     * @param keypass       私钥密码
     * @return              解密后的明文
     * @throws MessageException
     * @throws IOException
     * @throws UnrecoverableKeyException
     * @throws NotEncryptedToParameterException
     */
    public static byte[] decrypt(byte[] encrypted,KeyBundle privateKey,String keypass) throws MessageException, IOException, UnrecoverableKeyException, NotEncryptedToParameterException{

        MessageFactory mf = null;
        try {
            mf = MessageFactory.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        Collection msgs = mf.generateMessages(new ByteArrayInputStream(encrypted));

        //得到集合中的EncryptedMessage对象
        Message message = (Message)msgs.iterator().next();

        if (!(message instanceof EncryptedMessage)) {
            throw new MessageException("Not a encrypted message.");
        }

        EncryptedMessage em = (EncryptedMessage)message;
        Message msg = em.decrypt(privateKey,keypass.toCharArray());
        return ((LiteralMessage)msg).getBinaryData();
    }
    /**
     * 验证Message
     * @param signed    验证的内容
     * @param publickey 公钥
     * @return          返回验证后的内容
     * @throws MessageException
     * @throws IOException
     */
    public static byte[] verify(byte[] signed,KeyBundle publickey) throws MessageException, IOException{

        MessageFactory mf = null;
        try {
            mf = MessageFactory.getInstance("OpenPGP");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        Message msg = (Message)mf.generateMessages(new ByteArrayInputStream(signed)).iterator().next();
        if (!(msg instanceof SignedMessage)) {
            throw new MessageException(" Not a signed message.");
        }

        SignedMessage sm = (SignedMessage)msg;
        if (sm.verify(publickey)) {

        } else {
            throw new MessageException(" Signature verify fail. ");
        }

        if (!(sm.getContents() instanceof LiteralMessage)){
            throw new MessageException(" Not a signed message.");
        }

        LiteralMessage lm = (LiteralMessage)sm.getContents();
        return lm.getBinaryData();
    }

    ///////////////////////////////////////////解密用////////////////////////////////////////////////
}

功能类IOUtil


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;


public class IOUtil {

    public static byte[] read(String fileName,String encode) {
        String fileContent = "";
        try {
            File f = new File(fileName);
            if (f.isFile() && f.exists()) {
                InputStreamReader read = new InputStreamReader(new FileInputStream(f), encode);
                BufferedReader reader = new BufferedReader(read);
                String line;
                while ((line = reader.readLine()) != null) {
                    fileContent += line + "\n";
                }
                read.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileContent.getBytes();
    }

    public static void writeAsText(String fileName, String fileContent,String encode) {
        System.out.println("write path:"+fileName);
        System.out.println("write encode:"+encode);
        try {
            File f = new File(fileName);
            if (!f.exists()) {
                System.out.println("notexist");
                f.createNewFile();
            } else {
                System.out.println("exist");
            }
            OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(f), encode);
            BufferedWriter writer = new BufferedWriter(write);
            writer.write(fileContent);
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

最后是调用:

//------------------------PGP encrypt decrypt------------------------
String PGPpassword = "PGP私钥密码";
String filepath = "存放文件的路径";
String oripath = "存放源文件的文件夹";
String encryptpath = "存放加密后文件的文件夹";
String decryptpath = "存放解密后文件的文件夹";
String orifilename = "源文件文件名";
String encryptfilename = "加密文件文件名";
String decryptfilename = "解密文件文件名";
String keypath = "PGP私钥存放路径";
String publicPGPkey = "公钥文件名";
String privatePGPkey = "私钥文件名";
//------------------------PGP encrypt decrypt------------------------

/*执行加密*/    
PGPEncryptDecrypt.signEncrypt(PGPpassword, filepath+oripath, orifilename, filepath+encryptpath, encryptfilename, keypath, publicPGPkey, privatePGPkey);
/*执行解密操作*/
PGPEncryptDecrypt.decryptVerify(PGPpassword,filepath,encryptpath+encryptfilename,decryptpath+decryptfilename, keypath, publicPGPkey, privatePGPkey);

你可能感兴趣的:(java)