7
$\begingroup$

Suppose I use GnuPG to symmetrically encrypt a file like so:

gpg --no-options -c --cipher-algo AES256 --no-random-seed-file -o my.out my.file

I then provide a passphrase when prompted.

  • What steps does the software actually take to get from the passphrase I provide as a user, to the actual 256-bit AES key which is used to secure the data?
  • What data relating to or derived from the passphrase is stored in the output ciphertext file?
  • What of the above is guaranteed by the standard, and what is implementation-defined?
$\endgroup$

1 Answer 1

6
$\begingroup$

GPG implements the OpenPGP standard RFC 4880, so it implements the String-to-Key Specifiers.

3.7. String-to-Key (S2K) Specifiers

String-to-key (S2K) specifiers are used to convert passphrase strings into symmetric-key encryption/decryption keys. They are used in two places, currently: to encrypt the secret part of private keys in the private keyring, and to convert passphrases to encryption keys for symmetrically encrypted messages.

3.7.1. String-to-Key (S2K) Specifier Types

There are three types of S2K specifiers currently supported, and
some reserved values:

   ID          S2K Type
   --          --------
   0           Simple S2K
   1           Salted S2K
   2           Reserved value
   3           Iterated and Salted S2K
   100 to 110  Private/Experimental S2K

I wrote my own implementation of OpenPGP a while back, if you dont want to search through the GPG source code. If I remember correctly, while decrypting test data I generated with GPG, I found that by default, GPG uses Iterated and Salted S2K (S2K3).

std::string S2K3::run(std::string pass, unsigned int sym_len){
    // get string to hash
    std::string to_hash = "";
    while (to_hash.size() < coded_count(count)){// coded count is count of bytes, not interations
        to_hash += salt + pass;
    }
    to_hash = to_hash.substr(0, coded_count(count));
    // hash string
    std::string out = "";
    unsigned int context = 0;
    while (out.size() < sym_len){
        out += use_hash(hash, std::string(context++, 0) + to_hash);
    }
    return out.substr(0, sym_len);
}

As for your second and third questions, I don't know. I would hope that no information of the password is stored in the file. I have tried to read the GPG source code, but failed doing so. It is very large and complex.

$\endgroup$
2
  • 1
    $\begingroup$ So if I understand you and the RFC correctly, the user-provided passphrase is basically concatenated as many times as necessary to achieve the string length defined in RFC 4880 § 3.7.1.3, hashed according to the selected S2K algorithm, and then as stated in 3.7.1.1 the selected encryption algorithm's key length number of bits is taken out of the resultant hash value. That data is then used as the key to encrypt the ESK packet (5.3, holding a random session key which is used to encrypt the payload), stated in 3.7.2.2. Would you say that this interpretation agrees with yours? $\endgroup$
    – user
    Commented Dec 16, 2013 at 8:21
  • $\begingroup$ @MichaelKjörling I think so. $\endgroup$
    – calccrypto
    Commented Dec 16, 2013 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.