1

Is there a way to tell if things encrypted via the GNU Privacy Guard are symmetric or asymmetric (without decrypting them or already knowing to start with)? How?

Anyway (for those who want to know what I'm doing), I used Python 3.x to program a GUI-based IDE of sorts that can open symmetrically encrypted files (and save them, too). It can open asymmetrically encrypted files (enter the passphrase to use your secret key instead of the passphrase to decrypt a symmetrically encrypted file). However, it doesn't know they're asymmetric and will overwrite them with symmetrically encrypted files if saved. It would be nice to be able to save them asymmetrically, too. My editor uses the gpg command-line program on Linux (no gpg libraries or anything like that).

I could have a checkbox on the password prompt for asymmetric encryption, but I'd rather not make it so it has to be a manual thing for the user.

For my own personal files, I could add some kind of marker to the saved files to distinguish, but I want it to be able to open them correctly even if they weren't created in my IDE.

I know there's a question with a similar title, but the question asked in the body is fundamentally different.

Jens Erat
  • 37,523
  • 16
  • 80
  • 96
Brōtsyorfuzthrāx
  • 4,387
  • 4
  • 34
  • 56

2 Answers2

5

OpenPGP is a hybrid cryptosystem, which means messages (or files) are always encrypted symmetrically using a so-called session key. The session key again is encrypted using asymmetric encryption (using a public key) or symmetric encryption again (using a string to key function).

This has technical reasons (asymmetric cryptography is very slow for large amounts of data), but also practical ones: by encrypting the small session key multiple times (once for each recipient), you can also have multiple recipients with different keys and even mix asymmetric (public key) and symmetric (password based) encryption in a single OpenPGP message.

Each of those encrypted copies of the session key form an OpenPGP packet, either a packet with tag 1 (Public-Key Encrypted Session Key Packet) or a packet with tag 3 (Symmetric-Key Encrypted Session Key Packet). Those packets in an OpenPGP message can be easily decomposed using pgpdump. An example using GnuPG to create an OpenPGP message encrypting for both my own key and symmetrically for the passphrase foo:

$ echo foo | gpg --recipient a4ff2279 --symmetric --passphrase foo --encrypt | pgpdump
Old: Public-Key Encrypted Session Key Packet(tag 1)(524 bytes)
    New version(3)
    Key ID - 0xCC73B287A4388025
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA m^e mod n(4096 bits) - ...
        -> m = sym alg(1 byte) + checksum(2 bytes) + PKCS-1 block type 02
Old: Symmetric-Key Encrypted Session Key Packet(tag 3)(46 bytes)
    New version(4)
    Sym alg - AES with 128-bit key(sym 7)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA512(hash 10)
        Salt - 0c a6 e6 1d d2 f4 9a 50 
        Count - 102400(coded count 105)
    Encrypted session key
        -> sym alg(1 bytes) + session key
New: Symmetrically Encrypted and MDC Packet(tag 18)(63 bytes)
    Ver 1
    Encrypted data [sym alg is specified in sym-key encrypted session key]
        (plain text + MDC SHA1(20 bytes))

Each of the first two packets forms a key to open the encrypted string in the Symmetrically Encrypted and MDC Packet.

This also already explains how to analyze how a message was encrypted: look through the packets, looking for either tag 1 or 3 packets, indicating asymmetric or symmetric encryption (and be aware both might exist). You seem to be very lucky, and the Python GnuPG module already brings a ListPackets class, so you neither have to interface pgpdump nor write your own OpenPGP parser.

Jens Erat
  • 37,523
  • 16
  • 80
  • 96
  • Thanks for the detailed information. Does the GNU Privacy Guard command-line tool have any query functions/tools that might yield some results, by chance? I'm not using the Python GnuPG module. – Brōtsyorfuzthrāx Feb 05 '16 at 21:59
  • 1
    You could go for `--list-packets` in `--batch` mode, which will not ask for credentials but print a list similar to `pgpdump` one's. Are you sure it wouldn't be a better idea to go for a framework instead of manually parsing GnuPG's output? Writing reasonable parsers is a tedious and error-prone task. – Jens Erat Feb 05 '16 at 22:06
  • 1
    Often, `--with-colons` returns a much easier to parse output. It's a shame that with `--list-packets` it doesn't, this would make analyzing OpenPGP messages much easier. – Jens Erat Feb 05 '16 at 22:09
  • The only two problems I have with using a framework are these: 1. Documentation (I've tried figuring stuff out with the libraries before, but it was just too difficult.) 2. Licensing. I would have to use the GNU license if I used the libraries (not that that would be the end of the world, but I have my own free license in mind). I'm fairly comfortable with parsing, in most regards. The command-line tool is much more documented and used. Oh, there's a third reason (I don't want Windows users to have to have a compiler to install the libraries, if I make it cross-platform.) – Brōtsyorfuzthrāx Feb 05 '16 at 22:14
  • `--list-packets` doesn't directly say the words 'symmetric' and 'asymmetric', but I see a lot of differences I can work with. Thanks! However, I'll have to study the variability between systems, if there is any. – Brōtsyorfuzthrāx Feb 05 '16 at 22:33
  • `--list-packets` also indicates the package tags as described for `pgpdump`. – Jens Erat Feb 06 '16 at 08:21
  • `--list-packets` with `--batch` no longer works in gpg2 without prompting for a passphrase, but fortunately, pgpdump looks like it should work just fine (I don't know why I didn't use it before; maybe I just didn't want to install another program, but I don't mind now). – Brōtsyorfuzthrāx Sep 06 '18 at 10:35
1

Since you are using linux commands, I think you can try with the "file" utility to check the header and tell if the encryption is symmetric or asymmetric.

The output would be something like this (Tested in Ubuntu 14.04):

Command: file symm_encrypted.txt.gpg
Output: GPG symmetrically encrypted data (CAST5 cipher)

Command: file asymm_encrypted.txt.gpg
Output: GPG encrypted data
semperfids
  • 197
  • 8
  • `file` does not contain a complete OpenPGP parser and fails for me for binary encoded symmetric encryption, and generally for combinations of both of them. – Jens Erat Feb 05 '16 at 20:42
  • @JensErat Oh, it looks like I forgot to mention something very important. The encrypted files I have are armored (although I would like to be able to handle files that aren't, too). @semperfids, I get the following message for both symmetric and asymmetric encryption: `myFile.asc: PGP message` I wonder if it has to do with the fact that it's armored, or if it has to do with other encryption settings (I'm not using the default compression methods and stuff like that). – Brōtsyorfuzthrāx Feb 05 '16 at 21:52
  • Yeah, it's the armoring that makes the message so it doesn't show whether it's symmetric (but it won't say if it's asymmetric either way for some reason; although one thing is good enough for distinguishing between the two, where only one exists). I tried it with and without armoring. It works without armoring it for symmetric encryption; for asymmetric it says `myFile.gpg: GPG encrypted data`. So, I could just dearmor it and check it. This should work for Linux, at least (I'll need to work out a long-term cross-platform solution some day, though.) – Brōtsyorfuzthrāx Feb 05 '16 at 22:10