File: esapi4java-core-2.0-symmetric-crypto-user-guide.html

package info (click to toggle)
libowasp-esapi-java 2.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 7,480 kB
  • ctags: 4,161
  • sloc: java: 26,333; xml: 1,309; sh: 293; makefile: 4
file content (796 lines) | stat: -rw-r--r-- 38,170 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
	<TITLE>ESAPI 2.0 Symmetric Encryption User Guide</TITLE>
	<META NAME="GENERATOR" CONTENT="OpenOffice.org 3.0  (Linux)">
	<META NAME="CREATED" CONTENT="20100214;0">
	<META NAME="CHANGEDBY" CONTENT="Kevin W. Wall">
	<META NAME="CHANGED" CONTENT="20100304;00400700">
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<TABLE BORDER="0" BORDERCOLOR="#000000" CELLPADDING=4 CELLSPACING=0 STYLE="page-break-before: auto; page-break-after: auto; page-break-inside: auto">
<TR>
<TD>
<OBJECT TYPE="audio/x-mpeg" data="http://www.catonmat.net/download/crypt-o.mp3"
WIDTH="500" HEIGHT="64" AUTOPLAY="false">
    <PARAM NAME="src" VALUE="http://www.catonmat.net/download/crypt-o.mp3" />
    <PARAM NAME="controller" VALUE="true" />
    <PARAM NAME="autoplay" VALUE="false" />
    <PARAM NAME="autostart" VALUE="0" />
