[Esapi-user] ESAPI 2.0 crypt backward compatibility w/ ESAPI 1.4 crypto

Kevin W. Wall kevin.w.wall at gmail.com
Sun Jan 31 17:55:21 EST 2010

ESAPI 1.4 Users,

First, sorry about the length of this post. If you are not using ESAPI 1.4's
encryption, you probably can skip this. The rest of you, as well as ESAPI
developers, should probably read on.

Originally, when I first started working on ESAPI (2.0rc2, I think), someone had
already changed Encryptor.EncryptionAlgorithm from "PBEWithMD5AndDES" to "AES".
So my assumption was that "AES" was the default for 1.4 since I had never seen
anything else.

Then, during the recent discussions of several blog posts discussing ESAPI 1.4,
I found out that 1.4 was originally set to "PBEWithMD5AndDES". So I changed the
ESAPI.properties file to use "PBEWithMD5AndDES" for the property
"Encryptor.EncryptionAlgorithm". (Previously, I had it set to "AES".)

The problem is that from 1.4 to 2.0 we went from the property "MasterPassword"
to "Encryptor.MasterKey". Looking at the 1.4.3 source (sorry! I've not upgraded
to 1.4.4 yet!), I see nowhere that "MasterPassword" is generated, so I am
guessing that it simply was sent by manually editing ESAPI.properties to set it
to a password or pass phrase. (Indeed, it is treated as a char[] when it is
read.) OTOH, "Encryptor.MasterKey" is created using a SHA1 PRNG and then base64
encoded.  These two are also *used* quite differently. "MasterPassword" is
actually _used_ like this to generate a SecretKey for "PBEWithMD5AndDES":

byte[] salt = ESAPI.securityConfiguration().getMasterSalt(); // MasterSalt
char[] pass = ESAPI.securityConfiguration().getMasterPassword(); // MasterPassword
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 20);
SecretKeyFactory kf = SecretKeyFactory.getInstance(encryptAlgorithm);
SecretKey secretKey = kf.generateSecret(new javax.crypto.spec.PBEKeySpec(pass));

whereas "Encryptor.MasterKey" is used to create a SecretKey like this:

KeyGenerator kgen = KeyGenerator.getInstance( cipherAlg );
SecretKey secretKey = kgen.generateKey();

where cipherAlg is taken from either "Encryptor.CipherTransformation" or
"Encryptor.EncryptionAlgorithm", as appropriate.

I realized this dilemma when I was testing and decided to change from
to see if I could make the ESAPI 2.0 crypto *completely* backward compatible
with that of 1.4 when ESAPI.properties was configured to use

When I tried it, I got an exception when it tried to generate the secret key,
because in fact, they are not generated the same. As you might surmise, the root
cause is a NoSuchProviderException when trying to generate a key.

Now, I _could_ do some extra work and make this work so it is backward
compatible with ESAPI 1.4 when using the default PBEWithMD5AndDES and
LegacyJavaEncryptor for ESAPI.Encryptor. (It already is if you were using
"AES" with ESAPI 1.4 in this manner.)  But if I do, should I simply treat
"Encryptor.MasterKey" as the password / pass phrase for the PBEWithMD5AndDES
algorithm or should we add back another property, such as
"Encryptor.MasterPassword" for this?? (The latter of course requires changes to
SecurityConfiguration and DefaultSecurityConfiguration classes and more changes
to LegacyJavaEncryptor. What was in LegacyJavaEncryptor was really based on what
was in ESAPI 2.0rc2, not ESAPI 1.4. and its key generation is not compatible
with 1.4 and/or PBEWithMD5AndDES algorithm.) If we try to reuse the same
"Encryptor.MasterKey" for both the master key and as the master pass phrase for
PBEWithMD5AndDES, then that means that the old and new encryption absolutely
cannot be mixed together. That in turn may mean a longer transition period for
developers who started with ESAPI 1.4 encryption to migrate off those older
deprecated interfaces to use the new ESAPI 2.0 interfaces.

On the other hand, maybe (we can only hope!) that no one in the ESAPI user
community who is using ESAPI 1.4 is also using the symmetric encryption there.
If *no one* is using it or all who are immediately going to switch to ESAPI 2.0
once it is GA'd, then perhaps all this becomes a moot point. If so, we can ditch
ALL the crypto-related backward compatibility issues, simplify
SecurityConfiguration and DefaultSecurityConfiguration, and complete eliminate
the LegacyJavaEncryptor class.

But originally...back in August/Sept, the consensus was that it was important to
maintain backward compatibility and do proper deprecation so as not to
frustrate our ESAPI user community.

So...what is it that all of you--especially your in the ESAPI Users community--
suggest that we do? How much do you want backward compatibility with the
encryption in 1.4 (realizing that it was ,for the most, very badly broken)?
[Note that Jim has already deprecated it as of (at least) 1.4.3.]

Please vote:
A) I don't use crypto in ESAPI 1.4, so what's all the fuss about?
   Blow LegacyJavaEncryptor and all the related code away.
B) I need to have ESAPI 2.0 crypto be backward compatible with
   that in 1.4 despite how badly broken it is. If it is not, it
   probably will prevent me from migrating from 1.4 to ESAPI 2.0.
C) I use ESAPI 1.4 crypto, but am willing to make code changes to use
   ESAPI 2.0 crypto so backward compatibility is not that important
   to me. (I.e., a "nice to have".)

The polls are now open until Feb 2, 4:30pm Eastern/USA (EST).

Kevin W. Wall
"The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents."        -- Nathaniel Borenstein, co-creator of MIME

More information about the Esapi-user mailing list