云自無心水自閑

          天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
          posts - 288, comments - 524, trackbacks - 0, articles - 6
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          OpenPGP加密解密文件

          Posted on 2014-12-10 06:50 云自無心水自閑 閱讀(11802) 評論(5)  編輯  收藏 所屬分類: Java心得體會
          OpenPGP 號稱是世界上使用最廣泛的郵件加密標準.  OpenPGP is the most widely used email encryption standard in the world. ( http://www.openpgp.org/ )
          這篇例子介紹如何使用這個標準進行文件的加密解密 (https://www.bouncycastle.org/latest_releases.html, 需要下載: bcprov-jdk15on-151.jar, bcpg-jdk15on-151.jar).

          主要是使用bouncycastle提供的OpenPGP的庫來完成這個功能,參照了其提供的示例程序,進行了部分改動 ( Bouncy Castle 是一種用于 Java 平臺的開放源碼的輕量級密碼術包。它支持大量的密碼術算法,并提供 JCE 1.2.1 的實現。因為 Bouncy Castle 被設計成輕量級的,所以從 J2SE 1.4 到 J2ME(包括 MIDP)平臺,它都可以運行。它是在 MIDP 上運行的唯一完整的密碼術包。)
          1. 添加循環遍歷來查找第一個可用的message
          2. 需要注意的是在main函數中的,如果不添加這一句的話 Security.addProvider(new BouncyCastleProvider()); 程序運行中會報錯:No such Provider "BC"
          3. 
          錯誤Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters , 這是因為java缺省的庫支持的key長度比較短,需要到oracle的網站上去下載一個支持更長key的庫覆蓋原有的庫文件
          <JAVA_HOME>/lib/securty/ 目錄下的兩個jar文件
          local_policy.jar and US_export_policy.jar
          搜索這個文件: Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files

          package org.bouncycastle.openpgp.examples;

          import java.io.BufferedInputStream;
          import java.io.BufferedOutputStream;
          import java.io.File;
          import java.io.FileInputStream;
          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.security.NoSuchProviderException;
          import java.security.SecureRandom;
          import java.security.Security;
          import java.util.Iterator;

          import org.bouncycastle.bcpg.ArmoredOutputStream;
          import org.bouncycastle.bcpg.CompressionAlgorithmTags;
          import org.bouncycastle.jce.provider.BouncyCastleProvider;
          import org.bouncycastle.openpgp.PGPCompressedData;
          import org.bouncycastle.openpgp.PGPEncryptedData;
          import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
          import org.bouncycastle.openpgp.PGPEncryptedDataList;
          import org.bouncycastle.openpgp.PGPException;
          import org.bouncycastle.openpgp.PGPLiteralData;
          import org.bouncycastle.openpgp.PGPOnePassSignatureList;
          import org.bouncycastle.openpgp.PGPPrivateKey;
          import org.bouncycastle.openpgp.PGPPublicKey;
          import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
          import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
          import org.bouncycastle.openpgp.PGPSignatureList;
          import org.bouncycastle.openpgp.PGPUtil;
          import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
          import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
          import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
          import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
          import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
          import org.bouncycastle.util.io.Streams;

          /**
           * A simple utility class that encrypts/decrypts public key based
           * encryption files.
           * <p>
           * To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.<br>
           * If -a is specified the output file will be "ascii-armored".
           * If -i is specified the output file will be have integrity checking added.
           * <p>
           * To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.
           * <p>
           * Note 1: this example will silently overwrite files, nor does it pay any attention to
           * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
           * will have been used.
           * <p>
           * Note 2: if an empty file name has been specified in the literal data object contained in the
           * encrypted packet a file with the name filename.out will be generated in the current working directory.
           
          */
          public class KeyBasedFileProcessor
          {
              private static void decryptFile(
                  String inputFileName,
                  String keyFileName,
                  char[] passwd,
                  String defaultFileName)
                  throws IOException, NoSuchProviderException
              {
                  InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));
                  InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName));
                  decryptFile(in, keyIn, passwd, defaultFileName);
                  keyIn.close();
                  in.close();
              }

              /**
               * decrypt the passed in message stream
               
          */
              private static void decryptFile(
                  InputStream in,
                  InputStream keyIn,
                  char[]      passwd,
                  String      defaultFileName)
                  throws IOException, NoSuchProviderException
              {
                  in = PGPUtil.getDecoderStream(in);
                  
                  try
                  {
                      JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);
                      PGPEncryptedDataList    enc;

                      Object                  o = pgpF.nextObject();
                      //
                      
          // the first object might be a PGP marker packet.
                      
          //
                      if (o instanceof PGPEncryptedDataList)
                      {
                          enc = (PGPEncryptedDataList)o;
                      }
                      else
                      {
                          enc = (PGPEncryptedDataList)pgpF.nextObject();
                      }
                      
                      //
                      
          // find the secret key
                      
          //
                      Iterator                    it = enc.getEncryptedDataObjects();
                      PGPPrivateKey               sKey = null;
                      PGPPublicKeyEncryptedData   pbe = null;
                      PGPSecretKeyRingCollection  pgpSec = new PGPSecretKeyRingCollection(
                          PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());

                      while (sKey == null && it.hasNext())
                      {
                          pbe = (PGPPublicKeyEncryptedData)it.next();
                          
                          sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd);
                      }
                      
                      if (sKey == null)
                      {
                          throw new IllegalArgumentException("secret key for message not found.");
                      }
              
                      InputStream         clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));
                      
                      JcaPGPObjectFactory    plainFact = new JcaPGPObjectFactory(clear);
                      
                      Object              message = plainFact.nextObject();
              
                      while ( true ) {
                          if (message instanceof PGPCompressedData)
                          {
                              PGPCompressedData   cData = (PGPCompressedData)message;
                              JcaPGPObjectFactory    pgpFact = new JcaPGPObjectFactory(cData.getDataStream());
                              
                              message = pgpFact.nextObject();
                          }
                          
                          if (message instanceof PGPLiteralData)
                          {
                              PGPLiteralData ld = (PGPLiteralData)message;

                              String outFileName = ld.getFileName();
                              if (outFileName.length() == 0)
                              {
                                  outFileName = defaultFileName;
                              }

                              InputStream unc = ld.getInputStream();
                              OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));

                              Streams.pipeAll(unc, fOut);

                              fOut.close();
                              break;
                          }
                          else if (message instanceof PGPOnePassSignatureList)
                          {
                              System.out.println("encrypted message contains a signed message - not literal data.");
                          }
                          else if (message instanceof PGPSignatureList)
                          {
                              System.out.println("encrypted message contains a signed message - not literal data.");
                          }
                          else
                          {
                              throw new PGPException("message is not a simple encrypted file - type unknown.");
                          }
                          message = plainFact.nextObject();
                      }
                      
                      if (pbe.isIntegrityProtected())
                      {
                          if (!pbe.verify())
                          {
                              System.err.println("message failed integrity check");
                          }
                          else
                          {
                              System.err.println("message integrity check passed");
                          }
                      }
                      else
                      {
                          System.err.println("no message integrity check");
                      }
                  }
                  catch (PGPException e)
                  {
                      System.err.println(e);
                      if (e.getUnderlyingException() != null)
                      {
                          e.getUnderlyingException().printStackTrace();
                      }
                  }
              }

              private static void encryptFile(
                  String          outputFileName,
                  String          inputFileName,
                  String          encKeyFileName,
                  boolean         armor,
                  boolean         withIntegrityCheck)
                  throws IOException, NoSuchProviderException, PGPException
              {
                  OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
                  PGPPublicKey encKey = PGPExampleUtil.readPublicKey(encKeyFileName);
                  encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck);
                  out.close();
              }

              private static void encryptFile(
                  OutputStream    out,
                  String          fileName,
                  PGPPublicKey    encKey,
                  boolean         armor,
                  boolean         withIntegrityCheck)
                  throws IOException, NoSuchProviderException
              {
                  if (armor)
                  {
                      out = new ArmoredOutputStream(out);
                  }

                  try
                  {
                      byte[] bytes = PGPExampleUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);

                      PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(
                          new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));

                      encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));

                      OutputStream cOut = encGen.open(out, bytes.length);

                      cOut.write(bytes);
                      cOut.close();

                      if (armor)
                      {
                          out.close();
                      }
                  }
                  catch (PGPException e)
                  {
                      System.err.println(e);
                      if (e.getUnderlyingException() != null)
                      {
                          e.getUnderlyingException().printStackTrace();
                      }
                  }
              }

              public static void main(
                  String[] args)
                  throws Exception
              {
                  Security.addProvider(new BouncyCastleProvider());

                  if (args.length == 0)
                  {
                      System.err.println("usage: KeyBasedFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
                      return;
                  }

                  if (args[0].equals("-e"))
                  {
                      if (args[1].equals("-a") || args[1].equals("-ai") || args[1].equals("-ia"))
                      {
                          encryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].indexOf('i') > 0));
                      }
                      else if (args[1].equals("-i"))
                      {
                          encryptFile(args[2] + ".bpg", args[2], args[3], falsetrue);
                      }
                      else
                      {
                          encryptFile(args[1] + ".bpg", args[1], args[2], falsefalse);
                      }
                  }
                  else if (args[0].equals("-d"))
                  {
                      decryptFile(args[1], args[2], args[3].toCharArray(), new File(args[1]).getName() + ".out");
                  }
                  else
                  {
                      System.err.println("usage: KeyBasedFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
                  }
              }
          }


          asdf


          評論

          # re: OpenPGP加密解密文件   回復  更多評論   

          2014-12-11 11:47 by 專業祛痘
          不錯的文章,贊一個,我還想問樓主個問題,是不是文件加密了,就一定安全了呢

          # re: OpenPGP加密解密文件   回復  更多評論   

          2014-12-11 19:45 by usherlight
          @專業祛痘
          從理論上來說,如果你的私鑰和密碼保存妥當,使用的密鑰長度足夠的話,被加密的文件是不可能被破解的. 就算要破解,需要消耗的時間也將是一個非常大的數字

          # re: OpenPGP加密解密文件   回復  更多評論   

          2014-12-26 16:36 by bu 李
          可以提供下這個PGPExampleUtil類嗎?

          # re: OpenPGP加密解密文件 [未登錄]  回復  更多評論   

          2015-05-29 15:14 by 123
          @usherlight
          為什么我的程序會進這個判斷里,求解,急。。。。
          else if (message instanceof PGPOnePassSignatureList)
          {
          System.out.println("encrypted message contains a signed message - not literal data.");
          }

          # re: OpenPGP加密解密文件   回復  更多評論   

          2016-05-20 11:06 by vigo
          還是直接拿源碼包中的 兩個實例代碼,直接運行就OK,這個類改的,解密文件跳過去了。
          主站蜘蛛池模板: 遵义县| 竹溪县| 浦东新区| 岳阳市| 利辛县| 德江县| 永春县| 若羌县| 勃利县| 彝良县| 乌鲁木齐市| 永川市| 鄯善县| 手机| 泽普县| 马鞍山市| 江川县| 万盛区| 西畴县| 石渠县| 章丘市| 怀宁县| 青浦区| 陇西县| 茂名市| 海阳市| 藁城市| 麻栗坡县| 淮阳县| 肇州县| 宜良县| 颍上县| 西乡县| 临沭县| 台北市| 南皮县| 孝感市| 长顺县| 民勤县| 阳泉市| 甘南县|