</OBJECT>
</TD>
<TD>
<FONT COLOR="#00a444" SIZE="+2">
<I>Crypto song. Take a listen and enjoy! Harry Belafonte never sounded this good. ;-)</I>
</FONT>
</TD>
</TABLE>
<H1 ALIGN=CENTER>ESAPI 2.0 Symmetric Encryption User Guide</H1>
<H2>ESAPI.properties Properties Relevant to Symmetric Encryption</H2>
<P>Those properties that are new since ESAPI 2.0-rc2 are shown in
<FONT COLOR="#ff0000">red</FONT>. Values shown in <FONT COLOR="#0000ff">blue</FONT>
are ones that you would replace.</P>
<TABLE BORDER=1 BORDERCOLOR="#000000" CELLPADDING=4 CELLSPACING=0 STYLE="page-break-before: auto; page-break-after: auto; page-break-inside: auto">
	<COL WIDTH=249>
	<COL WIDTH=202>
	<COL WIDTH=226>
	<TR VALIGN=TOP>
		<TH WIDTH=249>
			<P>Property Name</P>
		</TH>
		<TH WIDTH=202>
			<P>Default Value</P>
		</TH>
		<TH WIDTH=226>
			<P>Comment</P>
		</TH>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT SIZE=2>ESAPI.Encryptor</FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT SIZE=2>org.owasp.esapi.reference.crypto.JavaEncryptor</FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>The class implementing the Encryptor interface and
			returned by ESAPI.encryptor().</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT SIZE=2>Encryptor.MasterKey</FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<P><FONT COLOR="#0000ff"><FONT SIZE=2>&lt;initially unset&gt;</FONT></FONT></P>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>The base64-encoded SecretKey. The key must be
			appropriate to the specified key size and cipher algorithm.</FONT></P>
			<P><FONT SIZE=2>Set as per the instructions in the ESAPI
			Installation Guide.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT SIZE=2>Encryptor.MasterSalt</FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<P><FONT COLOR="#0000ff"><FONT SIZE=2>&lt;initially unset&gt;</FONT></FONT></P>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>A base64-encoded random “salt”. This should be
			at least 20-bytes. It is used to generate a random (but
			consistent) public/private key pair used in asymmetric encryption
			and digital signatures.</FONT></P>
			<P><FONT SIZE=2>Set as per the instructions in the ESAPI
			Installation Guide.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><STRIKE><FONT SIZE=2>Encryptor.EncryptionAlgorithm</FONT></STRIKE></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT SIZE=2>AES</FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>A deprecated property, superseded by
			Encryptor.CipherTransformation.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.CipherTransformation</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>AES/CBC/PKCS5Padding</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Specifies the cipher transformation to use for
			symmetric encryption. The format is
			cipherAlgorithm/cipherMode/paddingScheme.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.EncryptionKeyLength</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>128</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Key size, in bits. Required for cipher algorithms
			that support multiple key sizes.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.ChooseIVMethod</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>random</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Legal values are “random” or “fixed”.
			Random is recommended. Set to “fixed” only if required for
			compatibility with legacy or third party software. If set to
			“fixed”, then the property Encryptor.fixedIV must also be
			set to hex-encoded specific IV that you need to use.
            </FONT></P><P><FONT SIZE=2>
            <B>CAUTION:</B> While it is not required that the IV be kept
            secret, encryption relying on fixed IVs can lead to a known
            plaintext attack called a "Key Collision Attack". While this
            attack is probably not practical (for those with modest
            resources) for ciphers with 128-bit key size, this attack
            makes it possible to capture the ciphertexts from only
            2<sup>(N/2)</sup> known plaintexts to discover the
            encryption key. Loughran and Dowling explain a Java
            implementation of Eli Biham's key collision attack on DES in
            their easy to understand paper,
            <a href="http://homepage.eircom.net/~johnloughran/projects/computer/camDesAttackv4.pdf">
            A Java Implemented Key Collision Attack on the
            Data Encryption Standard (DES)</a>. Since attacks only get
            better and the cost of storage is dropping rapidly, you are
            urged to avoid using "fixed" IVs except when required for
            backward compatibility. In particular, should never use
            fixed IVs just to avoid the storage cost of storing a random
            IV.
            </FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.fixedIV</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#0000ff"><FONT SIZE=2>0x000102030405060708090a0b0c0d0e0f</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>A hex-encoded value to use as a fixed IV. Only
			used if the property Encryptor.fixedIV is set to “fixed”. Intended
            <I>only</I> for compatibility with legacy code. See the above
            related above caution for <code>Encryptor.ChooseIVMethod</code>.
            </FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.CipherText.useMAC</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>true</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Whether or not <code>CipherText</code>
            should use a message authentication code (MAC) with
            it. This prevents an adversary from altering the IV
            as well as allowing a more fool-proof way of
			determining the decryption failed because of an incorrect key
			being supplied. This refers to the &quot;separate&quot; MAC
			calculated and stored in <code>CipherText</code>, not
            part of any MAC that is calculated as a result
            of a &quot;combined mode&quot; cipher mode.</FONT></P>
			<P><FONT SIZE=2>Note: If the cipher mode used is one specified in
			the comma-separated list of cipher modes given in the property
			<b>Encryptor.cipher_modes.combined_modes</b>, then a separate MAC
            is <i>not</i> calculated for <code>CipherText</code> regardless of
            the setting of this property. (Doing so would be
            superfluous.)</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.PreferredJCEProvider</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2><i>&lt;empty string&gt;</i></FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Specifies the <i>preferred</i> JCE provider, that
            is the JCE provider that is first looked at for JCE algorithms.
            The <code>Encryptor</code> reference implementation,
            <code>JavaEncryptor</code>, attempts to
			load this JCE provider at position the first position when the
            <code>JavaEncryptor</code> class is first loaded.
            <br><br>
            The value may either be a provider name (e.g., “BC” for
            Bouncy Castle) or the fully qualified class name implementing
            <code>java.security.Provider</code> for
			the desired JCE provider. If left set to the empty string (the
            default) or unset, the effect is to not change the preferred JCE
            provider so that your application ends up using whatever your Java
            VM is already using, which is generally determined by the settings
            in your <code>$JAVA_HOME/jre/lib/security/java.security</code>
            file.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.cipher_modes.additional_allowed</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>CBC</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Additional cipher modes allowed for ESAPI 2.0
			symmetric encryption. These cipher modes are in <I>addition</I> to
			those specified by the property
			<b>Encryptor.cipher_modes.combined_modes</b>.</FONT></P>
			<P><FONT SIZE=2>Note: We will add support for streaming modes like
			CFB &amp; OFB once we add support for 'specified' to the property
			<b>Encryptor.ChooseIVMethod</b> (probably in ESAPI 2.1).</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.cipher_modes.combined_modes</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>GCM,CCM,IAPM,EAX,OCB,CWC</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Comma-separated list of cipher modes that provide
			<B><I>both</I></B> confidentiality <B><I>and</I></B>
            message authenticity. (NIST refers to such cipher
            modes as &quot;combined modes&quot; so that's what we
			shall call them.) If any of these cipher modes are used then no
			MAC is calculated and stored in the <code>CipherText</code>
            upon encryption.  Likewise, if one of these cipher
            modes is used with decryption, no attempt will be
            made to validate the MAC contained in the <code>CipherText</code>
            object regardless of whether it contains one or not.
			Since the expectation is that these cipher modes support support
			message authenticity already, injecting a MAC in the
            <code>CipherText</code> object would be at best redundant.</FONT>
			</P>
			<P><FONT SIZE=2>Note that as of JDK 1.5, the SunJCE provider does
			not support <I>any</I> of these cipher modes. Of these listed,
			only GCM and CCM are currently NIST approved.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.PlainText.overwrite</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>TRUE</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>Whether or not the plaintext bytes for the
			PlainText object may be overwritten with “*” characters and
			then marked eligible for garbage collection. If not set, this is
			still treated as 'true'. If this is set to 'true', you will not be
			able to use any PlainText object after you have used it with one
			of the Encryptor encrypt() methods.</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>Encryptor.KDF.PDF</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#ff0000"><FONT SIZE=2>HmacSHA256</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>
            This is the Pseudo Random Function (PRF) that ESAPI's Key
            Derivation Function (KDF) normally uses. NSA wanted us to
            support something stronger than HmacSHA1 (even though that
            is considered fine for now--unless perhaps you are guarding
            nuclear launch codes--and if so, your Java license probably
            prohibits that ;-).
			<BR /><BR />
            (Note this is *only* the PRF used for ESAPI's KDF and *not*
            what is used for ESAPI's MAC. Currently, HMacSHA1 is always
            used for the MAC.)
			<BR /><BR />
            Currently supported choices for JDK 1.5 and 1.6 are:
            HMacSHA1 (160 bits), HMacSHA256 (256 bits), HMacSHA384
            (384 bits), and HMacSHA512 (512 bits).
			<BR /><BR />
            Note that HMacMD5 is *not* supported for the PRF
            used by the KDF even though these JDKs support it.
            ESAPI 2.0 release candidates prior to 2.0_rc11
            ALWAYS used HMacSHA1. It is somewhat faster than
            the SHA2 HMAC variations, but not significantly so.
            <BR /><BR />
            The only legitimate reason to tweak this would be to change it to
            one of the new HMACs based on the future SHA-3 winner once it is
            announced by NIST and supported in ESAPI and most JDKs. Until then,
            don't meddle.
			</FONT></P>
		</TD>
	</TR>
	<TR VALIGN=TOP>
		<TD WIDTH=249>
			<PRE><FONT COLOR="#000000"><FONT SIZE=2>Encryptor.CharacterEncoding</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=202>
			<PRE><FONT COLOR="#000000"><FONT SIZE=2>UTF-8</FONT></FONT></PRE>
		</TD>
		<TD WIDTH=226>
			<P><FONT SIZE=2>The default encoding used for certain aspects such
			as signing and sealing.</FONT></P>
		</TD>
	</TR>
