Subject: [hybi] proposed masking

From: John Tamplin <[email-masked]>
Date: Thu, 23 Dec 2010 14:19:25 -0500

Given that so far there seems to be general support for GET+Upgrade
with client->server masking, I thought I would write up a starting
point for a proposed masking algorithm.

Assuming the following:
- the client generated and sent a nonce in the handshake request
- the server generated and sent a nonce in the handshake response
- the handshake is already completed successfully

To send a frame, the client performs the following steps:
- chooses a random per-frame-key (size TBD based on brute force
attacks against the key, but likely 4-8 bytes)
- computes the 20-byte SHA1 of the string "WebSocket", server-nonce,
client-nonce, per-frame-key (in that order)
- send the per-frame-key
- XORs each byte in the frame, including headers and after compression
if any, with successive bytes of the SHA1 hash and sends them

To receive a frame, the server performs the following steps:
- read the per-frame-key
- computes the 20-byte SHA1 of the string "WebSocket", server-nonce,
client-nonce, per-frame-key (in that order)
- reads the frame, XOR'ing each read byte with successive bytes of the SHA1 hash

Note that the client can cache the SHA1 state after the client-nonce
has been added if desired, which would limit per-frame computation to
only adding the per-frame-key to the hash.

--
John A. Tamplin
Software Engineer (GWT), Google

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 23 Dec 2010 11:28:08 -0800

> only adding the per-frame-key to the hash.

A few comments as token crypto-oriented guy:

(1) I'd prefer a UUID to the WebSocket string.
(2) I'd prefer HMAC to SHA-1...

(1) seems like it has no impact on performance. (2) makes performance worse
by a
factor of about 2 but is better crypto-wise. I can live with SHA1, however.

-Ekr

-Ekr

---

From: John Tamplin <[email-masked]>
Date: Thu, 23 Dec 2010 15:11:35 -0500

On Thu, Dec 23, 2010 at 2:28 PM, Eric Rescorla <[email-masked]> wrote:
> (1) seems like it has no impact on performance. (2) makes performance worse by a

Ok, so something like:

key = SHA1(WebSocketGUID || server-nonce || client-nonce)
maskBytes = HmacSHA1(key, per-frame-key)

Is that what you are suggesting?

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 23 Dec 2010 21:32:04 +0100

John,

Can we use the already defined extension data section of the frame to carry
the key.

This is not to say that we make it optional (that's a discussion for another
day), but just that the extension area has already been defined to carry
frame meta data, so we should use it for that.
Perhaps "extension data" is the wrong name for that area and maybe it would
be more acceptable to call it metadata (which can include mandatory meta
data and extension).

So a frame would look like

     0                   1                   2                   3
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-------+-+-------------+-------------------------------+
    |M|R|R|R| opcode|R| Payload len |         Metadata length       |
    |O|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
    |R|V|V|V|       |V|             |   (if payload len==126/127)   |
    |E|1|2|3|       |4|             |                               |
    +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
    |     metadata payload length continued, if payload len == 127  |
    + - - - - - - - - - - - - - - - +-------------------------------+
    |                               |  Key         |    Meta data   |
    +-------------------------------+ - - - - - - - - - - - - - - - +
    :                                                               :
    +---------------------------------------------------------------+
    :                       Masked Application data                 :
    +---------------------------------------------------------------+

---

From: John Tamplin <[email-masked]>
Date: Thu, 23 Dec 2010 15:44:19 -0500

> frame meta data, so we should use it for that.

One problem with masking only the payload is that future extensions
might carry attacker-controlled data.  Also, I think it is cleaner to
have the same framing for both the client and server, and the only
difference is the presence of a mask from a key read before the frame
itself.  From an implementation viewpoint, that makes it easy to read
the rest of the frame in common code -- if I have a non-empty XOR
mask, I XOR each byte with a byte from the mask before processing it.

