ietf-smime
[Top] [All Lists]

Re: A New Triple-DES Key Wrap Algorithm

1999-02-04 17:09:49
Fair enough, Russ.

The only problem is that I have never known a standard that didn't 
end up being picked up and used by another group, many times inappropriately,
because they didn't understand the context and limitations of the original 
effort.

Any comments on my proposed solution?

bob

Russ Housley <housley(_at_)spyrus(_dot_)com> 02/04/99 02:18PM >>>
Bob:

I do not mind if a group goes off and solves the most general problem, but
that is not the problem that I have.

In the S/MIME v3 environment and other environments that use the
Cryptographic Message Syntax (CMS), the KEK and CEK will always be
symmetric keys.  If we could come to closure on one symmetric key wrapping
another symmetric key, it would be very helpful to the S/MIME v3 effort.
In fact, wrapping one 3DES key in another 3DES key is the highest priority,
and wrapping one RC2 key in another RC2 128-bit key is the next highest
priority.

Russ


At 12:57 PM 2/4/99 -0700, Bob Jueneman wrote:
Peter,

The only [small] problem I have with your approach is performance,
as double encryption with triple-DES is relatively expensive, especially 
if you don't save and reuse the state after the three key expansions 
step in DES.  In addition, I would like to have a key wrapper format
that is completely independent of the KEK algorithm, soi that I can use
the same wrapper whether I use DES, RSA, elliptic curves, etc. And
I don't think you want to propose doing double encryption with an 
asymmetric cipher!

What I would suggest would be to replace your inner encryption 
with the equivalent of Output Feedback mode, but using SHA-1
as the encryption or whitening function, with a random nonce R serving 
as the starting seed for SHA-1.  

In other words, begin by computing SHA-1(R) of the random nonce, and 
call that W(1).  Then W(2) = SHA-1(W(1)), and W(n) = SHA-1(W(n-1)),
where n= length(keyblob + encryption block size)/160 rounded up to 
the next SHA-1 block boundary, so that any necessary padding is whitened
as well.

Then XOR the string of W(1)...W(n) with the keyblob KB(1)...KB(n) to 
produce the whitened plaintext of the keyblob, P(1)...P(n).

Finally, encrypt R || P(1)...P(n) using whatever KEK algorithm is desired.

Now the only question I have is whether the fact that the whitening 
does not involve the plaintext and is therefore known once the random
nonce has been decrypted can somehow be used to leak information,
given partially known plaintext in the keyblob. It would if the nonce weren't
secret, but in order to gain any information about the nonce would require
finding a ciphertext block that matches a specific block, corresponding to R, 
rather than merely finding any two matching blocks.

So I don't see an attack, regardless of the type of KEK encryption algorithm
used, including both symmetric and asymmetric algorithms. Does anyone else?

I do concede that this approach produces some data expansion -- at least 160 
bits for the random nonce, and perhaps some more for padding if the keyblob 
that
is being encrypted is not an exact multiple of the encryption block size.
Generally speaking, that is a tradeoff I would be willing to make.

Bob


Peter Gutmann <pgut001(_at_)cs(_dot_)auckland(_dot_)ac(_dot_)nz> 02/05/99 
02:46AM >>>

[Note: Recipient list trimmed to those who've shown an interest so far]

Instead of using OAEP-type padding (which is rather complex to implement and 
results in data expansion), why not just encrypt the wrapped key twice?  This 
way, the outer encryption layer depends on every bit in the inner encryption 
layer, and that depends on the plaintext and MEK, so you never get lots of 
identical messages encrypted with different keys.  This is trivial to 
implement, requires no extra algorithms beside than the cipher used for the 
wrapping, and results in no data expansion.  Here's how it works:

 Notation: 

 P[] = plaintext blocks
 C1[], C2[] = ciphertext blocks encrypted once/twice

 Encryption:

 Encrypt P[ 0 ]...P[ n ] using the initial IV
 Encrypt C1[ 0 ]...C1[ n ] using the existing IV from the previous pass 
       (ie C1[ n ])

 Decryption:

 Decrypt C2[ 1 ]...C2[ n ] using C2[ 0 ] as the IV
 Decrypt C2[ 0 ] using C1[ n ] as the IV
 Decrypt C1[ 0 ]...C1[ n ] using the initial IV

Peter.