</TABLE>
<H2>How the Old (Deprecated) Methods Were Used</H2>
<P>To encrypt / decrypt using the String-based, deprecated methods
carried over from ESAPI 1.4, code similar to the following would be
used. 
</P>
<PRE>    String myplaintext = &quot;My plaintext&quot;;
    try {
        String ciphertext = ESAPI.encryptor().encrypt(myplaintext);
        String decrypted  = ESAPI.encryptor().decrypt(ciphertext);
        assert decrypted.equals(myplaintext);
    } catch(EncryptionException ex) {
        // Log error then return error designation however appropriate
    }</PRE><P>
This code will still work, however if you are using the standard
(default) reference for <CODE>ESAPI.Encryptor</CODE>, which is
<CODE>org.owasp.esapi.reference.crypto.JavaEncryptor</CODE>, the
cipher transformation used with be that specified by the property
<b>Encryptor.CipherTransformation</b> with a key size (when the
algorithm supports a variable key size) of that specified by
<b>Encryptor.EncryptionKeyLength</b> and the IV type specified
by <b>Encryptor.ChooseIVMethod</b>. What is not provided by
these methods (and why they are deprecated) is that they provide no
mechanism to ensure message authenticity unless they are used with a
so-called “combined” cipher mode such as CCM or GCM. <SPAN STYLE="font-style: normal">(Note
that as of JDK 1.6, the default JCE provider, “SunJCE”, does not
support any combined cipher modes.)</SPAN></P>
<H2>Requirements for using ESAPI Symmetric Encryption</H2>
<P>
The parties participating in using ESAPI's symmetric encryption
capabilities must agree on the following:
<ol>
<li>
All parties must share the same encryption key(s). If multiple keys are
used, each party must know which key to use for encryption / decryption.
Parties must ensure that exchanging, storing, and all management
of these encryption keys is done securely.  How this is done is
presently outside the scope of ESAPI encryptions, but developers may
find the advice in
<a href="http://www.owasp.org/index.php/Cryptographic_Storage_Cheat_Sheet">
OWASP's Cryptographic Storage Cheat Sheet</a> helpful in this regard.
</li>
<li>
If parties are only exchanging raw ciphertext (plus IV, when appropriate),
then they must also agree on the cipher transformation to use.
</li>
<li>
If the involved parties participating in encryption are <i>not</i> using a
"combined" cipher mode that provides both confidentiality and authenticity
(for example, something like GCM or CCM), then they <i>must</i> whether or
not there will be an additional MAC sent allow with the raw ciphertext and
other cipher spec information in order to provide evidence of authenticity /
data integrity. (See the property <b>Encryptor.CipherText.useMAC</b>
for further details.) Failure to agree on this may allow an adversary to
carry out certain chosen ciphertext attacks against their encrypted data
resulting in (possibly complete) leakage of the corresponding plaintext.
</li>
</ol>
<H2>Encrypting / Decrypting with the New Methods -- The Simple Usage</H2>
<P>Using the new encryption / decryption methods is somewhat more
complicated, but this is in part because they are more flexible and
that flexibility means that more information needs to be communicated
as to the details of the encryption. 
</P>
<P>A code snippet using the new methods that use the master
encryption key would look something like this: 
</P>
<PRE>    String myplaintext = &quot;My plaintext&quot;;
    try {
        CipherText ciphertext =
            ESAPI.encryptor().encrypt( new PlainText(myplaintext) );
        PlainText recoveredPlaintext = ESAPI.encryptor().decrypt(ciphertext) );
        assert myplaintext.equals( recoveredPlaintext.toString() );
    } catch(EncryptionException ex) {
        // Log error then return error designation however appropriate.
    }</PRE><P>
