3939// But if we do wish to restrict it to use from JavaEncryptor,
4040// it I can assume this class will be used correctly and not be
4141// concerned about making it act like it is immutable once everything
42- // has been collected and the MIC has been computed...all of which make
42+ // has been collected and the MAC has been computed...all of which make
4343// this class much more complex than it otherwise needs to be. But if
4444// we are uncertain as to the context of how it will be used, then it's
4545// probably best to be defensive.
4646/**
4747 * Reference implementation of <code>CipherText</code>. This object is both
4848 * serializable, and once all the required information has been collected and
49- * the Message Integrity Code (MIC ) has been computed, it acts as though it is
49+ * the Message Authentication Code (MAC ) has been computed, it acts as though it is
5050 * immutable as well. At that point, one can no longer call any of the 'setter'
5151 * methods.
5252 * <p>
5353 * <b>NOTE:</b> This class is <i>not</i> thread-safe.
5454 * </p><p>
55- * Copyright (c) 2009 - The OWASP Foundation
55+ * Copyright © 2009 - The OWASP Foundation
5656 * </p>
5757 * @author kevin.w.wall@gmail.com
5858 * @since 2.0
@@ -64,8 +64,7 @@ public final class DefaultCipherText implements CipherText {
6464
6565 private CipherSpec cipherSpec_ = null ;
6666 private byte [] raw_ciphertext_ = null ;
67- private byte [] nonce_ = null ;
68- private byte [] mic_ = null ;
67+ private byte [] mac_ = null ;
6968
7069 // All the various pieces that can be set, either directly or indirectly
7170 // via CipherSpec.
@@ -234,57 +233,57 @@ public String getEncodedIVCipherText() {
234233 /**
235234 * {@inheritDoc}
236235 */
237- public void computeAndStoreMIC ( byte [] raw_ciphertext ) {
238- assert !micComputed () : "Programming error: Can't store message integrity code while encrypting; " +
239- "computeAndStoreMIC () called multiple times." ;
240- assert collectedAll () : "Have not collected all required information to compute and store MIC ." ;
241- byte [] result = computeMIC ( raw_ciphertext );
236+ public void computeAndStoreMAC ( SecretKey authKey ) {
237+ assert !macComputed () : "Programming error: Can't store message integrity code while encrypting; " +
238+ "computeAndStoreMAC () called multiple times." ;
239+ assert collectedAll () : "Have not collected all required information to compute and store MAC ." ;
240+ byte [] result = computeMAC ( authKey );
242241 if ( result != null ) {
243- mic_ = new byte [ result .length ];
244- CryptoHelper .copyByteArray (result , mic_ );
245- assert micComputed ();
242+ mac_ = new byte [ result .length ];
243+ CryptoHelper .copyByteArray (result , mac_ );
244+ assert macComputed ();
246245 }
247- // If 'result' is null, we already logged this in computeMIC ().
246+ // If 'result' is null, we already logged this in computeMAC ().
248247 }
249248
250249 /**
251250 * {@inheritDoc}
252251 */
253- public boolean validateMIC ( byte [] secretKey ) {
254- boolean usesMIC = ESAPI .securityConfiguration ().useMICforCipherText ();
252+ public boolean validateMAC ( SecretKey authKey ) {
253+ boolean usesMAC = ESAPI .securityConfiguration ().useMACforCipherText ();
255254
256- if ( usesMIC && micComputed () ) { // Uses MIC and it was computed
257- // Calculate MIC from HMAC-SHA1(nonce, IV + plaintext) and
258- // compare to stored value (mic_ ). If same, then return true,
255+ if ( usesMAC && macComputed () ) { // Uses MAC and it was computed
256+ // Calculate MAC from HMAC-SHA1(nonce, IV + plaintext) and
257+ // compare to stored value (mac_ ). If same, then return true,
259258 // else return false.
260- assert getNonce () != null : "Cannot validate MIC while nonce is null." ;
261- byte [] mic = computeMIC (secretKey );
262- assert mic .length == mic_ .length : "MICs are of differnt lengths. Should both be the same." ;
263- for ( int i = 0 ; i < mic .length ; i ++ ) {
264- if ( mic [i ] != mic_ [i ] ) {
259+ byte [] mac = computeMAC (authKey );
260+ assert mac .length == mac_ .length : "MACs are of differnt lengths. Should both be the same." ;
261+ for ( int i = 0 ; i < mac .length ; i ++ ) {
262+ if ( mac [i ] != mac_ [i ] ) {
265263 return false ;
266264 }
267265 }
268266 return true ;
269- } else if ( ! usesMIC ) { // Doesn't use MIC
267+ } else if ( ! usesMAC ) { // Doesn't use MAC
270268 return true ;
271- } else { // Uses MIC but it has not been computed / stored.
272- logger .warning (Logger .SECURITY_FAILURE , "Cannot validate MIC as it was never computed and stored. Decryption result may be garbage." );
273- return true ; // Need to return 'true' here because of CryptoHelper encrypt() / decrypt() methods.
269+ } else { // Uses MAC but it has not been computed / stored.
270+ logger .warning (Logger .SECURITY_FAILURE , "Cannot validate MAC as it was never computed and stored. " +
271+ "Decryption result may be garbage even when decryption succeeds." );
272+ return true ; // Need to return 'true' here because of encrypt() / decrypt() methods don't support this.
274273 }
275274 }
276275
277276
278277 /**
279278 * Set the raw ciphertext.
280279 * @param ciphertext The raw ciphertext.
281- * @throws EncryptionException Thrown if the MIC has already been computed
282- * via {@link #computeAndStoreMIC (byte[])}.
280+ * @throws EncryptionException Thrown if the MAC has already been computed
281+ * via {@link #computeAndStoreMAC (byte[])}.
283282 */
284283 public void setCiphertext (byte [] ciphertext )
285284 throws EncryptionException
286285 {
287- if ( ! micComputed () ) {
286+ if ( ! macComputed () ) {
288287 if ( ciphertext == null || ciphertext .length == 0 ) {
289288 throw new EncryptionException ("Encryption faled; no ciphertext" ,
290289 "Ciphertext may not be null or 0 length!" );
@@ -295,7 +294,7 @@ public void setCiphertext(byte[] ciphertext)
295294 raw_ciphertext_ = new byte [ ciphertext .length ];
296295 CryptoHelper .copyByteArray (ciphertext , raw_ciphertext_ );
297296 } else {
298- String logMsg = "Programming error: Attempt to set ciphertext after MIC already computed." ;
297+ String logMsg = "Programming error: Attempt to set ciphertext after MAC already computed." ;
299298 logger .error (Logger .SECURITY_FAILURE , logMsg );
300299 throw new EncryptionException ("Cannot store raw ciphertext." , logMsg );
301300 }
@@ -316,7 +315,7 @@ public void setIVandCiphertext(byte[] iv, byte[] ciphertext)
316315 if ( isCollected (CipherTextFlags .CIPHERTEXT ) ) {
317316 logger .warning (Logger .SECURITY_FAILURE , "Raw ciphertext was already set; resetting." );
318317 }
319- if ( ! micComputed () ) {
318+ if ( ! macComputed () ) {
320319 if ( ciphertext == null || ciphertext .length == 0 ) {
321320 throw new EncryptionException ("Encryption faled; no ciphertext" ,
322321 "Ciphertext may not be null or 0 length!" );
@@ -335,7 +334,7 @@ public void setIVandCiphertext(byte[] iv, byte[] ciphertext)
335334 setCiphertext ( ciphertext );
336335 received (CipherTextFlags .CIPHERTEXT );
337336 } else {
338- String logMsg = "MIC already computed from previously set IV and raw ciphertext; may not be reset -- object is immutable." ;
337+ String logMsg = "MAC already computed from previously set IV and raw ciphertext; may not be reset -- object is immutable." ;
339338 logger .error (Logger .SECURITY_FAILURE , logMsg ); // Discuss: By throwing, this gets logged as warning, but it's really error! Why is an exception only a warning???
340339 throw new EncryptionException ("Validation of decryption failed." , logMsg );
341340 }
@@ -355,71 +354,52 @@ public boolean requiresIV() {
355354 public String toString () {
356355 StringBuilder sb = new StringBuilder ( "DefaultCipherText: " );
357356 String rawCipherText = (( getRawCipherText () != null ) ? "present" : "absent" );
358- String mic = (( mic_ != null ) ? "present" : "absent" );
357+ String mac = (( mac_ != null ) ? "present" : "absent" );
359358 sb .append ("raw ciphertext is " ).append (rawCipherText );
360- sb .append (", MIC is " ).append (mic ).append ("; " );
359+ sb .append (", MAC is " ).append (mac ).append ("; " );
361360 sb .append ( cipherSpec_ .toString () );
362361 return sb .toString ();
363362 }
364363
365364 //////////////////////////////////// P R I V A T E /////////////////////////////////////////
366365
367366 /**
368- * Compute a MIC , but do not store it. May set the nonce value as a
369- * side-effect. The MIC is calculated as:
367+ * Compute a MAC , but do not store it. May set the nonce value as a
368+ * side-effect. The MAC is calculated as:
370369 * <pre>
371370 * HMAC-SHA1(nonce, IV + plaintext)
372371 * </pre>
373- * @param ciphertext The ciphertext value for which the MIC is computed.
374- * @return The value for the MIC .
372+ * @param ciphertext The ciphertext value for which the MAC is computed.
373+ * @return The value for the MAC .
375374 */
376- private byte [] computeMIC (byte [] ciphertext ) {
377- assert ciphertext != null && ciphertext .length != 0 : "Plaintext may not be null or empty." ;
375+ private byte [] computeMAC (SecretKey authKey ) {
376+ assert raw_ciphertext_ != null && raw_ciphertext_ .length != 0 : "Raw ciphertext may not be null or empty." ;
377+ assert authKey != null && authKey .getEncoded ().length != 0 : "Authenticity secret key may not be null or zero length." ;
378378 try {
379- KeyGenerator kg = KeyGenerator .getInstance ("HmacSHA1" );
380- SecretKey sk = null ;
381- if ( nonce_ == null ) {
382- sk = kg .generateKey ();
383- } else {
384- sk = new SecretKeySpec (nonce_ , "HmacSHA1" );
385- }
379+ SecretKey sk = new SecretKeySpec (authKey .getEncoded (), "HmacSHA1" );
386380 Mac mac = Mac .getInstance ("HmacSHA1" );
387381 mac .init (sk );
388- byte [] result = mac .doFinal (ciphertext );
389- // POSSIBLE SIDE-EFFECT !!!!
390- if ( nonce_ == null ) {
391- nonce_ = sk .getEncoded (); // Side-effect -- nonce set here!
392- assert nonce_ != null : "Failed to create nonce value." ;
382+ if ( requiresIV () ) {
383+ mac .update ( getIV () );
393384 }
385+ byte [] result = mac .doFinal ( getRawCipherText () );
394386 return result ;
395387 } catch (NoSuchAlgorithmException e ) {
396388 e .printStackTrace (System .err );
397- logger .error (Logger .SECURITY_FAILURE , "Cannot compute MIC w/out HmacSHA1." , e );
389+ logger .error (Logger .SECURITY_FAILURE , "Cannot compute MAC w/out HmacSHA1." , e );
398390 return null ;
399391 } catch (InvalidKeyException e ) {
400392 e .printStackTrace (System .err );
401- logger .error (Logger .SECURITY_FAILURE , "Cannot comput MIC ; invalid 'key' for HmacSHA1." , e );
393+ logger .error (Logger .SECURITY_FAILURE , "Cannot comput MAC ; invalid 'key' for HmacSHA1." , e );
402394 return null ;
403395 }
404396 }
405397
406398 /**
407- * Return true if the MIC has already been computed (i.e., not null).
399+ * Return true if the MAC has already been computed (i.e., not null).
408400 */
409- private boolean micComputed () {
410- return (mic_ != null );
411- }
412-
413- /**
414- * Retrieve the nonce value used in the calculation of the MIC.
415- */
416- private byte [] getNonce () {
417- if ( micComputed () ) {
418- return nonce_ ;
419- } else {
420- logger .error (Logger .SECURITY_FAILURE , "Nonce for MIC not set yet; unable to retrieve; returning null" );
421- return null ;
422- }
401+ private boolean macComputed () {
402+ return (mac_ != null );
423403 }
424404
425405 /**
0 commit comments