【问题标题】:GPG decryptor doesn't work properlyGPG 解密器无法正常工作
【发布时间】:2014-03-31 10:46:24
【问题描述】:

我正在尝试编写 gpg 加密器/解密器(代码如下)。在第一步程序加密“#data1\n#data2\n#data3\n”字符串,并在下一步解密解密器返回的字节数组。但是...为什么来自解密器的文本与 "#data1\n#data2\n#data3\n" 不同?我在哪里错过了什么?感谢您的帮助。

package tests.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.util.Iterator;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter;

import Decoder.BASE64Encoder;

public class GPGTest {

    char[] pass = { 'p', 'a', 's', 's' };

    public static void main(String[] args) throws Exception {

        GPGTest gTest = new GPGTest();
        gTest.setUpCipher();
    }

    public void setUpCipher() throws NoSuchAlgorithmException,
            InvalidKeyException, IllegalBlockSizeException,
            NoSuchProviderException, BadPaddingException,
            NoSuchPaddingException {

        System.out.println("--- setup cipher ---");

        // public key
        String publicKeyFilePath = "E:/Programs/Keys/GPG/Public/public.key";
        File publicKeyFile = new File(publicKeyFilePath);

        // secret key
        String secretKeyFilePath = "E:/Programs/Keys/GPG/Secret/private.key";
        File secretKeyFile = new File(secretKeyFilePath);

        // security provider
        Security.addProvider(new BouncyCastleProvider());

        try {

            // Read the public key
            FileInputStream pubIn = new FileInputStream(publicKeyFile);
            PGPPublicKey pgpPubKey = readPublicKey(pubIn);
            PublicKey pubKey = new JcaPGPKeyConverter().getPublicKey(pgpPubKey);

            // Read the private key
            FileInputStream secretIn = new FileInputStream(secretKeyFile);
            PGPSecretKey pgpSecretKey = readSecretKey(secretIn);
            PGPPrivateKey pgpPrivKey = pgpSecretKey
                    .extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(
                            new BcPGPDigestCalculatorProvider()).build(pass));
            PrivateKey privKey = new JcaPGPKeyConverter()
                    .getPrivateKey(pgpPrivKey);

            Cipher cipher = Cipher.getInstance("RSA");

            // Encrypt data
            byte[] encData = encryptData(cipher, pubKey, new String(
                    "#data1\n#data2\n#data3\n").getBytes());
            String cryptString = new BASE64Encoder().encode(encData);

            System.out.println("\n\nEncrypted data=" + cryptString);

            // Decrypt data
            byte[] decData = decryptData(cipher, privKey, encData);
            String decryptString = new BASE64Encoder().encode(decData);

            System.out.println("\n\nDecrypted data=" + decryptString);

        } catch (Exception e) {
            System.out.println("Setup cipher exception");
            System.out.println(e.toString());
        }
    }

    public byte[] encryptData(Cipher cipher, PublicKey pubKey, byte[] clearText) {

        byte[] encryptedBytes = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            encryptedBytes = cipher.doFinal(clearText);

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return encryptedBytes;
    }

    public byte[] decryptData(Cipher cipher, PrivateKey privKey, byte[] encryptedText) {

        byte[] decryptedBytes = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, privKey);
            decryptedBytes = cipher.doFinal(encryptedText);

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decryptedBytes;
    }

    private static PGPPublicKey readPublicKey(InputStream input) throws IOException, PGPException {

        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input));

        Iterator<?> keyRingIter = pgpPub.getKeyRings();
        while (keyRingIter.hasNext()) {
            PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();

            Iterator<?> keyIter = keyRing.getPublicKeys();
            while (keyIter.hasNext()) {
                PGPPublicKey key = (PGPPublicKey) keyIter.next();

                if (key.isEncryptionKey()) {
                    return key;
                }
            }
        }

        throw new IllegalArgumentException(
                "Can't find encryption key in key ring.");
    }

    private static PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {

        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input));

        Iterator<?> keyRingIter = pgpSec.getKeyRings();
        while (keyRingIter.hasNext()) {
            PGPSecretKeyRing keyRing = (PGPSecretKeyRing) keyRingIter.next();

            Iterator<?> keyIter = keyRing.getSecretKeys();
            while (keyIter.hasNext()) {
                PGPSecretKey key = (PGPSecretKey) keyIter.next();

                if (key.isSigningKey()) {
                    return key;
                }
            }
        }

        throw new IllegalArgumentException(
                "Can't find signing key in key ring.");
    }

}

【问题讨论】:

  • 了解需要哪些额外的库来编译代码示例会很有帮助。你用的是maven吗?如果是这样,您可以编辑问题以包含您的依赖项吗?

标签: java encryption bouncycastle gnupg


【解决方案1】:

它们不一样,因为您是对解密结果进行 base-64 编码,而不是将其解码为文本。改为这样做:

byte[] decData = decryptData(cipher, privKey, encData);
System.out.println("\n\nDecrypted data=" + new String(decData));

使用平台默认字符编码是不好的做法。相反,您应该将文本转换为具有特定编码的字节,并在解码字节时使用相同的编码。

byte[] plaintext = "#data1\n#data2\n#data3\n").getBytes(StandardCharsets.UTF_8);
...
String recovered = new String(decData, StandardCharsets.UTF_8);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    相关资源
    最近更新 更多