• Breaking News

    Monday, November 5, 2018

    Cryptography Chacha20 based compression function

    Cryptography Chacha20 based compression function


    Chacha20 based compression function

    Posted: 04 Nov 2018 07:37 AM PST

    Context (you may skip)

    This is related to the recent handshake protocol I'm designing, and discussed here. While I'm very confident in the outer structure of the protocol (based on Noise, uses the same authentication method as RFC 7539), key derivation remains an issue.

    The problem is simple: deriving independent keys from X225529 shared secrets:

    AK1, EK1 = KDF(ss1) AK2, EK2 = KDF(ss1, ss2) AK3, EK3 = KDF(ss1, ss2, ss3) … AKn, EKn = KDF(ss1, ss2, ss3, …, ssn) 

    Noise solves this problem neatly with an HMAC based key derivation function HKDF, which produces 3 independent keys from a chaining key and a shared secret. One of those keys is the chaining keys, the other two are the keys I want:

    CK0 = 0 CK1, AK1, EK1 = HKDF(CK0, ss1) CK2, AK2, EK2 = HKDF(CK1, ss2) CK3, AK3, EK3 = HKDF(CK2, ss3) … 

    This makes for a very simple state machine: every time we perform a key exchange, we just update the keys, and voilà, we enjoy the full security of all preceding key exchanges. The problem is constructing the damned HKDF. Noise does it like this:

    tmp = HMAC(old_CK, ss) new_CK = HMAC(tmp, 1) new_AK = HMAC(tmp, 2) new_EK = HMAC(tmp, 3) 

    (Digression: I'm not quite sure why they do it like this. My first instinct would be to save one HMAC by having the temporary be the new chaining key.)

    Now for code size & simplicity reasons, I would very much like to avoid using a standard hash like Blake2. I have Chacha20 already, I would like to use it. The Noise HKDF has a pretty obvious compress / expand structure (a bit like sponges), and expanding stuff is the very point of stream ciphers. So I know for a fact that the following is secure:

    new_CK = compress(old_CK, ss) new_AK = Chacha20(old_CK)[ 0-31] new_EK = Chacha20(old_CK)[32-64] 

    Problem

    Ideally, I want a Chacha20 based compression function (and output filter), that absorbs 64 bytes of input, and outputs a 32 bytes hash. Basically, it needs do the same as HMAC(HMAC(old_CK, ss), 1).

    Give me that, and my protocol is done.

    Attempted solutions

    My first attempts included:

    1. new_CK = HChacha20(ss) XOR old_CK 2. new_CK = HChacha20(ss, ctr) XOR old_CK 3. new_CK = HChacha20(ss XOR old_CK) 

    The first is obviously broken, because two identical shared secrets along the chain would cancel each other out. The second is better, and I just found pretty similar to Rumba20, provided we don't have too many iterations (cryptanalysis have shown that collision are easily found if we compress too many shared secrets that way). The third… Well, the third is my favourite so far, due to its simplicity, not being obviously broken, and its similarity with other stuff I've seen (sponges, and the Argon2 compression function). But it's still not obviously right.

    Now for practical purposes, we don't really need the full security of a compression function (and subsequent output filter). Attackers don't fully control the outputs, they only control the public key part of the shared secrets. And even if they can force the shared secret to anything they like (preimage attack on X25519), the only possible values are either 0 or somewhere on the curve, which is pretty restricted. Still, it would be nice to have something that would behave like a genuine compression function.

    A second idea I haven't yet tried is a more sponge-like construction: HChacha20 doesn't have just 32 bytes worth of input, it has 48. We could use the spare 16 bytes to absorb the shared secret in two invocations:

    tmp1 = HChacha20(old_CK, ss[ 0-15]) new_CK = HChacha20(tmp1 , ss[16-31]) 

    I don't like the computational cost (though it's much better than Noise's HMAC(HMAC())), but the code is very simple, and it eliminates the funny XOR business that makes everyone nervous.

    On the other hand, it's not a proper sponge. It's very similar to a sponge in overwrite mode, but new_CK doesn't come from the bitrate part of the sponge, it comes from the capacity part. I'm not sure this is actually dangerous, but we could make a proper sponge (duplex construction) by instead using the full Chacha20 (C is 32 bytes and uses the key space. R is 16 bytes and uses the nonce and counter space):

    tmp_R || tmp_C = Chacha20(old_R XOR ss[ 0-15], old_C)[0-48] new_R || new_C = Chacha20(tmp_R XOR ss[16-31], tmp_C)[0-48] CK = tmp_R || new_R 

    A simpler alternative would be the overwrite mode:

    R1 || tmp_C = Chacha20(ss[ 0-15], old_C)[0-48] R2 || new_C = Chacha20(ss[16-31], tmp_C)[0-48] CK = R1 || R2 

    Note that CK no longer chains anything. The chaining state is now R and C (or just C in the overwrite mode).


    Any other ideas? Risks that I might not have seen?

    submitted by /u/loup-vaillant
    [link] [comments]

    Privacy-preserving ML: Crafting building blocks for secure AI

    Posted: 04 Nov 2018 04:40 AM PST

    Veracrypt encryption process on Linux?

    Posted: 04 Nov 2018 02:01 PM PST

    Hello all! I have 1.24 TB of 3.64 TB full on a backup drive. I'd like to have the entire thing encrypted, but will it erase my data already there? (if I use the SDA method)

    Thank you!

    (If I should pick another sub, that's okay. Tell me!)

    submitted by /u/bv9900
    [link] [comments]

    No comments:

    Post a Comment