[Dovecot] CRAM-MD5 Password Generation Algorithm

Bill Cole dovecot-20061108 at billmail.scconsult.com
Sat Apr 12 21:23:58 EEST 2008

At 2:07 PM +0100 4/12/08, Douglas Willcocks  imposed structure on a 
stream of electrons, yielding:
>On Sat, 12 Apr 2008 07:52:01 +0200, Patrick Ben Koetter
><p at state-of-mind.de> wrote:
>>  CRAM-MD5 passwords are passwords saved in plaintext format on the client
>>  and
>>  (!) on the server. Here's why:
>That's what I first thought.

It's not technically a plaintext format or an obvious encoding, but 
if I'm reading the Dovecot code correctly, it is some form of the 
intermediate "contexts" derived from the password as part of the 
HMAC-MD5 algorithm.

It is not clear to me whether one could actually reverse that 
derivation. It seems to me that it should be simple, but no one seems 
to say that explicitly about the practice of storing the 
pre-calculated contexts rather than the actual password, so maybe I'm 
missing something. It may be that actual implementations always use 
the MD5 of the actual password as the key the context calculation, 
rather than using the password itself. That would make the contexts 
16 bytes each plus padding, which would explain the Dovecot 
'CRAM-MD5' storage format.

What IS clear is that with the HMAC-MD5 contexts one can authenticate 
as the user using CRAM-MD5, and that CRAM-MD5 requires the server to 
store either a recoverable plaintext password or the HMAC-MD5 
contexts derived from it.


>Perhaps this not an irreversible hash, but more something like (althought
>it's not) base64? The thing is, it _looks_ like a hash.

I'm pretty sure that it is a pair of 16-byte values derived from the 
password, represented in hexadecimal and concatenated.

>For example, using dovecotpw I can generate the hashed (??) version of
>'password', which is
>I can then place that in the database and the authentication is successful.
>What's more, according to
>You only need to store the password in plaintext if you are using _both_
>To quote:
>"The problem with non-plaintext auth mechanisms is that the password must
>be stored either in plaintext, or using a mechanism-specific scheme that's
>incompatible with all other non-plaintext mechanisms. For example if you're
>going to use CRAM-MD5 authentication, the password needs to be stored in
>either PLAIN or CRAM-MD5 scheme. If you want to allow both CRAM-MD5 and
>DIGEST-MD5, the password must be stored in plaintext."

It may be illuminating to look at 
http://tools.ietf.org/html/draft-ietf-sasl-crammd5-09 and pay 
particular attention to Section 5.

>>>  To generate the passwords to go into the database I can use the
>>  dovecotpw
>>>  utility, but I'm wanting to stick some sort of minimal admin interface
>>  on
>>>  the server to be able to manage the users etc without having to use the
>>>  CLI.
>>  Use pwgen.
>The problem (as stated above) is not how to generate passwords, there are
>thousands of libraries that can do that relatively well.

What exactly is wrong with using dovecotpw?

Are you unaware of the existence of system() and backtick operators 
in your preferred languages, or of the ability to write a CGI in 

Most generic 'best practice' advice for writing web-based tools tries 
to discourage any mechanism that feeds commands to a shell, but it is 
important to understand why that is and when the generic advice 
should be set aside. No Bourne/POSIX or csh-based shell is 
particularly fast, and system() or `` calls launching a shell to run 
a command line from another language has a fork cost, so using either 
approach for performance-sensitive apps is a bad idea on that basis 
alone. In regards to security, there has been a long ugly history of 
sloppy coders being exposed by their failure to diligently validate 
user input before feeding it to a shell. That problem has been 
addressed to some degree by delusional misfeatures like PHP's 'safe' 
mode, which encourages the coder and the admin to collaborate in 
insecurity under the misimpression of being safe. If you are 
disciplined about how you use what the user tells you, there's 
nothing inherently unsafe in passing it through a shell or even 
writing a simple web app entirely in shell.

Bill Cole
bill at scconsult.com

More information about the dovecot mailing list