> be more acceptable to call it metadata (which can include mandatory meta

The current spec says it is only present if any reserved bits are
non-zero.  We can change that, but it makes it more awkward.

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 23 Dec 2010 23:38:40 +0100

John,

The problem with XORing the entire frame is that it means that any handling
that does not care about the content, but does care about the framing will
still need
to process the XOR in order to observe the frame header.

The masking could be specified that it applies to all extension data after
the key, as
well as to the payload itself.

regards

---

From: Brian <[email-masked]>
Date: Thu, 23 Dec 2010 16:26:11 -0800

That seems to be getting overly complicated, IMO.  I'm for just XORing
the entire frame for simplicity.

If the server doesn't care about the payload data, then what's the
point?  If it does care about the payload, then it's going to have to
unmask it at some point anyway, so I don't see the benefit.

The situations cited that require super high performance and low
overhead have traditionally been cluster-interconnect or message-buss
type scenarios within a trusted datacenter, in which case masking
could just be disabled.

It's somewhat amusing though that we're talking about basically adding
another framing layer to the framing.  Yet that is definitely the
simplest thing to do.

Brian McKelvey

On Thu, Dec 23, 2010 at 2:38 PM, Greg Wilkins <[email-masked]> wrote:
> _______________________________________________
> hybi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/hybi
>
>

---

From: Gabriel Montenegro <[email-masked]>
Date: Fri, 24 Dec 2010 01:23:30 +0000

> It's somewhat amusing though that we're talking about basically adding another
> framing layer to the framing.  Yet that is definitely the simplest thing to do.

That's how I think about it. Essentially, the framing layer prepares everything for transmission, and then hands off, except it does not go immediately to the network, but to the "masking layer" first.

---

From: Maciej Stachowiak <[email-masked]>
Date: Thu, 23 Dec 2010 19:18:00 -0700

> mask, I XOR each byte with a byte from the mask before processing it.

I agree. I think masking should mask everything else in the frame besides the per-frame key, including the opcode and data length, not just the actual data. This provides better protection against premade frames, since it's not possible to even send or read a well-formed frame without properly completing the handshake.

Regards,
Maciej

---

From: Patrick McManus <[email-masked]>
Date: Thu, 23 Dec 2010 21:36:10 -0500

> I agree. I think masking should mask everything else in the frame besides the per-frame key, including the opcode and data length, not just the actual data. This provides better protection against…

+1

---

From: Maciej Stachowiak <[email-masked]>
Date: Thu, 23 Dec 2010 23:02:40 -0700

As long as the client nonce, server nonce and per-frame key are included, I am satisfied with any particular algorithm that the crypto experts think is ok.

Some questions though:

- Is SHA1 or HMac-SHA1 significantly less expensive than using AES-CTR? AES-CTR would greatly reduce the ability to brute force the XOR mask, since the key stream would not repeat every 20 bytes.

- It seems like this mechanism gets weaker if it ever becomes possible to reverse SHA-1, and SHA-1 already has some known partial weaknesses against preimage attacks. Perhaps we should use a better hash. I do not know what the current state of the art in this area is.

Regards,
Maciej

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 23 Dec 2010 22:55:30 -0800

On Thu, Dec 23, 2010 at 10:02 PM, Maciej Stachowiak <[email-masked]> wrote:

>
> As long as the client nonce, server nonce and per-frame key are included, I
> am satisfied with any particular algorithm that the crypto experts think is
> ok.
>
> Some questions though:
>
> - Is SHA1 or HMac-SHA1 significantly less expensive than using AES-CTR?
> AES-CTR would greatly reduce the ability to brute force the XOR mask, since
> the key stream would not repeat every 20 bytes.
>

It's important to distinguish between using a stream cipher to generate
fresh keying material for the whole block versus
just to generate a short repeating mask. We could use AES or SHA-1 in either
configuration. The repeating mask
is faster by a fraction dictated by the size of the packet (ie., the bigger
the packet the more edge it gives you).

In general, AES seems preferable, both because it's faster and because it's
more conventional. However, SHA-1,
whether in HMAC mode or in regular mode, is less likely to fall afoul of
export type rules, and also has the advantage
that you can use it both for key derivation and masking. In all of these
cases
you would just run the algorithmic core forward in CTR mode, e.g.,
HMAC-SHA1(key, ctr)...

Strawman suggestion:

Key = HMAC-SHA1(uuid, client-nonce || server-nonce)
Mask = HMAC-SHA1(key, per-block key || i) where i is the block index.

> - It seems like this mechanism gets weaker if it ever becomes possible to
> reverse SHA-1, and SHA-1 already has some known partial weaknesses against
> preimage attacks. Perhaps we should use a better hash. I do not know what
> the current state of the art in this area is.
>

 I don't *think* that's the case, since the attacker never gets to see SHA-1
output that corresponds to a secret
which would be useful to him. I.e., he knows the Key and the per-block key
is random anyway and never
reused. But I don't have a proof of this.

-Ekr

---

From: Greg Wilkins <[email-masked]>
Date: Fri, 24 Dec 2010 08:08:18 +0100

On 24 December 2010 02:23, Gabriel Montenegro <[email-masked]> wrote:

> another
> That's how I think about it. Essentially, the framing layer prepares
> everything for transmission, and then hands off, except it does not go
> immediately to the network, but to the "masking layer" first.
>

This does mean that intermediaries will always need to un-mask frames, then
potentially remask them.  This seams unnecessary.

Also it means that the server will not be able to unmask in 1 operation, as
it will have to unmask the frame as it is received so that it can see the
frame header and determine the frame boundaries.   This is a lot more
complex than parsing the frame and then unmasking the payload.

---

From: Greg Wilkins <[email-masked]>
Date: Fri, 24 Dec 2010 08:34:53 +0100

The other issue with having masking applied to the framing, is that is
forces our hand with regards to the mandatory vs optional debate.
Once it is deployed where WS intermediaries must apply masking so they can
understand the framing (and other extensions), then there will be no way to
turn it off or replace it with something else, because intermediaries will
have been written that have the masking hard coded - when they don't even
care about the payload.

Not masking the framing, will allow intermediaries to be written that treat
the payload opaquely, and thus never apply the unmasking.  Such
intermediaries will be more robust in light of future changes and thus will
allow greater flexibility.

The whole point of the extension mechanism was to allow for such future
changes without the need to reimplement the low levels of the protocol frame
handling.

On 24 December 2010 08:08, Greg Wilkins <[email-masked]> wrote:

>
>
> On 24 December 2010 02:23, Gabriel Montenegro <[email-masked]>wrote:
>

---

From: Brian <[email-masked]>
Date: Fri, 24 Dec 2010 02:23:58 -0800

Ah yes, you make a good point!  Definitely something to consider in
more detail then.

Brian McKelvey

On Thu, Dec 23, 2010 at 11:34 PM, Greg Wilkins <[email-masked]> wrote:
>> This does mean that intermediaries will always need to un-mask frames,
>> then potentially remask them.  This seams unnecessary.
>>
>> Also it means that the server will not be able to unmask in 1 operation,
>> as it will have to unmask the frame as it is received so that it can see the

---

From: John Tamplin <[email-masked]>
Date: Fri, 24 Dec 2010 08:52:04 -0500

> potentially remask them.  This seams unnecessary.

I'm not sure exactly what intermediary you are thinking of here.
There are two types I see that care about the framing:

- inspection intermediaries
  they want to inspect the content for porn, IP leaks, etc, and therefore
  must unmask
- aggregation intermediaries
  a multiplexing or demultiplexing intermediary will have to unmask
  logical streams and the remask the combined stream, so again they
  have to unmask

Given the nature of WebSockets, any caching intermediary would have
to be application-specific, and would have to unmask the content.  Any
WS termination appliance would necessarily also have to unmask the
content.

It seems to me the only intermediary that wouldn't need to unmask the
content is something that exists below the WS protocol level, in which
case it doesn't need to understand the WS framing.  Can you give an
example of one that mgiht?

> complex than parsing the frame and then unmasking the payload.

I am not convinced this is more complex.  For example, in a blocking client
you just push a decoding module onto your stream (see
http://code.google.com/p/websocket-draft-eval/source/browse/trunk/src/com/google/websocket/AdamBarthHandshake.java?r=18#233
for an similar example following Adam's original proposal of AES.

If you are writing a non-blocking client, you already have a state machine
to keep track of where you are in processing the frame, and it seems to me
it simply has different states but is no more complex.

---

From: John Tamplin <[email-masked]>
Date: Fri, 24 Dec 2010 10:28:16 -0500

I am not still not sold on the idea of optional masking for the
following reasons:
 - when we discussed the framing, the objection about complexity for simple
   implementations was met with "if you don't negotiate any extensions, you
   never have to worry about any of the reserved bits or extension data".
   Having to do so means even simple implementations get pretty complex,
   and this is especially true when dealing with fragmentation of extension
   data.
 - we can't allow servers to refuse the masking extension, since we assume
   the attacker controls the server.  Therefore, we have to define "mandatory"
   extensions that the client will drop the connection if requested by
the server
   doesn't accept them.
 - defining an extension that has metadata now forces us to define the format
   now, which previously was problematic when trying to decide on the framing.
   This includes interaction with fragmentation and potential
extensions like MUX,
   and whether extension data is per-message or per-fragment, or the interaction
   between them if both are allowed.

However, I thought I would write up how it could work so we have
something concrete to talk about.  This is just a straw-man proposal
and there are some rough edges.

1. Change RSV4 in the spec to EXTDATA.  It defines that if set, "extension
    data" has a non-zero length.
2. In section 8, define mandatory extensions as extensions which the client
    MUST fail the connection if requested but not accepted by the server.
3. Define the format of "extension data":
     - offiicial mandatory extensions MAY define untagged data to be
present in the
       extension data, but MUST define all ordering constraints
relative to all other
       official extensions at the time it is standardized.
Non-official extensions MUST
       use the tag/value format.
     - after any untagged extension data, a series 0 or more of
tag/value pairs are
       present:
         tag (9 bits) - identifies the extension using this data
         length (7 bits, plus 0, 2, or 8 more bytes) - the length of
this extension value,
             interpreted the same as the Payload Length field
     - extension data is per-message and may be fragmented at any byte boundary,
       including within an untagged value or in the middle of a
tag/length.  Any frame
       with any extension data MUST have EXTDATA set.   A frame ending in the
       middle of an complete value (whether untagged or
tag/length+value) with the
       next frame having EXTDATA clear, or a final frame (MORE is unset)  is an
       error and will cause the connection to fail.
4. Define "clientmask" as an official mandatory extension:
    - all WS clients capable of making requests on behalf of untrusted code MUST
      request the clientmask extension and MUST fail the connection if
not accepted
      by the server.  However, such a client MAY rely on a known
intermediary over
      a trusted network to request the clientmask extension (for
example, a mobile
      phone client might not apply the masking itself if it forces all
connections
      through an intermediary on the provider's network which does require the
      clientmask extension).  A client which does not permit any
connections outside
      of a trusted network MAY choose not to request the clientmask extension.
    - intermediaries MAY remove masking only if the remainder of the
network from
      the intermediary to the ultimate server is trusted
    - if clientmask is negotiated, EXTDATA will be set on any frames
sent from the
      client to the server.  The first [4-8, TBD] bytes of extension
data are a masking
      key, and the entire remainder of the frame (including any other extension
      data, are masked according to the masking algorithm defined below.
    - the masking key exists only at the beginning of a message, and applies to
      the remaining extension data in the initial frame, as well as
all of the extension
      data in future frames, and all of the application data in the message.

      TODO: define a trusted network

5. Masking algorithm:

Let client-nonce and server-nonce be the respective nonces exchanged during
the handshake.  Let uid be a 20-byte constant defined in the standard, and
per-frame-key be the masking key read from the extension data.

// computed once during the handshake
sessionKey = HMAC-SHA1(uid, client-nonce || server-nonce);

for (int blockStart = 0; blockStart < remainingLength; blockStart += 20) {
  mask = HMAC-SHA1(sessionKey, per-frame-key || blockStart);
  for (int i = 0; i < 20 && blockStart + i < remainingLength; ++i) {
     remainingPayload[blockStart + i] ^= mask[i];
  }
}

The same operation is performed for masking and unmasking.

---

From: Maciej Stachowiak <[email-masked]>
Date: Fri, 24 Dec 2010 23:35:36 -0700

>   between them if both are allowed.

I addition to these issues, making masking an extension creates greater risk of attacking (possibly sloppy) WebSocket servers with browser-hosted HTTP clients. One of the purposes of masking is to protect against this threat model. With masking, it is impossible for malicious script to pre-generated a POST body that will be interpreted as WebSocket frames by the server. However, if masking is an extension, and servers are required to respect the absence of that extension, then whenever you use an HTTP client to try to talk to a WebSocket server, and for whatever reason the server doesn't check for "Upgrade: WebSocket" carefully enough, then the server won't see the extension and won't expect masking. Thus, the defense in this scenario is completely neutered.

Some might argue that checking for "Upgrade: WebSocket" is a sufficient security check, since as far as we know, there's no browser-based way to emit a cross-domain HTTP request with this header. However, if a server has improperly lenient checking for "Upgrade: WebSocket", for instance, it doesn't check at all, or it checks in an overly loose way, such as with a regexp, then this will not be noticed during normal operation. But masking requires the server to check the nonce parts of the handshake correctly to function even in normal operation. Thus, checking for "Upgrade: WebSocket" is likely to be a weaker defense.

For this reason, in addition to the issues you listed, I don't think I can live with masking as an extension. It's just too risky.

Regards,
Maciej

---

From: John Tamplin <[email-masked]>
Date: Sat, 25 Dec 2010 10:02:11 -0500

On Dec 25, 2010 1:35 AM, "Maciej Stachowiak" <[email-masked]> wrote:
I addition to these issues, making masking an extension creates greater risk
of attacking (possibly sloppy) WebSocket servers with browser-hosted HTTP
clients. One of the purposes of masking is to protect against this threat
model. With masking, it is impossible for malicious script to pre-generated
a POST body that will be interpreted as WebSocket frames by the server.
However, if masking is an extension, and servers are required to respect the
absence of that extension, then whenever you use an HTTP client to try to
talk to a WebSocket server, and for whatever reason the server doesn't check
for "Upgrade: WebSocket" carefully enough, then the server won't see the
extension and won't expect masking. Thus, the defense in this scenario is
completely neutered.
>
> Some might argue that checking for "Upgrade: WebSocket" is a sufficient
security check, since as far as we know, there's no browser-based way to
emit a cross-domain HTTP request with this header. However, if a server has
improperly lenient checking for "Upgrade: WebSocket", for instance, it
doesn't check at all, or it checks in an overly loose way, such as with a
regexp, then this will not be noticed during normal operation. But masking
requires the server to check the nonce parts of the handshake correctly to
function even in normal operation. Thus, checking for "Upgrade: WebSocket"
is likely to be a weaker defense.
>
> For this reason, in addition to the issues you listed, I don't think I can
live with masking as an extension. It's just too risky.

This concern could be addressed by having something generated from the
client/server nonces in a hello frame after the handshake.

---

From: Maciej Stachowiak <[email-masked]>
Date: Sat, 25 Dec 2010 17:12:29 -0700

On Dec 25, 2010, at 8:02 AM, John Tamplin wrote:

> This concern could be addressed by having something generated from the client/server nonces in a hello frame after the handshake.
> 
If the server doesn't need to check validity  of the hello frame to successfully handle the normal case, then it's nearly as weak as expecting the server to check for "Upgrade: WebSocket". I say "nearly" because you couldn't as readily exploit client-side bugs to send it, but you could just as easily slip it by an overly lenient server. Masking doesn't have this issue at all, if it is mandatory, since the server must correctly compute the send key in the same way as the client to be able to interpret frames at all, even in the non-attack case.

Thus, a hello frame would not address my objection to making masking an optional extension on the server side. (Hello frames are also redundant in the presence of masking, but we can have that discussion once we get masking in.)

Regards,
Maciej

---

From: Bruce Atherton <[email-masked]>
Date: Sun, 26 Dec 2010 13:39:11 -0800

>     and this is especially true when dealing with fragmentation of extension

If the specification is written as I described, where the default 
masking is specified and only a mention is made that alternate masking 
strategies could be used, then simple implementations will only use the 
default scheme. If the default scheme is used when no extension is 
specified, then there is no added complexity.

>     extensions that the client will drop the connection if requested by

Given what I said above, I can't see that this is relevant. Perhaps I am 
misunderstanding, though. If so feel free to enlighten me.

>     between them if both are allowed.

Given the above, I can't see why you can't handwave this away for now 
until you are ready to tackle it. Just keep in mind in other discussions 
that an extension may replace the default masking with something else.

---

From: Bruce Atherton <[email-masked]>
Date: Sun, 26 Dec 2010 13:41:04 -0800

On 24/12/2010 10:35 PM, Maciej Stachowiak wrote:
> I addition to these issues, making masking an extension creates greater risk of attacking (possibly sloppy) WebSocket servers with browser-hosted HTTP clients.

I'm confused. You yourself suggested the solution to this[1],  that if 
an extension to allow either masking or no masking were required, the 
lack of an extension should indicate that masking is present. Have I 
lost the thread here?

[1] http://www.ietf.org/mail-archive/web/hybi/current/msg05255.html 
(point 3 in the list)

---

From: John Tamplin <[email-masked]>
Date: Sun, 26 Dec 2010 20:13:43 -0500

On Sun, Dec 26, 2010 at 4:39 PM, Bruce Atherton <[email-masked]> wrote:
> If the specification is written as I described, where the default masking is
> specified and only a mention is made that alternate masking strategies could
> be used, then simple implementations will only use the default scheme. If
> the default scheme is used when no extension is specified, then there is no
> added complexity.

If all you want is language in the spec saying other masking methods
may be specified by future extensions, then I am certainly that.
However, I don't know that it actually changes anything, because
implementations today will not know what those future extensions are
and therefore can't interpret them until they are modified to support
the new encoding.  That is exactly the same as what your objecting
about my original proposal, other than informing implementors that it
might change so they might design their implementation to make it
easier to upgrade in the future.  That seems of little value, but I
certainly don't have any problem including such language in the spec.

> Given the above, I can't see why you can't handwave this away for now until
> you are ready to tackle it. Just keep in mind in other discussions that an
> extension may replace the default masking with something else.

The point of the optional masking proposal was to addressed concerns
raised by Greg and others, in that we essentially are defining a new
framing for masked frames.  If instead, we use the extension points
already present in the framing, we keep one framing instead of two.
However, the framing as currently written requires that all reserved
bits are 0 and the extension data is 0 if no extensions are
negotiated.  So making the client masking the default and having an
extension to turn it off while still using the extension-data field
would require changes to the framing.  Certainly it is possible, but
given how contentious it was the first time I don't look forward to
trying to do that.  So, the optional masking proposal was just an
attempt to write up a concrete proposal of how it would fit in with
the extension mechanism already defined in the current framing.

The above paragraph also answers your question about Maciej's message.

---

From: "Martin J. Dürst" <[email-masked]>
Date: Mon, 27 Dec 2010 16:46:16 +0900

On 2010/12/24 15:55, Eric Rescorla wrote:
> On Thu, Dec 23, 2010 at 10:02 PM, Maciej Stachowiak<[email-masked]>  wrote:

> reused. But I don't have a proof of this.

I was just thinking about the following conceptual attack:
- Client sends extremely, extremely long frame.
- Server somehow gets start of frame, and sends key used back to the 
client in a separate frame.
- Client knows key and is now able to attack the extremely, extremely 
long frame that is still in the process of being sent.

This would require that for very long stuff, the client can 'compose' a 
frame from several pieces. It's not currently the case, but we have to 
make sure it doesn't get possible in the future.

Regards,   Martin.

-- 
#-# Martin J. Dürst, Professor, Aoyama Gakuin University
#-# http://www.sw.it.aoyama.ac.jp   mailto:[email-masked]

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 27 Dec 2010 00:46:47 -0800

On Dec 23, 2010, at 10:55 PM, Eric Rescorla wrote:

>  I don't *think* that's the case, since the attacker never gets to see SHA-1 output that corresponds to a secret
> which would be useful to him. I.e., he knows the Key and the per-block key is random anyway and never

I'm assuming the following proposed scheme for determining the mask bytes per frame:

The reason I worry about reversing SHA-1 in light of this scheme is:

- Assume we are worrying about a threat model where the server may be malicious.
- Server sees the client nonce before it has to send the server nonce.
- Server can choose server nonce such that "key" is a chosen value.

I'm not enough of a crypto expert to know how bad this would be, or whether reversing SHA-1 is ever likely to become practical. But it seems like at the very least the server has negated the entropy in the client-nonce, thus leaving the per-frame-key as the only effective source of entropy, with respect to these particular threat models.

(I would also assume this doesn't make things any worse in the case where you can correctly predict a per-frame key, since in that case the server could compute the maskBytes and tell the script running in the client).

Regards,
Maciej

---

From: Adam Barth <[email-masked]>
Date: Mon, 27 Dec 2010 00:59:54 -0800

On Mon, Dec 27, 2010 at 12:46 AM, Maciej Stachowiak <[email-masked]> wrote:
> I'm not enough of a crypto expert to know how bad this would be, or whether
> reversing SHA-1 is ever likely to become practical. But it seems like at the
> very least the server has negated the entropy in the client-nonce, thus
> leaving the per-frame-key as the only effective source of entropy, with
> respect to these particular threat models.
> (I would also assume this doesn't make things any worse in the case where
> you can correctly predict a per-frame key, since in that case the server
> could compute the maskBytes and tell the script running in the client).

I'm not sure its worth worrying about weaknesses in SHA-1 here.  If
folks can perform pre-image attacks against SHA-1, we've got much
bigger problems, like HTTPS not working at all.

Adam

---

From: Bruce Atherton <[email-masked]>
Date: Mon, 27 Dec 2010 10:42:13 -0800

> certainly don't have any problem including such language in the spec.

Great. That makes one of you.

You are of course correct that this suggestion is far from ideal for 
dealing with the issues I've mentioned. What I would ideally like to see 
is a standard extension to introduce an alternate masking scheme, along 
with at least one alternative defined in the spec (like no masking) and 
some sort of  process that would allow others to be introduced as 
standard without requiring a rewriting of the specification.

But given how entrenched everyone is on their current perspectives and 
use cases, I see no hope whatsoever that such a thing could be 
introduced. The most I can hope for, and even here I am probably 
overreaching, is a line that alternate masking schemes could legally be 
used. At least a line like that will hopefully preclude any design 
decisions that end up ruling out the ability to use an alternate scheme, 
and offers a faint hope that such schemes may eventually show up in 
equipment where they are most needed.

And a faint hope is better than no hope at all, right?

> framing for masked frames.

Thanks for the clarification, John. I thought I was missing something 
and it turns out I was right.

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 27 Dec 2010 22:43:50 +0100

On 27 December 2010 02:13, John Tamplin <[email-masked]> wrote:
> may be specified by future extensions

That is not all I want.

I have a preference for masking to be optional and for it to be an extension.

But separately to that, I don't think I can accept masking to be
applied to framing.  This makes the parsing of frames more complex and
will force WS code that does not actually care about content to
implement masking.   If we mask framing, then we will lose for all
time the possibility of changing or making masking optional.

So I could possibly live with non-optional masking.   I might even
swallow changing the framing so that a masking key was a dedicated
part of the frame rather than extension data (although that makes
framing asymmetric - ugh!)

But I'm strongly against masking the framing itself.  Their is
absolutely no reason for it other than to prevent the possibility of
making it optional.

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 27 Dec 2010 16:30:43 -0800

> time the possibility of changing or making masking optional.

I don't think that's the case. A future no-mask extension could just result in maskBytes that are always 0. Such a design could go through infrastructure that inspects frames but hasn't been updated to no-mask.

> absolutely no reason for it other than to prevent the possibility of

That's not right. One reason for masking the framing is to make it impossible for hostile browser-hosted hosted code to pre-generate valid-looking frames. If you don't mask framing, then it is trivial to create valid-looking frames, even if the contents are scrambled. Depending on circumstances, this could still be a dangerous attack on integrity.

Regards,
Maciej

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 27 Dec 2010 16:32:35 -0800

> bigger problems, like HTTPS not working at all.

Does HTTPS have a way to move to stronger hashes in the future? If so, do we need that as well? Perhaps this is adequately covered by the existing extension mechanism.

Regards,
Maciej

---

From: Gabriel Montenegro <[email-masked]>
Date: Tue, 28 Dec 2010 00:40:37 +0000

> Does HTTPS have a way to move to stronger hashes in the future? If so, do we
> need that as well? Perhaps this is adequately covered by the existing
> extension mechanism.

After learning the hard way what happens when this is not the case, IETF protocols (like TLS) are supposed to incorporate crypto agility.
I brought this up previously, but am willing to think that the existing negotiation mechanism within the HTTP part of the handshake could take care of whatever agility is required for the masking (even if it is not explicitly specified from the get go).

---

From: Eric Rescorla <[email-masked]>
Date: Tue, 28 Dec 2010 00:22:33 -0800

HTTPS has such mechanisms.

But of course since practically all CAs use SHA-1, there would be a huge
impact if preimage attacks ever become possible.

-Ekr

On Mon, Dec 27, 2010 at 4:40 PM, Gabriel Montenegro <[email-masked]>wrote:

> After learning the hard way what happens when this is not the case, IETF
> protocols (like TLS) are supposed to incorporate crypto agility.
> I brought this up previously, but am willing to think that the existing
> negotiation mechanism within the HTTP part of the handshake could take care
> of whatever agility is required for the masking (even if it is not
> explicitly specified from the get go).