$\begingroup$

Although there are already many answers here, I wanted to strongly advocate AGAINST MAC-then-encrypt. I fully agree with Thomas' first half of the answer, but completely disagree with the second half. The ciphertext is the ENTIRE ciphertext (including IV etc.), and this is what must be MACed. This is granted.

However, if you MAC-then-encrypt in the straightforward way, then you are completely vulnerable to padding-oracle attacks. by the "straightforward way", what I mean is that you call the "decrypt" function, and afterwards the "mac verify". However, if you get an error in the decrypt function, then you return this straight away, as a padding error. You have now just got a full blown padding oracle attack and you are dead. You can now hack the API and give a single error message only, but the time it takes to return the error has to be the same, whether it's a MAC error or a padding error. If you think that this is easy, then look at the Lucky13 attack on SSL. It's really really really hard (and much harder than just MACing all of the ciphertext).

The argument by Schneier and Ferguson for MAC-then-encrypt has no formal basis at all. The definition of authenticated-encryption is met by encrypt-then-MAC and is NOT met by MAC-then-encrypt. Furthermore, most implementations of MAC-then-encrypt are actually completely vulnerable to padding oracle attacks and so are actually broken in practice. Don't do this!

Having said all of the above, my recommendation is to not use any of this. You should be using GCM or CCM today (GCM is much faster, so use it as long as you are sure that your IV won't repeat). A combined authenticated-encryption scheme, with a single API call, and now you won't get in trouble.