3

My problem is with symmetric decryption. Not asymmetric decryption. So the correct answer is here Decrypt PGP encrypted file with passphrase only in Java

I use gpg to encrypt "hello":

[root@shc-sma-cd13 opt]# echo "hello" | gpg --symmetric --armor --cipher-algo AES256 --passphrase "2R79P7z5f8350VEp" --batch
-----BEGIN PGP MESSAGE-----
Version: GnuPG v2.0.22 (GNU/Linux)

jA0ECQMC1XpaSrXhBAfU0jsBXw817k4k4iT++AGV8MUev4/gKkuIwAW2VaJsEANa
+0ZuqZgFp/8N7AndRhyNj5WGcloQQkLkwvIV3Q==
=GwQi
-----END PGP MESSAGE-----

I use Java to decrypt the string:

public class AESUtils1 {
private static final String KEY_VAL = "2R79P7z5f8350VEp";

public static String AESDecode(String content) {
    try {
        SecretKey key = new SecretKeySpec(KEY_VAL.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] byte_content = new BASE64Decoder().decodeBuffer(content);
        byte[] byte_decode = cipher.doFinal(byte_content);
        String AES_decode = new String(byte_decode, "utf-8");
        return AES_decode;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }
    //如果有错就返加nulll
    return null;
}

public static void main(String[] args) {
    String encryptString = "jA0ECQMC1XpaSrXhBAfU0jsBXw817k4k4iT++AGV8MUev4/gKkuIwAW2VaJsEANa\n" +
            "    +0ZuqZgFp/8N7AndRhyNj5WGcloQQkLkwvIV3Q==\n" +
            "    =GwQi";
    String decryptString = AESDecode(encryptString);
    System.out.println("decryptString: " + decryptString);
}

}

But it fails with error message:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at com.hpe.itsma.itsmaInstaller.AESUtils1.AESDecode(AESUtils1.java:33)
at com.hpe.itsma.itsmaInstaller.AESUtils1.main(AESUtils1.java:57)
decryptString: null

I am curious that what is the real encrypted string from gpg that I can put it into Java. The output of gpg is different from using Java to encrypt "hello". And another interesting thing is that every time I run command echo "hello" | gpg --symmetric --armor --cipher-algo AES256 --passphrase "2R79P7z5f8350VEp" --batch, the result is always different. Is that possible to decrypt the string which is encrypted by gpg. Or the wrong way I used of gpg?

Cain
  • 585
  • 1
  • 9
  • 25
  • 1
    Looks like your string consists of **multiple** Base64 encoded datagrams and needs to be decoded before decrypting. Also, I'm no gpg expert but I'm sure it's much more complicated than just AES. – Mark Jeronimus Dec 12 '18 at 09:27
  • I found another interesting thing. Every time I run command `echo "hello" | gpg --symmetric --armor --cipher-algo AES256 --passphrase "2R79P7z5f8350VEp" --batch` The result is always different. – Cain Dec 12 '18 at 09:41
  • 1
    I suppose the encryption is salted and the salt is somewhere concatenated to the result. – Mark Jeronimus Dec 12 '18 at 10:17
  • Possible duplicate of [Getting GPG Decryption To Work In Java (Bouncy Castle)](https://stackoverflow.com/questions/14993223/getting-gpg-decryption-to-work-in-java-bouncy-castle) – Mark Jeronimus Dec 12 '18 at 10:19
  • @MarkJeronimus+ to be exact, PGP password-based key derivation can be and for GPG by default is salted, AND the 'bulk' (data/session) encryption is (always) randomized, although with a kind of pseudo-IV instead of the standard IV. Cain: PGP encryption, even password-based, is not even remotely similar to just encrypting the data with AES using the password. And it doesn't use ECB, as your Java code does. And last line of the body `=GwQi` is not part of the message, but rather a CRC value; see RFC4880. ... – dave_thompson_085 Dec 12 '18 at 22:59
  • ... If you just want a solution (and and can use BouncyCastle) see https://stackoverflow.com/questions/47715675/decrypt-pgp-encrypted-file-with-passphrase-only-in-java#48388939 and particularly the link to Bouncy example code. If you want to do it yourself, start by reading RFC 4880 and then you'll understand the magnitude of the task. – dave_thompson_085 Dec 12 '18 at 23:01
  • Thanks, @dave_thompson_085, you give me the direct answer. What I am looking for is a snippet of symmetric encryption, not asymmetric decryption. The answer is here https://stackoverflow.com/questions/47715675/decrypt-pgp-encrypted-file-with-passphrase-only-in-java#48388939 – Cain Dec 13 '18 at 02:50

1 Answers1

1

Thanks all. Finally, I figure out the solution. Cause my data was symmetric encrypted. The decryption will be different from the asymmetric decryption. I put my code below, also you can find the same answer here Decrypt PGP encrypted file with passphrase only in Java

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePBEDataDecryptorFactoryBuilder;
import org.bouncycastle.util.io.Streams;

import java.io.*;
import java.security.NoSuchProviderException;
import java.security.Security;

public class SymmetricDecyption {

  public static byte[] decrypt(byte[] var0, char[] var1) throws IOException, PGPException, NoSuchProviderException {
    ByteArrayInputStream var2 = new ByteArrayInputStream(var0);
    InputStream var11 = PGPUtil.getDecoderStream(var2);
    PGPObjectFactory var3 = new PGPObjectFactory(var11);
    Object var5 = var3.nextObject();
    PGPEncryptedDataList var4;
    if (var5 instanceof PGPEncryptedDataList) {
      var4 = (PGPEncryptedDataList) var5;
    } else {
      var4 = (PGPEncryptedDataList) var3.nextObject();
    }

    PGPPBEEncryptedData var6 = (PGPPBEEncryptedData) var4.get(0);
    InputStream var7 = var6.getDataStream((new JcePBEDataDecryptorFactoryBuilder((new JcaPGPDigestCalculatorProviderBuilder()).setProvider("BC").build())).setProvider("BC").build(var1));
    PGPObjectFactory var8 = new PGPObjectFactory(var7);
    PGPCompressedData var9 = (PGPCompressedData) var8.nextObject();
    var8 = new PGPObjectFactory(var9.getDataStream());
    PGPLiteralData var10 = (PGPLiteralData) var8.nextObject();
    return Streams.readAll(var10.getInputStream());
  }

  public static void main(String[] var0) throws Exception {
    String password = "2R79P7z5f8350VEp";
    File file = new File("C:\\Users\\zhongtao.CORPDOM\\Desktop\\file.txt.asc");
    InputStream input = new FileInputStream(file);
    byte[] byt = new byte[input.available()];
    input.read(byt);

    Security.addProvider(new BouncyCastleProvider());
    byte[] var5 = decrypt(byt, password.toCharArray());
    System.out.println("Decrypted data is: " + new String(var5));
  }
}
Cain
  • 585
  • 1
  • 9
  • 25