Yes, this is a bit more complicated, but it will 1) work across
different hardware platforms and operating systems whereas the older
methods may not, and 2) it provides for <I>authenticity</I> <I><B>and</B></I>
<I>confidentiality</I> of the ciphertext regardless of which cipher
mode is chosen.</P>
<P>Also, these new methods allow a general byte array to be
encrypted, not just a Java String. If one needed to encrypt a byte
array with the old deprecated method, one would first have to use 
</P>
<PRE>    byte[] plaintextByteArray = { /* byte array to be encrypted */ };
    String plaintext = new String(plaintextByteArray, &quot;UTF-8&quot;);</PRE><P>
all the while catching the required <CODE>UnsupportedEncodingException</CODE>.
For example, to handle this in ESAPI 1.4, one would have to write
something like:</P>
<PRE>
    try {
        byte[] plaintextByteArray = { /* byte array to be encrypted */ };
        String myplaintext = new String(plaintextByteArray, &quot;UTF-8&quot;);
        String ciphertext = ESAPI.encryptor().encrypt(myplaintext);
        String decrypted  = ESAPI.encryptor().decrypt(ciphertext);
        byte[] recoveredBytes = decrypted.getBytes(“UFT-8”);
        assert java.util.Arrays.equals( plaintextByteArray, recoveredBytes );
    } catch( UnsupportedEncodingException ex) {
        // Should not happen but need to catch and deal with it anyhow.
        // Log error then return error designation however appropriate.
    } catch(EncryptionException ex) {
        // Log error then return error designation however appropriate.
    }
</PRE><P>
However, dealing with this in ESAPI 2.0 is not any more cumbersome
than dealing with Strings:</P>
<PRE>
    try {
        byte[] plaintextByteArray = { /* byte array to be encrypted */ };
        CipherText ciphertext =
            ESAPI.encryptor().encrypt( new PlainText(plaintextByteArray) );
        PlainText recoveredPlaintext = ESAPI.encryptor().decrypt(ciphertext) );

        assert java.util.Arrays.equals( plaintextByteArray,
                                        recoveredPlaintext.asBytes() );
    } catch(EncryptionException ex) {
        // Log error then return error designation however appropriate.
    }
