- SSLv3/TLSv1 ciphers listed in the original specifications with forward secrecy are all DES (very weak) or 3DES (less weak).
- AES ciphers for TLSv1 were originally specified in RFC 3268 in 2002, and did not make it into XP's SChannel implementation. I believe this is why they aren't present in IE8/XP. If the link is trustworthy, the only ciphers available on IE/XP are RC4 and 3DES, neither of which can be considered excellent choices today.
- IE/XP does not truly offer forward secrecy because it doesn't support RSA modes with DHE, only DSS which has a 1024-bit limit; much of the TLS infrastructure has moved to require 2048-bit keys recently as 1024 is no longer considered adequate.
- TLS specifications require one mandatory cipher, presumably to ensure minimum interoperability. In TLSv1.2 (RFC 5246, published in 2008), that cipher is AES128-SHA. Earlier versions including TLSv1 and TLSv1.1 listed 3DES-SHA.
- Camellia cipher suites were defined in RFC 4132 in 2005. That RFC has been superseded by RFC 5932 in 2010; the latter uses the SHA-2 hash family instead of SHA-1.
- Camellia itself is expected to be of similar security to AES; current attacks on AES are better, but it's likely that AES is more widely studied.
- SHA-2 hash family MACs were introduced in TLS v1.2. It is believed that the older MD5/SHA-1 functions are still secure as used in TLS. To the best of my knowledge, SHA-2 suites are only available when using TLSv1.2.
- ECDHE suites are defined RFC 4492, from 2006; including a ClientHello extension to indicate support.
- ECDHE is not required (though it is listed) in TLSv1.2, nor is usage of TLSv1.2 a requirement for using ECDHE. Recent versions of Firefox support ECDHE suites in conjunction with TLSv1. Older versions—Firefox 21/Fedora 19 for instance—do not.
- Some browsers prefer alleged key length over other considerations, and prioritize 3DES with its "168" bit key over AES128. It's actually designated by NIST as providing 80 bits of security, though it could be providing up to 112 bits.
- The default cipher policy provided by AWS Elastic Load Balancers enables only SSLv3/TLSv1 and an extremely limited set of ciphers: AES128 and 256, 3DES, and RC4, with no forward secrecy suites. (Suites are configurable in the AWS Console, but not cipher preference order, nor some renegotiation options. Renegotiation settings are implicit in the choice of supporting, or not, the more-recent TLS versions.)
Friday, October 18, 2013
TLS Cipher Suites in 2013
Saturday, October 5, 2013
The Lavabit Problem: the Universal TLS Key
Lavabit refused to hand over the key to the whole kingdom for the U.S. Government to ostensibly capture the traffic of one user. The judge ruled in the prosecution's favor in the resulting court case:
Judge Claude Hilton said that it was effectively Levison's fault that sites have only a single private SSL key.Ars doesn't evaluate the truth of that, but technically, it could be accurate. The Perfect Forward Secrecy modes of TLS—DHE and ECDHE—effectively generate a key per connection, authenticating the parameters used to create it with the server's certificate (which is in turn authenticated by the CA system.) However, if Lavabit's servers were set up to allow RSA-only modes, then that configuration introduces the weakness. Under RSA, the server's private key becomes the master private key, capable of decrypting any connection traffic in those modes, because that private key is used to encrypt all the traffic.
Saturday, September 14, 2013
Go Slices and the Hash API
I finished my first little program in Go months ago. One of the mysteries was "Why does Hash.Sum take a byte slice if it doesn't write into it?"
Well, the question is broken. Let's look at some code that attempts to hash a file's content and save the result into a file-info structure, but which doesn't actually work:
Since
What works?
Second, if we don't want
Now that we have some working code, let's reflect on the point of passing in a slice to Hash.Sum in the first place. The goal is to avoid allocating inside Sum, if the caller has space for it. But Sum already allocates and copies a slice: it needs to finalize the hash for Sum, without disturbing the original state so that writers can still add data. By working in a temporary buffer on the stack and copying at the end, it doesn't make a discrete allocation on the heap, but it still needs to ask append to copy it.
Why not begin
Well, the question is broken. Let's look at some code that attempts to hash a file's content and save the result into a file-info structure, but which doesn't actually work:
sumbuf := make([]byte, hsh.Size())What happens? This allocates a byte slice with both
hsh.Sum(sumbuf)
fi.hash = sumbuf
len and cap equal to the output size of the underlying hash, filled with 0x00 bytes. It then passes into hsh.Sum (which, in this particular case, was crypto/sha512) which copies the internal state, finalizes the hash, then wraps everything up with return append(in, digest[:size]...).Since
sumbuf didn't have any room (make(T, n) is equivalent to make(T, n, n)) the append didn't have anywhere to put it. So it did what it had to do, allocating a new backing array of sufficient size, then copying both in (aka sumbuf) and the elements from the digest slice into it. The expanded slice backed by this new array then gets returned... only to be discarded by me. fi.hash ends up being the slice I allocated containing all zero, which made the program think all files were duplicates. Oops!What works?
sumbuf := make([]byte, 0, hsh.Size())First, the return value must be assigned: the original slice's backing array is shared, but append creates a new slice with a larger length to hold the data.
fi.hash = hsh.Sum(sumbuf)
fmt.Printf's %p will show that fi.hash and sumbuf live at the same address, and they have the same capacity as well, but the len of each differs.Second, if we don't want
append to allocate a fresh array, we need a slice with enough free space after its length to hold the data it wants to copy there. A slice with nothing in it (yet) and the capacity of the hash length is precisely the smallest thing to fit this description.Now that we have some working code, let's reflect on the point of passing in a slice to Hash.Sum in the first place. The goal is to avoid allocating inside Sum, if the caller has space for it. But Sum already allocates and copies a slice: it needs to finalize the hash for Sum, without disturbing the original state so that writers can still add data. By working in a temporary buffer on the stack and copying at the end, it doesn't make a discrete allocation on the heap, but it still needs to ask append to copy it.
Why not begin
d := append(in, _____) and then work inside the caller's buffer directly? My guess is that working in a private buffer prevents Sum from leaving partial state visible to the rest of the program. I don't know if it is, but I would not be surprised if append is atomic from the point of view of running goroutines, and clearly Sum needs to allocate in order to be re-entrant.
Tuesday, September 10, 2013
The Forgotten Gem: LDAP
I keep wanting a "configuration lookup service" with the following properties:
- Optimized for a read-heavy workload (config stays the same for months).
- Hierarchical structure (by data center, by server group, by specific host if necessary).
- Queryable at any level.
Saturday, September 7, 2013
Pen and Paper
One of the surprises I had when I wrote some golang code was that static typing was a real bear to wrestle with again. Once I had the type errors sorted out, though, programs ran fairly well. By the time I could get it past the compiler, I had been forced to think about it deeply enough that there were far fewer bugs in the final result.
Of course, it's not magic. My code has still deadlocked.
The mindset that Go enforces, by virtue of checking the types, has led me to try being more careful in my regular work. I now try to make notes on everything that I need to come back to as I'm exploring a problem (such as: "what code interacts with this variable?") so that I can check my plan against all relevant cases. Likewise, a multi-step change will end up with a few bullet points like...
For complex issues and solutions, doing the design on paper has an extra benefit. Paper encourages brevity. There's only so much room within the confines of a page, and it takes a while to write. Consequently, pseudo code tends to stay pseudo code, at an appropriate level of abstraction, when writing out steps. It's the exact opposite of the temptation to switch to writing the real code when trying to write pseudo code in a text editor. It looks like a convenient shortcut to combine the two coding steps, but then the faults in the overall plan don't get noticed until (often) most of the way through—then a random amount of already-written code is made irrelevant or wrong.
Modifying half-implemented approach A to become approach B (hopefully not with the same last-lap change of course) adds a lot of mental state to juggle. Now there are four states complected: original code, usable code from A, unusable but not yet changed code from A, and code from B. It can be quite useful, and a bit simpler, to work out some of those false starts in advance, on paper. Then there's both a record of where my thoughts have been, and a clean body of current code to implement the final result.
As useful as paper can be, there are also times when it's at a disadvantage. For picking apart tricky, complex control flow with nested ifs, repeated conditionals, and the like, I find it easiest to copy the code into a new window and then start deleting lines and replacing them with pseudo-code comments. Often, hundreds of lines can be reduced to a single window, which makes it trivial to get a higher-level overview of what's being accomplished.
Paper's other major disadvantage is that it lacks undo. I've learned by the number of cross-outs on the page just how frequently I rename things as I get a better sense of the problem and what those parts represent in the whole. (I have even been known to choose a name, cross it out in favor of an alternate, then cross out the alternate to restore the original.)
Overall, though, for the appropriate tasks, it's been a great advantage these past few months to put more effort into paper and less into backtracking in vim.
Of course, it's not magic. My code has still deadlocked.
The mindset that Go enforces, by virtue of checking the types, has led me to try being more careful in my regular work. I now try to make notes on everything that I need to come back to as I'm exploring a problem (such as: "what code interacts with this variable?") so that I can check my plan against all relevant cases. Likewise, a multi-step change will end up with a few bullet points like...
EmailBounce (#3351)This also helps in event of interruptions, such as realizing the office manager's radio is playing the same annoying pop songs again today, for the 110th day in a row. There's a list of stuff to help re-establish concentration, knowing I'm not forgetting anything.
- set in SES bounce processor
- clear when email changes
- react in notifier code
For complex issues and solutions, doing the design on paper has an extra benefit. Paper encourages brevity. There's only so much room within the confines of a page, and it takes a while to write. Consequently, pseudo code tends to stay pseudo code, at an appropriate level of abstraction, when writing out steps. It's the exact opposite of the temptation to switch to writing the real code when trying to write pseudo code in a text editor. It looks like a convenient shortcut to combine the two coding steps, but then the faults in the overall plan don't get noticed until (often) most of the way through—then a random amount of already-written code is made irrelevant or wrong.
Modifying half-implemented approach A to become approach B (hopefully not with the same last-lap change of course) adds a lot of mental state to juggle. Now there are four states complected: original code, usable code from A, unusable but not yet changed code from A, and code from B. It can be quite useful, and a bit simpler, to work out some of those false starts in advance, on paper. Then there's both a record of where my thoughts have been, and a clean body of current code to implement the final result.
As useful as paper can be, there are also times when it's at a disadvantage. For picking apart tricky, complex control flow with nested ifs, repeated conditionals, and the like, I find it easiest to copy the code into a new window and then start deleting lines and replacing them with pseudo-code comments. Often, hundreds of lines can be reduced to a single window, which makes it trivial to get a higher-level overview of what's being accomplished.
Paper's other major disadvantage is that it lacks undo. I've learned by the number of cross-outs on the page just how frequently I rename things as I get a better sense of the problem and what those parts represent in the whole. (I have even been known to choose a name, cross it out in favor of an alternate, then cross out the alternate to restore the original.)
Overall, though, for the appropriate tasks, it's been a great advantage these past few months to put more effort into paper and less into backtracking in vim.
Thursday, September 5, 2013
Moose Alternatives
Wednesday, September 4, 2013
More FastCGI: Apache 2.4, PHP-FPM, PSGI, and hot deployment
Driven by mod_fcgid's failings at graceful restart and preforking, I've been looking hard for alternatives.
php-fpm ships with an init script and reloads gracefully via SIGUSR2, so that's all you really need there.
For Perl, gracefully restarting an FCGI app is difficult, so the better approach for PSGI apps is to run them in an HTTP server with Server::Starter support (e.g. Starman or others).
tl;dr
External FCGI is best done via mod_fastcgi on Apache prior to 2.4, or mod_proxy_fcgi on 2.4. mod_proxy in general is super awesome on 2.4.php-fpm ships with an init script and reloads gracefully via SIGUSR2, so that's all you really need there.
For Perl, gracefully restarting an FCGI app is difficult, so the better approach for PSGI apps is to run them in an HTTP server with Server::Starter support (e.g. Starman or others).
Subscribe to:
Posts (Atom)