On 21 July 2013 22:40, Ben Lincoln <f70c9...@beneaththewaves.net> wrote:

> Maybe I am misunderstanding (and I apologize if so), but I don't think
> authenticated encryption will address the main problem I'm trying to solve.
> Preventing tampering is important (and I think some of what I suggested has
> the effect of making it at least a little harder to tamper with the data),
> but it's by far the secondary concern.
>

Unless your software is horribly broken to begin with - and it arguably is
given what you're attempting to do - then a MAC or authenticated encryption
is sufficient to solve *most* of your problem.



>
> The main problem is trying to reduce the likelihood that the system will
> decrypt data of a different type than it expects, and then display that
> decrypted data to the user (IE allowing them to decrypt arbitrary data
> without themselves knowing the encryption key). Unless I'm missing
> something (and that is certainly possible), then the data will always pass
> an authentication check, because it's always generated by the system in
> question - it just isn't intended to be decrypted and displayed by that
> specific part of the application.
>

The MAC covers the entire data blob, so assuming each attribute you wish to
store/retrieve has context information associated with it then it is
impossible for the attacker to forge.

Say, you have a data block which contains,

someSensitiveVariable=topsecretinfo

then trying to send that to a display function that expects

someVariableToBeDisplayed=info

won't work because your code checks the variable name (a trite example but
you get the idea).


If the attacker determines field boundaries within the data blob, they
still cannot forge a sensitive attribute into an unsensitive one because
they cannot calculate the required MAC because they do not have the
required secret key to do so.

If it were I implementing a scheme such as this, I'd do the MAC after the
encryption, include a nonce value in the blob as well as an expiry
timestamp and an identifier for the user; I'd also use a different secret
key for the MAC as to the encryption.

Be very careful with your padding and field delineation. And as
CodesInChaos said above, use a different cryptographically random IV for
encrypting each different data blob and for the MAC.


The first reason I said "most of your problem" above is that an attacker
can resubmit a valid blob and have it processed identically, viz. a replay
attack. For example,

someSensitiveTransactionAmountToTransfer=10000

could be resubmitted and your software cannot tell whether it's a duplicate
or not.  The only way past that, as far as I can see, is to keep track of
the nonce values in which case you're back to square one because you need
to have a central transaction store and may-as-well just put all your
sensitive info in there anyway, which I strongly suggest you should be
doing in the first place.


The second reason I said "most of your problem" is slightly more subtle.
 If an attacker can create encrypted fields from *plaintext* data, say they
enter their information in a form which is then encrypted and stored in the
browser, then the attacker can use the application as an oracle.  If we
furthermore consider the sensitive data and non-sensitive data in the vein
of error-correcting codes and that these span a space much smaller than the
possible space over F_2^n, and we also assume the block-size of the cipher
is small enough (64-bits is enough), it may be possible for the attacker to
iterate over that search space and generate the corresponding ciphertext
blocks, storing them in a table.  By comparing the cipher-text of sensitive
data blobs to the table, the attacker can then identify the corresponding
plaintext, essentially decrypting the sensitive data without requiring the
key.  There are optimisations to this attack which I haven't described here.

This last problem can be solved by using temporal or derived secret keys,
i.e. you have the master secret key and for each data block you combine
that with some cryptographically random data to derive a "one-time" secret
key.  However, as you'll notice we're already getting quite messy and the
scope for making a complete hash of things (pun intended) has dramatically
increased.



>
>  Using separate keys for separate types of data will go a long way there,
> but I am trying to come up with a completely separate mechanism that
> operates using a different method, but which will also help prevent the
> unwanted outcome even if someone makes a mistake and uses the same key for
> sensitive and non-sensitive data. In other words, the mechanism I'm trying
> to come up with can't involve using different keys, because I already have
> a mechanism based on that principle.


> For comparison, think of physical safety features in industrial equipment.
> The B Reactor at Hanford had a gravity-based system that would
> automatically insert the control rods in the event of a power failure, but
> there was also a system that could drop a bunch of neutron-moderating fluid
> and/or ball bearings into the reactor in case the first system jammed or
> was inoperable for other reasons. Because they were based on different
> designs, it's unlikely that they would both fail in an emergency, unless
> the emergency involved loss of gravity locally.
>

Cryptography is not nuclear reactor design, although there is a pertinent
similarity in that in both cases if you're not confident in what you're
doing then it's best to copy *precisely* a tried-and-tested solution.

While there is a minimum complexity, keeping it as simple and easy to
analyse as possible is a very good idea: the more convoluted your design
is, the more likely it is to screw-up.



>
> Alternately, in software development, we strongly encourage developers to
> check their code for e.g. buffer overflow vulnerabilities, but we also
> strongly encourage them to perform input validation so that e.g. if they
> are working on one piece of code and someone less-capable is working on
> another, and that second person introduces a buffer overflow issue,
> malicious input never makes it to the second system because the input
> validation of the first system catches it (or passes the first mechanism
> but is stopped by the second, if the skill of the two developers is
> reversed).
>
> Using HMAC or AES-GCM would improve the overall security of the system,
> but I don't think either of them address the core issue I have. That core
> issue seems like it's outside the scope of the encryption, but the reason
> I'm asking here is because I don't want to compromise the encryption in
> some way as a result.


It does *almost* solve your issue, with the caveats above.


Peter




>
>
> On 2013-07-21 13:55, CodesInChaos wrote:
>
>> 1) If you want to prevent tampering, use a MAC, not a cipher. My
>> recommendation is HMAC-SHA-2. Be sure to use a constant time equality
>> check while verifying the MAC.
>> 2) If you want to encrypt something symmetrically, use authenticated
>> encryption. Either with a specialized mode, like AES-GCM or with an
>> encrypt-then-mac scheme. Use a proper IV and don't forget to include it
>> in the MAC.
>> 3) Use separate keys for different uses. This avoids interactions
>> between different parts of the software.
>>      If you want only a single key in the config, then don't use it
>> directly. Instead derive a distinct key for each usage with a key
>> derivation function.
>>      My recommendation for a KDF is HKDF with HMAC-SHA-2 as building
>> block.
>>
>>  _______________________________________________
> cryptography mailing list
> cryptography@randombit.net
> http://lists.randombit.net/mailman/listinfo/cryptography
>
_______________________________________________
cryptography mailing list
cryptography@randombit.net
http://lists.randombit.net/mailman/listinfo/cryptography

Reply via email to