</PRE><P>
Ideally when you are encrypting sensitive data you do not want the
plaintext sensitive data to be left lying around after it is
encrypted. Instead, you should overwrite them after their value as
been used. However, when you are using immutable Strings, this is not
possible using native Java methods. But if you are able to pass in
byte arrays that are passed directly to <CODE>PlainText</CODE>
objects (as shown above), the <I>default</I> is to overwrite this
after they are encrypted.
<!-- Need to verify this. It was like this, but think I may have changed
it to return a copy rather than a reference based on FindBugs report. -->
<SPAN STYLE="background: #ffff00">(Note: Verify!) If the default for
</SPAN><CODE><SPAN STYLE="background: #ffff00">Encryptor.PlainText.overwrite</SPAN></CODE><SPAN STYLE="background: #ffff00">
of </SPAN><CODE><B><SPAN STYLE="background: #ffff00">true</SPAN></B></CODE><SPAN STYLE="background: #ffff00">
had been used, then the array </SPAN><CODE><SPAN STYLE="background: #ffff00">plaintextByteArray</SPAN></CODE><SPAN STYLE="background: #ffff00">
would have been overwritten with ASCII “*” characters.</SPAN></P>
<H2>Encrypting / Decrypting with the New Methods – Storing Encrypted Data</H2>
<P><SPAN STYLE="background: transparent">If you use one of the new
Encryptor encrypt() / decrypt() methods, how do you persist the
<code>CipherText</code> object returned by the encrypt() methods and how do
you restore it to pass to the decrypt() method?</SPAN></P>
<P><SPAN STYLE="background: transparent">The following example code
snippet will illustrate this. In the following example we will simply
write out the serialized <code>CipherText</code> object to a local file, but
obviously you could hex- or base64-encode the serialized byte array
and store it in a database or sent it in a SOAP XML message to a web
service, etc.</SPAN></P>
<PRE>    public class PersistedEncryptedData
    {
        public static int persistEncryptedData(PlainText plaintext,
                                                String filename)
            throws EncryptionException, IOException
        {
            File serializedFile = new File(filename);
            serializedFile.delete(); // Delete any old serialized file.

            CipherText ct = ESAPI.encryptor().encrypt(plaintext);
            byte[] serializedCiphertext = ct.asPortableSerializedByteArray();

            FileOutputStream fos = new FileOutputStream(serializedFile);
            fos.write(serializedCiphertext);
            fos.close();
            return serializedCiphertext.length;
        }

        public static PlainText restorePlaintext(String encryptedDataFilename)
            throws EncryptionException, IOException
        {
            File serializedFile = new File(encryptedDataFilename);
            FileInputStream fis = new FileInputStream(serializedFile);
            int avail = fis.available();
            byte[] bytes = new byte[avail];
            fis.read(bytes, 0, avail);

            CipherText restoredCipherText =
                                CipherText.fromPortableSerializedBytes(bytes);
            fis.close();
            PlainText plaintext = ESAPI.encryptor().decrypt(restoredCipherText);
            return plaintext;
        }
    }
  </PRE>
