# Attack on Double Encryption Scheme

In this protocol:

1. A → B : { <[A, {K}pk(B)]> }pk(B)
2. B → A : { <[B, {K}pk(A)]> }pk(A)

I'd like to determine why this is insecure. How can the attacker learn the key K if A and B are both honest agents?

This is what I have started with:

1. A → B : { <[A, {K}pk(B)]> }pk(B)

An attacker M can intercept this, however M cannot decrypt this. M sends it to B so B thinks the message is coming from M:

1. M → B : { <[A, {K}pk(B)]> }pk(B)

Then I run into the problem that A's identity is still in the message. When B decrypts, he will realize that D and A do not match, and end the session.

Any help, hints, or advice would be appreciated! Thanks!

• Why does B reply? – SEJPM Jul 28 '15 at 21:42
• I think I've found the attack... Hint: What else can M do besides trying to forward / decrypt the message? – SEJPM Jul 28 '15 at 21:44
• I'm honestly not sure. I'm new to cryptography and am trying to learn on my own. I came across this problem and it didn't come with a solution, but I'm having trouble coming up with my own! Perhaps...What if M knows that A's identity will be the first part of the message? M then knows what the first part should look like and can break the decrypted message that way? – CoCo72 Jul 28 '15 at 23:29
• Is the PKE scheme assumed to be CCA-secure? $\;$ – user991 Jul 29 '15 at 9:47
• @RickyDemer, I'd think so. The attack I found doesn't need it to be non-CCA secure. – SEJPM Jul 29 '15 at 9:53

EDIT: I think what I do is provide a little more than a hint so don't read further if that is an issue.

This problem is very much like the NSL protocol in that it allows an intermediary due to neither party declaring their own identity:

That is:

A -> E : { <[A, {K}pk(E)]> }pk(E) } E -> B : { <[A, {K}pk(B)]> }pk(B) } B -> E : { <[B, {K}pk(A)]> }pk(A) } E -> A the above

Resulting in:

Now B believes it has a shared channel with A but E is involved. You can even simplify and omit A entirely since its existence was never proven to party B:

Alternatively:

E -> B : { <[A, {K}pk(B)]> }pk(B) } B -> anyone : { <[B, {K}pk(A)]>}pk(A) }

and

Now 'B' presumably believes key $K$ is shared with party $A$ when in fact party $E$ holds a copy.

I'll just write up a nice answer on how I think the protocol is broken.
Read one hint by the other and think about each hint some time before proceeding to the next one. Their usefulness increases.

Hint 1:

An attacker may not only observe packets but only drop or replace them.

Hint 2:

The attack involves no decryption from the attacking party.

Hint 3:

The attack assumes a man-in-the-middle scenario.

Hint 4:

The attack would be prevented by key confirmation.

Hint 5:

The attacker learns the secret key by supplying it.

Attack:

A initiates a standard protocol run with B. M is a man-in-the-middle and drop A's initial packet. M formulates the packet $M\rightarrow B: \{ <[A, \{K_M\}pk(B)]> \}pk(B)$ with a $K_M$ of his choice. B continues the protocol as normal and sends the standard message to A except that $K$ is replaced by $K_M$ as he thinks, that's what A sent. Now M knows the shared key between both parties ($K_M$). This attack only works against the protocol given at hand. If A check wether $K=K_M$ he can find out that there was an attack and can alert B but if A just uses the key received in the second message, the attack works.

I believe I may have come up with a solution that makes the double encryption scheme problematic.

As in the protocol, A sends the packet to B:

A → B : { <[A, {K}pk(B)]> }pk(B)

Now, let m1 be the entire packet and m2 be the encrypted key K:

m1 = <[A, {K}pk(B)]>

m2 = K

Some attacker M intercepts A's message. M forms her own packet to send to B:

M → B : { <[M, {m1}pk(B)]> }pk(B)

Which is equivalent to:

M → B : { <[M, { <[A, {K}pk(B)]> }pk(B)]> }pk(B)

B receives M's message. He decrypts the first layer, see's M's identity, and decrypts the second layer to reveal what he believes the key K to be. Then, following the protocol, B responds, encrypting with the public key of M since M's identity was in the message:

B → M : { <[B, {m1}pk(M)]> }pk(M)

Which is equivalent to:

B → M : { <[B, { <[A, {K}pk(B)]> }pk(M)]> }pk(M)

Now M has decrypted the first layer. M again sends a message to B:

M → B : { <[M, {m2}pk(B)]> }pk(B)

Which is equivalent to:

M → B : { <[M, {K}pk(B)]> }pk(B)

B responds similarly as before:

B → M : { <[B, {m2}pk(M)]> }pk(M)

Which is equivalent to:

B → M : { <[B, {K}pk(M)]> }pk(M)

And now M has the key K.