Subject: Re: private key CFB

From: "Hal Finney" <[email-masked]>
Date: Mon, 17 Nov 2003 09:22:18 -0800

Douglas Maus writes:
> 1. In Private Key packets (tag 5, section 5.5.3), what is the bitsize of the CFB mode used in encrypting the secret MPI? For example, AES256 may be performed in CFB 1bit, CFB 8bit and CFB 128bit (1bit, 1octet, and 1block). Is this noted somewhere in the RFC that I'm missing?

CFB in PGP always uses one block shift widths.  That would be 128 bits for
AES.

> 2. Could someone please help me confirm a key from salt and passphrase?
> keysize of 256 (AES 256 - algorithm 9 in section 9.2)
> Iterated and salted mode (3.7.1.3)
> SHA1 hash (algorithm 2 in section 9.4)
> salt of 0x61f8a7c834124c3a
> coded count 96 (count then 65536)
> passphrase: 'passphrase'
>
> I get
> 0x66913d886546e5e352edaddff30255d26a4f0b969603131df274720b68d78f6f

Sorry, I don't have time to do this.

Hal Finney

---

From: [email-masked]
Date: Fri, 21 Nov 2003 08:42:34 +0000

> Two beginner questions:
..begets at least one beginner's answer:

#1. CFB shifts == the algorithm's block size.
    Blowfish, 3DES, CAST, & IDEA use 8 byte blocks.
    AES (128, 192, 256) and Twofish use 16 byte blocks.

#2. Given the string-to-key parameters:

    Hash algorithm: 2
    Salt: 0x61f8a7c834124c3a 
    Type: 3 
    Count code: 96
    Encryption algorithm: 9
    Passphrase: 'passphrase'

..the resulting string is (previously posted by Michael Young,
seconded by yours truly):
 0x 53 f2 fd a7 69 7d 0b a6 c0 ee 18 4f 89 db 1d f8 
    14 6c d4 ad 36 1b 8c 4e 63 13 ab 68 75 a7 ad 0b 

Grammatically-challenged, I gave up trying to figure out S2K mechanics
using the draft and eventually found a nice code sample at the link
below. I also gave up trying to improve on the documentation which
actually makes a lot more sense once the code is working. :)

My Python-ized version looks something like:

# Given string 'passphrase', string 'salt', integer 'count' (actual
# "big" count, not the "count code"), and integer keysize (16 for
# CAST, Blowfish, and AES128, 24 for 3DES and AES192, and 32 for
# AES256)
# 'hasher' is a magic MD5 or SHA1 hash machine
# len(x) : "length of x"

pos, run, result = 0, 0, ''
while pos < keysize:
    md = [] # reset message digest "hash context" every run
    done = 0
    for i in range(run): # preloaded 0x00s depending on iteration "run"
        md.append('\x00')
    if count < (len(passphrase) + len(salt)):
        count = len(passphrase) + len(salt)
    while (count - done) > (len(passphrase) + len(salt)):
        if (len(salt) > 0):
            md.append(salt)
        md.append(passphrase)
        done = done + len(passphrase) + len(salt)
    for i in range(len(salt)): # "for (i=0; i++; i<=len(salt))"
        if done < count:
            md.append(salt[i]) # byte index of 'salt'
            done += 1
    for i in range(len(passphrase)):
        if done < count:
            md.append(passphrase[i]) 
            done += 1
    hash = hasher.new(''.join(md)).digest() # list joining quirk
    size = len(hash)
    if (pos + size) > keysize:
        size = keysize - pos
    result = ''.join([result[:pos], hash[0:size]]) # quirk again
    pos += size
    run += 1
return result

Best of luck,
the poiboy

CVS source for Cryptix OpenPGP implementation
(file PGPIteratedAndSaltedS2K.java)
http://anoncvs.cryptix.org/co.php/projects/openpgp/src/cryptix/openpgp/algorithm/PGPIteratedAndSaltedS2K.java?r=1.8