<H2>Advanced Usage</H2>
<H3>Encrypting / Decrypting with the New Methods</H3>
<P>ESAPI 1.4 and earlier only allowed you to use the master key
(<FONT FACE="DejaVu Sans Mono, sans-serif">MasterPassword</FONT> in
ESAPI 1.4; <CODE>Encryptor.MasterKey</CODE> in ESAPI 2.0) to encrypt
and decrypt with. But encryption with a single key seldom is
sufficient. For instance, lets say that your application has a need
to encrypt both bank account numbers and credit card numbers. The
encrypted bank account numbers are to be sent to one recipient and
the encrypted credit card numbers are to be sent to a different
recipient. Obviously in such cases, you do not want to share the same
key for both recipients. 
</P>
<P>In ESAPI 1.4 there was not much you can do, but in ESAPI 2.0 and
later, there are new encryption / decryption methods that allow you
to specify a specific <CODE>SecretKey</CODE>. There is also a static
helper method in <CODE>CryptoHelper</CODE> to allow you to generate a
<CODE>SecretKey</CODE> of a specific type. (Distribution of this key
is out of scope for this particular example, but for the moment, we
will assume that secret keys are first generated, and then
distributed to the recipients out-of-band. On you could distribute
them dynamically via asymmetric encryption assuming that you've
previously exchanged public keys with the recipients.)</P>
<P>The following illustrates how these new methods might be used. 
</P>
<P>First, we would generate some appropriate secret keys and
distribute them securely (e.g., perhaps over SSL/TLS) or exchange
them earlier out-of-band to the intended recipients. (E.g., one could
put them on two separate thumb drives and use a trusted courier to
distribute them to the recipients or one could use PGP-mail or S/MIME
to securely email them, etc.) 
</P>
<PRE>    // Generate two random, 128-bit AES keys to be distributed out-of-band.
    import javax.crypto.SecretKey;
    import org.owasp.esapi.crypto.CryptoHelper;
    import org.owasp.esapi.codecs.Hex;

    public class MySecretKeys {
        public void main(String[] args) {
          try {
            SecretKey bankAcctKey = CryptoHelper.generateSecretKey(&quot;AES&quot;, 128);
            SecretKey credCardKey = CryptoHelper.generateSecretKey(&quot;AES&quot;, 128);

            System.out.println(&quot;Bank account key: &quot; +
                Hex.encode( bankAcctKey.getEncoding(), true ) );
            System.out.println(&quot;Credit card key: &quot; +
                Hex.encode( credCardKey.getEncoding(), true ) );
          } catch(Exception ex) {
            ex.printStackTrace(System.err);
            System.exit(1);
          }
          System.exit(0);
        }
    }</PRE><P>
Second, these keys would be printed out and stored somewhere secure
by our application, perhaps using something like ESAPI's
<CODE>EncryptedProperties</CODE> class, where they could later be
retrieved and used. 
</P>
<P>In the following code, we assume that the <CODE>SecretKey</CODE>
values have already been initialized elsewhere. 
</P>
<PRE>    SecretKey bankAcctKey = ...;        // These might be read from EncryptedProperties
    SecretKey credCardKey = ...;        // or from a restricted database, etc.
    ...
    String bankAccountNumber = ...;     // Assume obtained elsewhere
    String creditCardNumber = ...;      // Ditto
    ...
    try {
        // Encrypt each with their appropriate secret key
        CipherText encryptedBankAcct =
            ESAPI.encryptor().encrypt( bankAcctKey, new PlainText(bankAccountNumber) );
        CipherText encryptedCreditCard =
            ESAPI.encryptor().encrypt( credCardKey, new PlainText(creditCardNumber) );
        ...
        // Decrypt using appropriate secret key
        PlainText recoveredBankAcct = ESAPI.encryptor().decrypt( bankAcctKey, encryptedBankAcct ) );
        assert bankAccountNumber.equals( recoveredBankAcct );
        ... etc. ...
    } catch(EncryptionException ex) {
        // Log error then return error designation however appropriate.
    }</PRE>
<H3>Using ESAPI with Multiple Cipher Transformations</H3>
For the most part, the architecture of ESAPI assumes that you will
stick to using the defaults in the <b>ESAPI.properties</b> configuration
file or implment your own classes--possibly by extending the ESAPI
reference classes--and use these classes instead of the reference
classes.
<p>
For most things, this works well. Most applications likely can
standardize on a single cipher transformation such as AES/CBC/PKCS5Padding
with a 128-bit AES key and use that 100% of the time. However, on
occassion, an application may need to use two separate cipher
transformations (or even two different cipher algorithms) to
handle legacy applications or deal with multiple partners.
</p><p>
This section discusses how to do this without implementing your own
classes or extending the ESAPI reference class, <code>JavaEncryptor</code>.
Note that it is recognized that this approach is somewhat of a kludge.
A simpler approach is planned for ESAPI 2.1, but the approach shown
here is workable even though it's not pretty.
</p><p>
If you find yourself in need of encrypting with a different cipher
transformation, the first thing that you should count on is not
using the same encryption key for each. While in some cases this
likely would work (e.g., you are only using a different cipher mode
or you have 256-bit AES key for "Encryptor.MasterKey" but also have
a need to do encryption with a 128-bit AES key), it is not guaranteed
to do so. Instead, you should count on generating a separate encryption
key and using the encrypt / decrypt methods taking an additional
<code>SecretKey</code> parameter as show in the previous section.
</p>
<p>
Rather than repeating all the details of how to do this in this
user guide, we encourage you to investigate how this was done in
the Junit testing for the <code>JavaEncryptor</code> class. Please
look at the source code for the private method
<code>runNewEncryptDecryptTestCase(String, int, byte[])</code> in
the <code>EncryptorTest</code> JUnit test in the source code
"src/test/java/org/owasp/esapi/reference/crypto/EncryptorTest.java".
This code calls:
<pre>
		ESAPI.securityConfiguration().setCipherTransformation(cipherXform);
