{"id":1511,"date":"2023-03-25T14:02:14","date_gmt":"2023-03-25T06:02:14","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1511"},"modified":"2023-04-28T20:21:17","modified_gmt":"2023-04-28T12:21:17","slug":"gpg-encryption-and-decryption-based-on-java","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/25\/gpg-encryption-and-decryption-based-on-java\/","title":{"rendered":"\u57fa\u4e8eJava\u4ee3\u7801\u8fdb\u884cGPG\u52a0\u89e3\u5bc6"},"content":{"rendered":"<h2>\u4f9d\u8d56<\/h2>\n<pre><code class=\"language-xml\">&lt;!-- https:\/\/mvnrepository.com\/artifact\/org.bouncycastle\/bcpg-jdk15on --&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.bouncycastle&lt;\/groupId&gt;\n    &lt;artifactId&gt;bcpg-jdk15on&lt;\/artifactId&gt;\n    &lt;version&gt;1.65&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n<p><!-- more --><\/p>\n<h2>\u521d\u59cb\u5316<\/h2>\n<pre><code class=\"language-java\">Security.addProvider(new BouncyCastleProvider());<\/code><\/pre>\n<h2>\u8f85\u52a9\u7c7b<\/h2>\n<pre><code class=\"language-java\">@Slf4j\npublic class PGPFileProcessor {\n\n    public static void decryptFile(String inputFilePath, String keyFilePath, char[] passWd, String outputFilePath)\n            throws IOException, NoSuchProviderException {\n        InputStream in = new BufferedInputStream(new FileInputStream(inputFilePath));\n        InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFilePath));\n        decryptFile(in, keyIn, passWd, outputFilePath);\n        keyIn.close();\n        in.close();\n    }\n\n    public static void decryptFile(File inputFile, String keyFilePath, char[] passWd, File outputFile)\n            throws IOException, NoSuchProviderException {\n        InputStream in = new BufferedInputStream(new FileInputStream(inputFile));\n        InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFilePath));\n        decryptFile(in, keyIn, passWd, outputFile.getAbsolutePath());\n        keyIn.close();\n        in.close();\n    }\n\n    \/**\n     * decrypt the passed in message stream\n     *\/\n    private static void decryptFile(InputStream in, InputStream keyIn, char[] passWd, String outputFilePath)\n            throws IOException, NoSuchProviderException {\n        in = PGPUtil.getDecoderStream(in);\n        try {\n            JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);\n            PGPEncryptedDataList enc;\n            Object o = pgpF.nextObject();\n            \/\/ the first object might be a PGP marker packet.\n            if (o instanceof PGPEncryptedDataList) {\n                enc = (PGPEncryptedDataList) o;\n            } else {\n                enc = (PGPEncryptedDataList) pgpF.nextObject();\n            }\n            \/\/ find the secret key\n            Iterator&lt;PGPEncryptedData&gt; it = enc.getEncryptedDataObjects();\n            PGPPrivateKey sKey = null;\n            PGPPublicKeyEncryptedData pbe = null;\n            PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(\n                    PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());\n            while (sKey == null &amp;&amp; it.hasNext()) {\n                pbe = (PGPPublicKeyEncryptedData) it.next();\n                sKey = PGPHelper.findSecretKey(pgpSec, pbe.getKeyID(), passWd);\n            }\n            if (sKey == null) {\n                throw new IllegalArgumentException(&quot;secret key for message not found.&quot;);\n            }\n            InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(&quot;BC&quot;).build(sKey));\n            JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);\n            Object message = plainFact.nextObject();\n            if (message instanceof PGPCompressedData) {\n                PGPCompressedData cData = (PGPCompressedData) message;\n                JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());\n                message = pgpFact.nextObject();\n            }\n            if (message instanceof PGPLiteralData) {\n                PGPLiteralData ld = (PGPLiteralData) message;\n                String outFilePath = ld.getFileName();\n                if (outFilePath.length() == 0) {\n                    outFilePath = outputFilePath;\n                } else {\n                    outFilePath = outputFilePath;\n                }\n                InputStream unc = ld.getInputStream();\n                OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFilePath));\n                Streams.pipeAll(unc, fOut);\n                fOut.close();\n            } else if (message instanceof PGPOnePassSignatureList) {\n                throw new PGPException(&quot;encrypted message contains a signed message - not literal data.&quot;);\n            } else {\n                throw new PGPException(&quot;message is not a simple encrypted file - type unknown.&quot;);\n            }\n            if (pbe.isIntegrityProtected()) {\n                if (!pbe.verify()) {\n                    log.error(&quot;PGP.decryptFile: message failed integrity check&quot;);\n                } else {\n                    log.info(&quot;PGP.decryptFile: message integrity check passed&quot;);\n                }\n            } else {\n                log.error(&quot;PGP.decryptFile: no message integrity check&quot;);\n            }\n        } catch (PGPException e) {\n            log.error(&quot;PGP.decryptFile exception: &quot;, e);\n            if (e.getUnderlyingException() != null) {\n                log.error(&quot;PGP.decryptFile underlying exception: &quot;, e.getUnderlyingException());\n            }\n        }\n    }\n\n    public static void encryptFile(String outputFilePath, String inputFilePath, String encKeyFilePath,\n                                    boolean armor, boolean withIntegrityCheck)\n            throws IOException, NoSuchProviderException, PGPException {\n        OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFilePath));\n        PGPPublicKey encKey = PGPHelper.readPublicKey(encKeyFilePath);\n        encryptFile(out, inputFilePath, encKey, armor, withIntegrityCheck);\n        out.close();\n    }\n\n    private static void encryptFile(OutputStream out, String inputFilePath, PGPPublicKey encKey,\n            boolean armor, boolean withIntegrityCheck)\n            throws IOException, NoSuchProviderException {\n        if (armor) {\n            out = new ArmoredOutputStream(out);\n        }\n\n        try {\n            byte[] bytes = PGPHelper.compressFile(inputFilePath, CompressionAlgorithmTags.ZIP);\n            PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(\n                    new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider(&quot;BC&quot;));\n            encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(&quot;BC&quot;));\n            OutputStream cOut = encGen.open(out, bytes.length);\n            cOut.write(bytes);\n            cOut.close();\n            if (armor) {\n                out.close();\n            }\n        } catch (PGPException e) {\n            log.error(&quot;PGP.encryptFile exception: &quot;, e);\n            if (e.getUnderlyingException() != null) {\n                log.error(&quot;PGP.encryptFile underlying exception: &quot;, e.getUnderlyingException());\n            }\n        }\n    }\n\n    \/\/\u4e3b\u65b9\u6cd5\n    public static void main(String[] s) throws Exception {\n        Security.addProvider(new BouncyCastleProvider());\n        String inputPath = &quot;E:\\\\AppBlog\\\\test.csv.gpg&quot;;\n        String outputPath = &quot;E:\\\\AppBlog\\\\test.csv&quot;;\n        String password = &quot;appblog.cn&quot;;  \/\/\u79c1\u94a5\u7684Key\n        String privateKey = &quot;E:\\\\AppBlog\\\\test.key&quot;; \/\/\u79c1\u94a5\u5730\u5740\n        decryptFile(inputPath, privateKey, password.toCharArray(), outputPath);\n    }\n\n}<\/code><\/pre>\n<pre><code class=\"language-java\">public class PGPHelper {\n\n    public static byte[] compressFile(String fileName, int algorithm) throws IOException {\n        ByteArrayOutputStream bOut = new ByteArrayOutputStream();\n        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(algorithm);\n        PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY,\n                new File(fileName));\n        comData.close();\n        return bOut.toByteArray();\n    }\n\n    \/**\n     * Search a secret key ring collection for a secret key corresponding to keyID if it exists.\n     *\n     * @param pgpSec a secret key ring collection.\n     * @param keyID  keyID we want.\n     * @param pass   passphrase to decrypt secret key with.\n     * @return the private key.\n     * @throws PGPException\n     * @throws NoSuchProviderException\n     *\/\n    public static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass)\n            throws PGPException, NoSuchProviderException {\n        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);\n        if (pgpSecKey == null) {\n            return null;\n        }\n        return pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(&quot;BC&quot;).build(pass));\n    }\n\n    public static PGPPublicKey readPublicKey(String fileName) throws IOException, PGPException {\n        InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName));\n        PGPPublicKey pubKey = readPublicKey(keyIn);\n        keyIn.close();\n        return pubKey;\n    }\n\n    \/**\n     * A simple routine that opens a key ring file and loads the first available key\n     * suitable for encryption.\n     *\n     * @param input data stream containing the public key data\n     * @return the first public key found.\n     * @throws IOException\n     * @throws PGPException\n     *\/\n\n    public static PGPPublicKey readPublicKey(InputStream input) throws IOException, PGPException {\n        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(\n                PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());\n        \/\/ we just loop through the collection till we find a key suitable for encryption, in the real\n        \/\/ world you would probably want to be a bit smarter about this.\n        Iterator&lt;PGPPublicKeyRing&gt; keyRingIter = pgpPub.getKeyRings();\n        while (keyRingIter.hasNext()) {\n            PGPPublicKeyRing keyRing = keyRingIter.next();\n            Iterator&lt;PGPPublicKey&gt; keyIter = keyRing.getPublicKeys();\n            while (keyIter.hasNext()) {\n                PGPPublicKey key = keyIter.next();\n                if (key.isEncryptionKey()) {\n                    return key;\n                }\n            }\n        }\n        throw new IllegalArgumentException(&quot;Can&#039;t find encryption key in key ring.&quot;);\n    }\n\n    public static PGPSecretKey readSecretKey(String fileName) throws IOException, PGPException {\n        InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName));\n        PGPSecretKey secKey = readSecretKey(keyIn);\n        keyIn.close();\n        return secKey;\n    }\n\n    \/**\n     * A simple routine that opens a key ring file and loads the first available key\n     * suitable for signature generation.\n     *\n     * @param input stream to read the secret key ring collection from.\n     * @return a secret key.\n     * @throws IOException  on a problem with using the input stream.\n     * @throws PGPException if there is an issue parsing the input stream.\n     *\/\n    public static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {\n        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(\n                PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());\n        \/\/ we just loop through the collection till we find a key suitable for encryption, in the real\n        \/\/ world you would probably want to be a bit smarter about this.\n        Iterator&lt;PGPSecretKeyRing&gt; keyRingIter = pgpSec.getKeyRings();\n        while (keyRingIter.hasNext()) {\n            PGPSecretKeyRing keyRing = keyRingIter.next();\n            Iterator&lt;PGPSecretKey&gt; keyIter = keyRing.getSecretKeys();\n            while (keyIter.hasNext()) {\n                PGPSecretKey key = keyIter.next();\n                if (key.isSigningKey()) {\n                    return key;\n                }\n            }\n        }\n        throw new IllegalArgumentException(&quot;Can&#039;t find signing key in key ring.&quot;);\n    }\n\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u4f9d\u8d56 &lt;!&#8211; https:\/\/mvnrepository.com\/artifact\/org.bounc [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43],"tags":[369],"class_list":["post-1511","post","type-post","status-publish","format-standard","hentry","category-java-basic","tag-gpg"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1511"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1511\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}