1616< H1 ALIGN =CENTER > Why Is OWASP Changing ESAPI Encryption?</ H1 >
1717< H2 > Reasons for Change</ H2 >
1818< P STYLE ="margin-bottom: 0in "> The existing ESAPI 1.4 uses the cipher
19- mode Electronic Code Book (ECB) for encryption with < CODE > < FONT SIZE = 2 > Encryptor</ FONT > </ CODE >
20- and the reference implementation, < CODE > < FONT SIZE = 2 > JavaEncryptor</ FONT > </ CODE > .
19+ mode Electronic Code Book (ECB) for encryption with < CODE > Encryptor</ CODE >
20+ and the reference implementation, < CODE > JavaEncryptor</ CODE > .
2121ECB cipher mode is the simplest cipher mode to use, but it is also
2222cryptographically very weak. If more than one block of plaintext is
2323encrypted with the same key, those identical blocks of ciphertext
@@ -89,7 +89,7 @@ <H2>The Encryption Changes in ESAPI Java 2.0</H2>
8989 </ P >
9090 < LI > < P STYLE ="margin-bottom: 0in "> A mechanism to attempt to preserve
9191 backward compatibility with ESAPI Java 1.4 (via
92- < CODE > < FONT SIZE = 2 > org.owasp.esapi.reference.LegacyJavaEncryptor</ FONT > </ CODE > )
92+ < CODE > org.owasp.esapi.reference.LegacyJavaEncryptor</ CODE > )
9393 has been added, but because of the security implications of using
9494 the ECB cipher mode, you are encouraged to stop using this as soon
9595 as possible. (In fact, this backward compatibility mechanism should
@@ -144,9 +144,10 @@ <H3>The Bad</H3>
144144< P > Likewise, the use of padding is going to add some overhead to the
145145length of the ciphertext.
146146</ P >
147- < P STYLE ="margin-bottom: 0in "> For short plaintext of 16-24 bytes,
148- this overhead can be around 30% of the total message size. Here is a
149- table that may help:
147+ < P STYLE ="margin-bottom: 0in "> For example, a short plaintext of 0-15 bytes,
148+ this overhead can be around 200% of the total plaintext size. This
149+ overhead diminishes (as a percent of the total plaintext size) as the
150+ plaintext size increases. Here is a table that illustrates this:
150151</ P >
151152< TABLE WIDTH =348 BORDER =1 CELLPADDING =4 CELLSPACING =0 >
152153 < COL WIDTH =126 >
@@ -166,39 +167,47 @@ <H3>The Bad</H3>
166167 < P ALIGN =LEFT > 0-15</ P >
167168 </ TD >
168169 < TD WIDTH =204 >
169- < P ALIGN =LEFT > 20 </ P >
170+ < P ALIGN =LEFT > 44 </ P >
170171 </ TD >
171172 </ TR >
172173 < TR >
173174 < TD WIDTH =126 >
174175 < P ALIGN =LEFT > 16-31</ P >
175176 </ TD >
176177 < TD WIDTH =204 >
177- < P ALIGN =LEFT > 44 </ P >
178+ < P ALIGN =LEFT > 64 </ P >
178179 </ TD >
179180 </ TR >
180181 < TR >
181182 < TD WIDTH =126 >
182183 < P ALIGN =LEFT > 32-47</ P >
183184 </ TD >
184185 < TD WIDTH =204 >
185- < P ALIGN =LEFT > 64 </ P >
186+ < P ALIGN =LEFT > 88 </ P >
186187 </ TD >
187188 </ TR >
188189 < TR >
189190 < TD WIDTH =126 >
190191 < P ALIGN =LEFT > 48-63</ P >
191192 </ TD >
192193 < TD WIDTH =204 >
193- < P ALIGN =LEFT > 64 </ P >
194+ < P ALIGN =LEFT > 108 </ P >
194195 </ TD >
195196 </ TR >
196197 < TR >
197198 < TD WIDTH =126 >
198- < P ALIGN =LEFT > 48-63 </ P >
199+ < P ALIGN =LEFT > 64-79 </ P >
199200 </ TD >
200201 < TD WIDTH =204 >
201- < P ALIGN =LEFT > 84</ P >
202+ < P ALIGN =LEFT > 128</ P >
203+ </ TD >
204+ </ TR >
205+ < TR >
206+ < TD WIDTH =126 >
207+ < P ALIGN =LEFT > Etc. Each additional 16 bytes of plaintext...</ P >
208+ </ TD >
209+ < TD WIDTH =204 >
210+ < P ALIGN =LEFT > ...adds 20 additional bytes</ P >
202211 </ TD >
203212 </ TR >
204213</ TABLE >
@@ -207,14 +216,20 @@ <H3>The Bad</H3>
207216of the plaintext message increases. The IV is always a fixed length
208217for a given cipher; it is always the same as the cipher block size.
209218The padding can vary, but for PKCS5 padding, the padding will be
210- between 1 to the cipher block size / 8 bytes. Typically, a cipher's
211- block size is 64-bits so the padding would be between 1 to 8 bytes
212- and the IV would be 8 bytes. So the worst case is for 1 byte of
213- input, it would require 8 bytes for the IV, 1 bytes for the actual
214- encrypted raw ciphertext, and 7 bytes for padding for a total of 16
215- bytes, but that's before base64 encoding. (< FONT COLOR ="#ff0000 "> < B > CHECKME</ B > </ FONT > ;
216- seems wrong)
217- </ P >
219+ between 1 to the cipher block size (in bits) / 8 bytes. For AES,
220+ the cipher block size is 128-bits, but more typically, a cipher's
221+ block size is 64-bits so the padding would be between 1 to 16 bytes for
222+ AES and 1 to 8 bytes for a 64-bit block size cipher and the IV would be
223+ IV would be 16 bytes for AES and 8 bytes for most other ciphers.
224+ (Note: If space were truly a concern, say because of legacy database
225+ tables, etc., then one could set the properties
226+ < PRE >
227+ Encryptor.ChooseIVMethod=fixed
228+ Encryptor.fixedIV=<your_hex_encoded_IV_here>
229+ </ PRE >
230+ in < code > ESAPI.properties</ code > and then
231+ store only the raw ciphertext bytes, but this is not quite as
232+ secure as using a random IV for each plaintext that is encrypted.)
218233< H3 > The Ugly</ H3 >
219234< P > Well, so far, this "bad" news may be bad for you but
220235good for your database and/or storage vendor, but you probably can
@@ -229,22 +244,24 @@ <H3>The Ugly</H3>
229244< P > All this backward compatibility and flexibility comes at the
230245additional cost of complexity, and not < I > merely</ I > additional
231246complexity in the reference implementation. There is also some
232- additional complexity in the ESAPI < CODE > < FONT SIZE = 2 > Encryptor</ FONT > </ CODE >
247+ additional complexity in the ESAPI < CODE > Encryptor</ CODE >
233248interfaces as well.
234249</ P >
235- < P > In particular, there is a new < CODE > < FONT SIZE = 2 > CipherText</ FONT > </ CODE >
250+ < P > In particular, there is a new < CODE > CipherText</ CODE >
236251class to coalesce all this complexity of handling the ciphertext
237252result from encryption operations as well as a reference
238- implementation (< CODE > < FONT SIZE = 2 > DefaultCipherText</ FONT > </ CODE > )
253+ implementation (< CODE > DefaultCipherText</ CODE > )
239254for it as well. And then there is one new encryption and one new
240- decryption method for the < CODE > < FONT SIZE = 2 > Encryptor</ FONT > </ CODE >
255+ decryption method for the < CODE > Encryptor</ CODE >
241256interface. Specifically, the encrypt and decrypt methods have been
242257generalized as:
243258</ P >
244- < PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> C< FONT COLOR ="#000000 "> < FONT FACE ="Monospace "> < FONT SIZE =2 > ipherText encrypt(SecretKey key, PlainText plaintext) throws EncryptionException;</ FONT > </ FONT > </ FONT > </ PRE > < P >
259+ < PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> < FONT
260+ COLOR ="#000000 "> < FONT FACE ="Monospace "> CipherText encrypt(SecretKey key, PlainText plaintext) throws EncryptionException;</ FONT > </ FONT > </ PRE > < P >
245261and
246262</ P >
247- < PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> < FONT COLOR ="#000000 "> < FONT FACE ="Monospace "> < FONT SIZE =2 > PlainText decrypt(SecretKey key, CipherText ciphertext) throws EncryptionException</ FONT > </ FONT > </ FONT > </ PRE > < P >
263+ < PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> < FONT
264+ COLOR ="#000000 "> < FONT FACE ="Monospace "> PlainText decrypt(SecretKey key, CipherText ciphertext) throws EncryptionException</ FONT > </ FONT > </ PRE > < P >
248265The two existing interfaces from ESAPI 1.4 and earlier</ P >
249266< PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> String encrypt(String plaintext) throws EncryptionException</ PRE > < P >
250267and
@@ -262,8 +279,8 @@ <H3>The Ugly</H3>
262279to decrypt it using the ESAPI 2.0</ P >
263280< PRE STYLE ="margin-left: 0.49in; margin-bottom: 0.2in "> String decrypt(String ciphertext) throws EncryptionException</ PRE > < P >
264281method. If you require such compatibility, you should set
265- < CODE > < FONT SIZE = 2 > org.owasp.esapi.reference.LegacyJavaEncryptor</ FONT > </ CODE >
266- for the property < CODE > < FONT SIZE = 2 > ESAPI.Encryptor</ FONT > </ CODE > in
282+ < CODE > org.owasp.esapi.reference.LegacyJavaEncryptor</ CODE >
283+ for the property < CODE > ESAPI.Encryptor</ CODE > in
267284your < B > ESAPI.properties</ B > file, this class likely will be removed
268285in a future ESAPI release. (This class is intended only to provide
269286backward compatibility so that you may decrypt previously encrypted
@@ -273,7 +290,7 @@ <H3>The Ugly</H3>
273290ensure authenticity and integrity so the more general encrypt() /
274291decrypt() methods should be preferred over the String-based ones.
275292(See below for examples of how to use these new methods.)</ P >
276- < P > Further details are provided in the < CODE > < FONT SIZE = 2 > Encryptor</ FONT > </ CODE >
293+ < P > Further details are provided in the < CODE > Encryptor</ CODE >
277294Javadoc.</ P >
278295< H2 > Symmetric Encryption in ESAPI 2.0</ H2 >
279296< H3 > ESAPI.properties Properties Relevant to Symmetric Encryption</ H3 >
@@ -299,9 +316,11 @@ <H3>ESAPI.properties Properties Relevant to Symmetric Encryption</H3>
299316 < FONT COLOR ="#ff0000 "> Encryptor.ChooseIVMethod=random</ FONT >
300317
301318 # This is only used when Encryptor.ChooseIVMethod=fixed is set, otherwise a random IV is used.
302- # Should only be used for compatibility with legacy systems. In such cases, you should
303- # set it to whatever fixed IF is required using hexadecimal representation. Note however
304- # use of a random IV is always preferable.
319+ # Should only be used for compatibility with legacy systems when space
320+ # to store the encrypted values is at a premium or your partner in
321+ # encryption requires you to use a specific IV. In such cases, you
322+ # should set it to whatever fixed IV is required using hexadecimal representation.
323+ # Note however use of a random IV is always preferable.
305324 < FONT COLOR ="#ff0000 "> Encryptor.fixedIV=</ FONT > < FONT COLOR ="#0000FF "> 0xdbd1a3636024b7b402da7d6fe3fb056e</ FONT >
306325 < FONT COLOR ="#ff0000 "> Encryptor.CipherText.useMAC=true</ FONT >
307326</ PRE >
@@ -323,13 +342,13 @@ <H3>
323342</ PRE >
324343< P >
325344This code will still work, however if you are using the standard
326- (default) reference for < CODE > < FONT SIZE = 2 > ESAPI.Encryptor</ FONT > </ CODE > ,
327- which is < CODE > < FONT SIZE = 2 > org.owasp.esapi.reference.JavaEncryptor</ FONT > </ CODE > ,
345+ (default) reference for < CODE > ESAPI.Encryptor</ CODE > ,
346+ which is < CODE > org.owasp.esapi.reference.JavaEncryptor</ CODE > ,
328347the cipher transformation used with be that specified by the property
329- < CODE > < FONT SIZE = 2 > Encryptor.CipherTransformation</ FONT > </ CODE > with
348+ < CODE > Encryptor.CipherTransformation</ CODE > with
330349a key size (when the algorithm supports a variable key size) of that
331- specified by < CODE > < FONT SIZE = 2 > Encryptor.EncryptionKeyLength</ FONT > </ CODE >
332- and the IV type specified by < CODE > < FONT SIZE = 2 > Encryptor.ChooseIVMethod</ FONT > </ CODE > .
350+ specified by < CODE > Encryptor.EncryptionKeyLength</ CODE >
351+ and the IV type specified by < CODE > Encryptor.ChooseIVMethod</ CODE > .
333352This is opposed to the old ESAPI 1.4 default of 256-bit AES in ECB
334353mode with no padding (and obviously no IV). If you have no need to
335354decrypt data that was previously encrypted using ESAPI 1.4, this
341360which will cause these two String-based encrypt / decrypt methods to
342361use 256-bit AES with cipher transformation “AES/ECB/None”. Note
343362that the new encryption / decryption methods continue to work as they
344- do as if you were using the < CODE > < FONT SIZE = 2 > JavaEncryptor</ FONT > </ CODE >
363+ do as if you were using the < CODE > JavaEncryptor</ CODE >
345364class. Note that the legacy encryption can < I > only </ I > < SPAN STYLE ="font-style: normal "> use
346365the master encryption key, but that is all that is required for
347366compatibility with ESAPI 1.4.</ SPAN > </ P >
@@ -376,7 +395,7 @@ <H3>Encrypting / Decrypting with the New Methods -- The Simple Usage</H3>
376395</ P >
377396< PRE > byte[] plaintextByteArray = { /* byte array to be encrypted */ };
378397 String plaintext = new String(plaintextByteArray, "UTF-8");</ PRE > < P >
379- all the while catching the required < CODE > < FONT SIZE = 2 > UnsupportedEncodingException</ FONT > </ CODE > .
398+ all the while catching the required < CODE > UnsupportedEncodingException</ CODE > .
380399For example, to handle this in ESAPI 1.4, one would have to write:</ P >
381400< PRE > try {
382401 byte[] plaintextByteArray = { /* byte array to be encrypted */ };
@@ -385,7 +404,7 @@ <H3>Encrypting / Decrypting with the New Methods -- The Simple Usage</H3>
385404 String decrypted = ESAPI.encryptor().decrypt(ciphertext);
386405 byte[] recoveredBytes = decrypted.getBytes(“UFT-8”);
387406 assert java.util.Arrays.equals( plaintextByteArray, recoveredBytes );
388- } catch( < CODE > < FONT SIZE = 2 > UnsupportedEncodingException</ FONT > </ CODE > ex) {
407+ } catch( < CODE > UnsupportedEncodingException</ CODE > ex) {
389408 // Should not happen but need to catch and deal with it anyhow.
390409 // Log error then return error designation however appropriate.
391410 } catch(EncryptionException ex) {
@@ -409,17 +428,17 @@ <H3>Encrypting / Decrypting with the New Methods -- The Simple Usage</H3>
409428encrypted. Instead, you should overwrite them after their value as
410429been used. However, when you are using immutable Strings, this is not
411430possible using native Java methods. But if you are able to pass in
412- byte arrays that are passed directly to < CODE > < FONT SIZE = 2 > PlainText</ FONT > </ CODE >
431+ byte arrays that are passed directly to < CODE > PlainText</ CODE >
413432objects (as shown above), the < I > default</ I > is to overwrite this
414433after they are encrypted. If the default for
415- < CODE > < FONT SIZE = 2 > Encryptor.PlainText.overwrite</ FONT > </ CODE > of
416- < CODE > < FONT SIZE = 2 > < B > true</ B > </ FONT > </ CODE > had been used, then the
417- array < CODE > < FONT SIZE = 2 > plaintextByteArray</ FONT > </ CODE > would have
434+ < CODE > Encryptor.PlainText.overwrite</ CODE > of
435+ < CODE > < B > true</ B > </ CODE > had been used, then the
436+ array < CODE > plaintextByteArray</ CODE > would have
418437been overwritten with ASCII “*” characters.</ P >
419438< H3 > Encrypting / Decrypting with the New Methods -- Advanced Usage</ H3 >
420439< P >
421440ESAPI 1.4 and earlier only allowed you to use the master key
422- </ code > Encryptor.MasterKey</ code > to encrypt and decrypt with.
441+ < code > Encryptor.MasterKey</ code > to encrypt and decrypt with.
423442But encryption with a single key is not always sufficient. For
424443instance, lets say that your application has a need to encrypt both
425444bank account numbers and credit card numbers. The encrypted bank account
@@ -473,7 +492,6 @@ <H3>Encrypting / Decrypting with the New Methods -- Advanced Usage</H3>
473492by our application, perhaps using something like ESAPI's
474493< code > EncryptedProperties</ code > class, where they could later be
475494retrieved and used.
476- </ P >
477495< P >
478496In the following code, we assume that the < code > SecretKey</ code > values
479497have already been initialized elsewhere.
@@ -499,6 +517,5 @@ <H3>Encrypting / Decrypting with the New Methods -- Advanced Usage</H3>
499517 // Log error then return error designation however appropriate.
500518 }
501519</ PRE >
502- </ P >
503520</ BODY >
504521</ HTML >
0 commit comments