Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?
share|improve this question
up vote 2 down vote accepted

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.

share|improve this answer
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 §, hashed according to the selected S2K algorithm, and then as stated in 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 Would you say that this interpretation agrees with yours? – Michael Kjörling Dec 16 '13 at 8:21
@MichaelKjörling I think so. – calccrypto Dec 16 '13 at 16:11

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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