首先,需要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);