</pre>
which sets ESAPI to use the specified cipher transformation,
<code>cipherXform</code>. As a convenience (for later restoral),
it returns the previous cipher transformation.
<p>
There are also a few non-obvious key size adjustments that are also
going on with DES and DESede (aka, triple DES) keys that are made there
as well. This has to do with the fact that for DES keys (which
includes DESede), the "true" key size differs from the "effective"
key size. (E.g., in DES, the "true" key size--from the DES algorithms's
perspective is 64-bits, however the <i>effective</i> key size for DES
is only 56-bits because of the 8-bits of parity "imposed" by the NSA in
the early 1970s.) This inconsistency manifests itself in the JCE by
the fact that <code>KeyGenerator.init()</code> wants the <i>effective</i>
key size to be specified (so 56-bits for DES, 112- or 168-bits for
DESede), but <code>SecretKey.getEncoding().length</code> stores the
"true" key size (e.g., 64-bits or 192-bits for DES and DESede respectively).
Other cipher algorithms do not have this discrepancy between true and
effective key sizes. Since a <code>SecretKey</code> is returned by the
<code>KeyGenerator</code>, this is only all too confusing. The
reference <code>JavaEncryptor</code> and its JUnit test,
<code>EncryptorTest</code> attempt to deal with this discrepency.
See the adjustments made to key size in
<code>EncryptorTest.runNewEncryptDecryptTestCase()</code>
for further details.
</p>
<H2>Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules</H2>
If you wish to use ESAPI with a FIPS 140-2 validated, JCE-compliant
cryptographic module such as the
<a
href="http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/1401val2005.htm#497"
target="_blank">
IBM Java JCE FIPS 140-2 Cryptographic Module</a>
(hereafter referred to as IBMJCEFIPS) or the
<a
href="http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/1401val2008.htm#1048"
target="_blank">
RSA Security BSafe Crypto-J</a>
(hereafter referred to as Crypto-J), or other similar products, you
<i>must</i> follow these instructions. Failure to do so will mean that
you will fail to meet FISMA compliance. (<b>Note</b>: The mention of these
two specific vendor products does not constitute an endorsement from
either OWASP or this author.)
<br />
<ol>
<li>Follow the vendor's regular instructions to configure your application
to use the vendor product in a FIPS 140-2 compliant manner. Generally this
will include some special configuration and/or initialization requirements
that must be followed to restrict the vendor software to use FIPS 140-2
approved algorithms.
<br /><br />
If the vendor's instructions do not already include a recommendation to edit
the <code>$JAVA_HOME/jre/lib/security/java.security</code> file, the OWASP
team recommends that you do so to prevent you from accidentally using any
other cryptographic module (such as SunJCE). To do this, you will need
to change the property "security.provider.1" (which represents the default)
provider so that it refers to the fully-qualified classname of
your vendor's JCE <code>Provider</code> class. (By default, this is set to
"sun.security.provider.Sun".) In fact, you may wish to go as far as to
either comment out or remove the other providers to reduce the possibility
that they will accidentally be used by your application.
</li>
<li>Edit the <b>ESAPI.properties</b> that your application is going to
be using and set the property "Encryptor.PreferredJCEProvider" to
the fully qualified classname of your vendor's FIPS 140-2 compliant
JCE provider class. (If you are using a Java <code>SecurityManager</code>
you may also need to grant
<code>org.owasp.esapi.reference.crypto.JavaEncryptor</code> permissions
to change the JCE provider.)
</li>
<li>Edit the <b>ESAPI.properties</b> that your application is going to
be using and set the property <b>Encryptor.CipherText.useMAC</b> to
<b><code>false</code></b>. This is critical as having this property
set to <b><code>true</code></b> causes ESAPI to use <i>derived</i> keys
for the actual encryption and MAC calculation, which is against FIPS 140-2
compliance. (<b>Note</b>: This
does not mean that OWASP believes that this key derivation is weak--its
design has been suggested some cryptographers--but it would be creating and
using a related key for encryption in a manner not reviewed by NIST
and thus it is not acceptable to FIPS 140-2 approval.)
</li>
<li>Edit the <b>ESAPI.properties</b> that your application is going to
be using and set the property "Encryptor.CipherTransformation" to
a cipher transformation that is FIPS 140-2 certified for you vendor's
software. OWASP recommends using a NIST "combined" cipher mode, that is
one that provides for both message confidentiality <i>and</i> message
authenticity if such a cipher mode is available from your vendor
and FIPS 140-2 certified. (Cipher modes "GCM" and "CCM" are the only
FIPS 140-2 approved as of this writing.)
If such a "combined" cipher mode is not available, then use a cipher
transformation like "AES/CBC/PKCS5Padding" with a random IV.
This is almost always available as one of the FIPS 140-2 certified cipher
transformations, however it will not provide you with message authenticity
because to remain FIPS 140-2 compliant you will have had to disable the
MAC calculation (via setting <b>Encryptor.CipherText.useMAC</b> to
<b><code>false</code></b>) causing ESAPI to skip calculating an
explicit MAC for you and hence providing no assurance of data integrity
to the party attempting to decrypt your data. Without authenticity
however, your encryption may still be vulnerable to the "padded oracle"
chose ciphertext attack. Consult with your local cryptographic expert in
such cases as this depends greatly on the circumstances of how you are
using encryption.
</li>
<li>
If your vendor softare requires you to explicitly to initialize their
software for FIPS-mode (e.g., to cause the required FIPS 140-2 "power-on
self tests" to run) by calling some software method, then this must be
done <i>by your application code <b>before</b></i> calling any of the ESAPI
crypto-related code. Specifically, it must be called <i>before</i>
your application calls <code>ESAPI.encryptor()</code>.
</li>
</ol>
<br />
We believe that following these steps will still allow for your application
to be FIPS 140-2 / FISMA compliant, however, as always, you should check
with your FIPS auditor before using ESAPI in this manner. Should your
auditors ask, feel free to point them to the ESAPI source code, which
we believe will convince them that ESAPI is not a cryptographic module.
(Rather, it only provides a wrapper to call other cryptographic modules
through the standard JCE APIs.)
<H2>Acknowledgments</H2>
The OWASP ESAPI development team would like to acknowledge the contributions
of cryptographers David A. Wagner and Ian Grigg. David provided the
outline of how to securely compute derived keys for confidentiality
and authenticity from a single master key and Ian convinced us
to take a packetizing approach to laying out the portable, serialized
<code>CipherText</code> object.
<p>
In addition, Kevin Kenan has agreed to review all the crypto code
from ESAPI 2.0-rc5 or 2.0-rc6 candidate release. Others are invited
to participate as well, especially those with a background in cryptography.
(See <a href="http://www.owasp.org/index.php/Request_to_review_ESAPI_2.0_crypto">
"Request to review ESAPI 2.0 crypto"</a> for details.)
</p><p>
I would also like to thank Jessica Fitzgerald-McKay and Andy Sampson of
the Systems and Network Analysis Center of the NSA for their excellent feedback in
response to the review request made in Google Issue #81. Working with bureaucracy
is not something that I do particularly well, but Jessica and Andy made it as
painless as it possibly could be. Their feedback, which at this point,
unfortunately we are unable to quote, was generally favorable, but in the
places where they had recommendations, these were very precise and
helpful.
</p><p>
Lastly, I would like to thank Jeffrey Walton of Software Integrity, LLC.
Jeff provided an extremely thorough analysis of ESAPI 2.0's (as of 2.0_rc10)
Key Derivation Function (KDF). Jeff's analysis convinced me to bring ESAPI's
KDF more in line with NIST's recommendations for KDFs as described in
NIST Special Publication 800-108 (and specifically section 5.1). You can
read about Jeff's review at
<a href="http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/Analysis-of-ESAPI-2.0-KDF.pdf">
Analysis of ESAPI 2.0's Key Derivation Function
</a>
</p>
</BODY>
</HTML>