- From: Ryan Sleevi <sleevi@google.com>
- Date: Fri, 5 Oct 2012 10:14:26 -0700
- To: Zooko Wilcox-OHearn <zooko@leastauthority.com>
- Cc: "public-webcrypto@w3.org" <public-webcrypto@w3.org>
On Mon, Oct 1, 2012 at 3:08 PM, Zooko Wilcox-OHearn <zooko@leastauthority.com> wrote: > Folks: > > I apologize again for being late to today's call. Here is my current > proposal in light of today's discussion. > > 1. We agreed that WebCrypto should specify ECB. (This is a change from > my earlier position. I agree to specifying ECB because it could be > more efficient to compute AES on a number of blocks at once, such as > when implementing an encryption mode of operation.) > > 2. I propose that the ECB function take a number of input bytes which > is an integer multiple of 16, and raise an exception if the input is > of a different length. That's the standard requirement for ECB. Is this the input to processData(), or the final result upon calling .complete()? In the current processing model, and given that the intent is that calls to .processData() do not necessarily need to fire a corresponding event, I would argue that it's highly inappropriate to have length requirements on .processData(). This applies to any padding mode - ECB, CBC, OFB, GCM. If .processData() is called with a length that is not a multiple of block size (or whatever other requirements exist for the algorithm), then it should internally buffer until either the conditions are satisfied (eg: a subsequent set of calls to processData) or until a signal is received that the user is completed processing (eg: .complete()). I think it is important to detach the above semantics from the discussion of ECB, since they equally apply to other modes - such as CBC. If a non-blocksize multiple is supplied to .processData(), should the application: 1) Internally buffer until a multiple of blocksize data is available or until .complete is called 2) Fail 3) Compute the block by adding the CBC padding and immediately return it IF we choose 2, we're forcing every application developer to implement the buffering themselves. IF we choose 3, we're changing how the API behaves from most common "Init/Update/Final" APIs behave, which requires a solid justification as to why to violate expectations as such. Thus, I think the requirement for a "multiple of 16" only applies in the context of when discussing at terms of final. And I remain unconvinced as to the security benefits in practice, since any developer can (and many developers will) simply random-extend the buffer to a maximum of size, and then chop off the end. Again, I do not believe the complexity or simplicity of the *low-level* API can or should be used as a means to "prevent" bad crypto, since it's trivial to implement bad crypto atop (as I have previously demonstrated). Any value to be derived from doing so will, I strongly believe, be quickly eclipsed by the headaches involved with arbitrary or capricious complexities for developers who *do* know what they're doing. > > 3. I propose that the API and documentation clearly signal that ECB is > not an encryption mode. Specifically, I propose that the algorithms > are grouped like this: > > • Public key encryption: RSA-OAEP, RSAES-PKCS1-v1_5 > • Public key digital signature: ECDSA, RSA-PSS, RSASSA-PKCS1-v1_5 > • Key agreement: ECDH, Diffie-Hellman > • Authenticated encryption: AES-OCB, AES-GCM > • Unauthenticated encryption: AES-CTR, AES-CBC > • Message authentication code: HMAC-SHA256 > • Key-derivation functions: HKDF, PBKDF2 > • Primitives: AES-ECB, SHA256 I strongly disagree with the distinction of "SHA" as a Primitive here. While it's somewhat orthogonal to the ECB proposal, since you've decided to group all of these things together, I think it's important for "SHA" to be exposed as a "hash" - so that it can be seamlessly used with HKDF, PBKDF2, HMAC, and any other SHA-using scheme (eg: PK signing, PK encryption). That said, I have reservations about trying to organize the algorithms into an normative categories, since it goes back to the general problem of trying to find a hierarchy for all existing/supported algorithms (see for example what I believe are reasonable points re: primitives vs. hashing), and in experience, inevitably fails to consider future algorithms or alternative ways of classifying things. I would much rather present the list of algorithms as simply that - a list of algorithms - rather than trying to inject them into categories. I could live with it, if it was simply for readability, but the further comments in this e-mail make it very clear that you feel strongly about this for reasons of security, which I think is a red herring and a false premise. > > And I propose that the documentation of the AES-ECB function say > something like this: > > "NOTE: This function does not, except in special cases, conceal the > content of the message and cannot, except in special cases, be used > for encryption. It is included only for the use of cryptographers to > implement other cryptographic algorithms. For an encryption function, > please see the functions listed under Authenticated Encryption or > Unauthenticated Encryption." > > > As a framing note: I care a lot about the security of apps. My work is > sometimes used by people who risk suffering not just financial loss > but imprisonment, torture, or murder, if the confidentiality and > integrity that they need from their apps isn't there. Our work here is > destined to be used that way, too. People are already using web apps > such as Crypto.cat to say things that could get them murdered or > imprisoned if the wrong people overhear, and this trend will increase > greatly in the coming years. > > Older crypto libraries such as Crypto++ ¹, Java ², and .NET ³ > typically included ECB among a list of encryption modes, sometimes > with a warning note in the documentation. This has been repeatedly > demonstrated to lead to insecure apps which use ECB mode for > encryption of secret plaintexts. It is not hypothetical that ECB > *could* lead to this -- it is established fact that it has done so, > many times. It is such a common pattern that another instance of it > was announced while we were having this very conversation: ⁴. In that > case, a library which included ECB (with warning documentation) > adjacent to CBC mode and CTR mode led to web sites in which attackers > could take over the sessions of authenticated users. A different > library (which I wrote) which excluded ECB mode was not vulnerable to > that attack. > > So it is important to me that the WebCrypto standard doesn't replicate > these practices which have led to these vulnerabilities. My proposal > above will, I hope, avoid that. In my opinion, your proposal fails to do that, but more importantly, I do not believe our efforts should try to do prevent or solve bad crypto, as I have repeatedly stated. I do not consider that "bad software" exists to be a failure of the API. It is a failure of developers who used a tool in an incorrect way. That someone wrote a "bad .NET application" does not mean that the designers of .NET suffered from myopia - it means that some developer didn't know what they were doing did something bad. Great. That's the history of computer science. It will continue to be the history of computer science, for as long as developers are allowed to write programs that run on general purpose machines. I'm sure we can get into many ideological discussions about whether security can be done 'by convention', and what is the true way to get programmers to do "The Right Thing". I think invoking examples of "risk of life and limb", while sensational and perhaps attractive to media outlets, do not belong in a rational and technical discussion about the merits of the algorithm. I have yet to see such an emotional appeal made when discussing Content Security Policy or the Web Origin Model, which are both equally essential to web security, so I think invoking it here is simply unhelpful for balanced technical discussions. Like I said earlier, I support moves to enhance readability and organization of the spec, but I think we should be clear on why we're doing it, and I think the framing you gave is problematic, even if it ends up as a good result, because it means we'll continue to have this discussion with every algorithm. Like I mentioned on the call, I would like to eventually see the possibility of algorithms such as MD5 or 3DES, again on the basis that this is "just" a low-level API, and there are a number of places where such algorithms *can* be beneficial (either for legacy reasons or for acceptable equivalent security propositions). I'm all for including caveats on those as well - but like I said then as well - I think our overall goal is to 1) Provide an API that can expose "keys" managed by user agents without having to give origins *direct* access to the key material 2) Provide an API that allows useful transformations/operations to be performed on those keys, for any particular value of "useful". Not to save lives or solve bad crypto.
Received on Friday, 5 October 2012 17:14:55 UTC