Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
259   860   51   11.77
66   444   0.28   22
22     3.27  
1    
 
 
  LogFileWriter       Line # 75 259 51 59.1% 0.5907781
 
No Tests
 
1    /*
2    * Copyright (c) 2006, University of Kent
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this
9    * list of conditions and the following disclaimer.
10    *
11    * Redistributions in binary form must reproduce the above copyright notice,
12    * this list of conditions and the following disclaimer in the documentation
13    * and/or other materials provided with the distribution.
14    *
15    * 1. Neither the name of the University of Kent nor the names of its
16    * contributors may be used to endorse or promote products derived from this
17    * software without specific prior written permission.
18    *
19    * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20    * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22    * PURPOSE ARE DISCLAIMED.
23    *
24    * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31    * POSSIBILITY OF SUCH DAMAGE.
32    *
33    * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE
34    * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS
35    * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS
36    * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH
37    * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH
38    * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY
39    * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE
40    * SERIOUS FAULTS, IN THIS SOFTWARE.
41    *
42    * 5. This license is governed, except to the extent that local laws
43    * necessarily apply, by the laws of England and Wales.
44    */
45   
46    package issrg.SAWS;
47   
48    import issrg.SAWS.util.SAWSLogWriter;
49   
50    import java.util.*;
51    import java.io.*;
52    import java.io.File;
53   
54    import java.io.BufferedReader;
55    import java.io.FileInputStream;
56    import java.io.FileNotFoundException;
57    import java.io.InputStreamReader;
58   
59    import java.security.*;
60    import javax.crypto.*;
61    import java.security.AlgorithmParameters;
62    import javax.crypto.spec.* ;
63   
64    import javax.security.auth.callback.*;
65   
66    import javax.swing.*;
67   
68    import issrg.SAWS.callback.SAWSGUICallbackHandler;
69    import issrg.SAWS.callback.SAWSTextOutputCallback;
70   
71    /**
72    *
73    * @author W.Xu
74    */
 
75    public class LogFileWriter {
76   
77    // for writing the current log file
78    public int currentRecordWriteCount= -1 ;
79    public byte[] accumulatedHash = null; // new byte[20];
80    public byte [] finalSignature = null;
81   
82    private String currentLogFilename = null;
83    private int currentLogSequence = -1;
84   
85    private File CurrentLogFile = null;
86    private java.security.MessageDigest accMD = null;
87    private RandomAccessFile rafCurrentLogFile = null;
88    private String logFileRoot;
89   
90    private byte[] secureRandomBytes = new byte[20];
91    private SecretKey symmetricKeyInLog = null; //symmetric encryption key stored in log file
92    private byte[] baSigningPublicKeyCert = null;
93   
94    private int thisRecordLength = 0;
95    private int lastRecordLength = 0;
96   
97    // keys used in SAWS
98    private PublicKey sawsEncryptionPublicKey = null;
99    private PrivateKey sawsEncryptionPrivateKey = null;
100    private PublicKey sawsSigningPublicKey = null;
101    private PrivateKey sawsSigningPrivateKey = null;
102    private PublicKey vtEncryptionPublicKey = null;
103    private PublicKey rootCAPublicKey = null;
104    private Map UserIDPKMap = null;
105   
106   
107    //String signingAlgName = null;
108   
109    private byte hashAlgorithm = SAWSConstant.SHA1;
110    private String hashAlgorithmName = "SHA1";
111   
112    private byte [] lastAccumulatedHash = null;
113   
114    private int debugLevel = 0;
115   
116    private CallbackHandler callbackHandler = new SAWSGUICallbackHandler();
117   
118   
119    /**
120    * @aggregation composite
121    */
122    private static SAWSLogWriter sawsDebugLog = new SAWSLogWriter(LogFileWriter.class.getName());
123   
124    /**
125    * This method is the constructor of LogFileWriter.
126    *
127    */
 
128  0 toggle public LogFileWriter() {
129    }
130   
 
131  11 toggle public void setDebugLevel(int debugLevel) {
132  11 this.debugLevel = debugLevel;
133    }
134   
135    /**
136    * This method is the constructor of LogFileWriter.
137    *
138    * @param root String is the log root
139    * @param cLogFilename is the log file name to be written
140    * @param vt is the SAWS VT public key
141    * @param sawsEncPK is the SAWS encryption public key
142    * @param sawsSignPIK is the SAWS signing private key
143    * @param ba is the binary array of the SAWS signing public key certificate to be written into
144    * the log file
145    * @param hashAlgorithm is the hash algorithem code
146    * @param secureBytes is the secure random number used for secure hashing
147    *
148    * @return null.
149    */
 
150  11 toggle public LogFileWriter(String root, String cLogFilename, PublicKey vt, PublicKey sawsEncPK, PrivateKey sawsSignPIK,
151    byte[] ba, byte hashAlgorithm, byte[] secureBytes, Map UserIDPKMap) {
152  11 logFileRoot = root;
153  11 currentLogFilename = cLogFilename;
154  11 vtEncryptionPublicKey = vt;
155  11 sawsEncryptionPublicKey = sawsEncPK;
156  11 sawsSigningPrivateKey = sawsSignPIK;
157  11 baSigningPublicKeyCert = ba;
158    //signingAlgName = sAlgName;
159  11 this.hashAlgorithm = hashAlgorithm;
160  11 this.setHashAlgorithmName(hashAlgorithm);
161   
162  11 if (secureBytes != null)
163  0 secureRandomBytes = secureBytes;
164   
165  11 try{
166  11 accMD = java.security.MessageDigest.getInstance(this.hashAlgorithmName);//"SHA");
167    } catch (Exception e) {
168  0 e.printStackTrace(System.err);
169    }
170  11 this.UserIDPKMap = UserIDPKMap;
171   
172   
173    }
174   
175    /**
176    * This method is the constructor of LogFileWriter.
177    *
178    * @param root String is the log root
179    * @param cLogFilename is the log file name to be written
180    * @param vt is the SAWS VT public key
181    * @param sawsEncPK is the SAWS encryption public key
182    * @param sawsSignPIK is the SAWS signing private key
183    * @param ba is the binary array of the SAWS signing public key certificate to be written into
184    * the log file
185    * @param hashAlgorithm is the hash algorithem code
186    * @param secureBytes is the secure random number used for secure hashing
187    *
188    * @return null.
189    */
 
190  11 toggle public LogFileWriter(String root, String cLogFilename, PublicKey vt, PublicKey sawsEncPK, PrivateKey sawsSignPIK,
191    byte[] ba, byte hashAlgorithm, byte[] secureBytes, Map UserIDPKMap, CallbackHandler ch) {
192  11 this(root, cLogFilename, vt, sawsEncPK, sawsSignPIK, ba, hashAlgorithm,
193    secureBytes, UserIDPKMap);
194  11 this.callbackHandler = ch;
195    }
196   
197    /**
198    * Method that sets the callback handler for the class. If the handler
199    * is null, the class will keep using the default callback handler.
200    *
201    * @param ch The callback handler.
202    */
 
203  0 toggle public void setCallbackHandler(CallbackHandler ch) {
204  0 if (ch != null) {
205  0 this.callbackHandler = ch;
206    }
207    }
208   
209    /**
210    * method that sets the name of the hash algorithm from the code of the algorithm.
211    *
212    * @see issrg.SAWS.SAWSConstant
213    *
214    * @param hashAlgorithm The code of the algorithm.
215    */
 
216  11 toggle public void setHashAlgorithmName(byte hashAlgorithm) {
217  11 if ((hashAlgorithm >= 0) && (hashAlgorithm < SAWSConstant.HASH_ALG_NAMES.length)) {
218  11 this.hashAlgorithmName = SAWSConstant.HASH_ALG_NAMES[hashAlgorithm];
219    } else {
220  0 this.showMessage("Hash algorithm not supported. SAWS will stop",
221    SAWSTextOutputCallback.WARNING);
222    //System.err.println("Hash algorithm not supported. SAWS will stop");
223  0 if (debugLevel > SAWSConstant.NoInfo) {
224  0 sawsDebugLog.write("Hash algorithm not supported.");
225    }
226  0 System.exit(-1);
227    }
228    }
229   
230    /**
231    * This method is to set the algorithm for hash generation. SHA1 is the default algorithm.
232    * @param hashAlgorithm an integer value that represents the algorithm.
233    * 0 for SHA1 and 1 for MD5 (see issrg.SAWS.SAWSConstant).
234    */
 
235  0 toggle public void setHashAlgorithm(byte hashAlgorithm) {
236  0 this.hashAlgorithm = hashAlgorithm;
237    }
238   
239    /**
240    * This method returns the int for the hash algorithm.
241    * @return 0 for SHA1 or 1 for MD5 (see issrg.SAWS.SAWSConstant).
242    */
 
243  0 toggle public byte getHashAlgorithm() {
244  0 return this.hashAlgorithm;
245    }
246   
247    /**
248    * This method is to get the final signature
249    *
250    */
 
251  7 toggle public byte[] getSignature(){
252  7 return finalSignature;
253    }
254   
255    /**
256    * This method is to get the final accumualted hash
257    *
258    */
 
259  115 toggle public byte[] getAccHash(){
260  115 return accumulatedHash;
261    }
262   
263    /**
264    * This method is to get the current writing record number in the current log file
265    *
266    */
 
267  173 toggle public int getCurrentRecordWriteCount(){
268  173 return currentRecordWriteCount;
269    }
270   
271    /**
272    * This method creates a new log file, prepares this file for adding new log records to it in the future.
273    *
274    * @return 0 if success or -1 if fails.
275    */
 
276  11 toggle public int prepareNewLog(){
277  11 try{
278  11 accMD.reset();
279  11 accMD.update(currentLogFilename.getBytes());
280    } catch (Exception e){
281  0 this.showMessage("Updating accumulated hash error. SAWS will stop.",
282    SAWSTextOutputCallback.ERROR);
283    //System.err.println("Updating accumulated hash error. SAWS will stop.");
284  0 if (debugLevel > SAWSConstant.NoInfo) {
285    //adding log4j logging
286  0 sawsDebugLog.write(e.toString());
287    }
288  0 return -1;
289    }
290   
291  11 if (debugLevel > SAWSConstant.NoInfo) {
292    //adding log4j logging
293  0 sawsDebugLog.write("Now creating a new log.");
294    }
295  11 currentRecordWriteCount = -1;
296   
297  11 CurrentLogFile = new File(logFileRoot, currentLogFilename );
298   
299  11 try{
300  11 rafCurrentLogFile = new RandomAccessFile(CurrentLogFile, "rw");
301    } catch (Exception e) {
302  0 this.showMessage("Open file " + currentLogFilename + " error. SAWS will stop.",
303    SAWSTextOutputCallback.ERROR);
304    //System.err.println("Open file " + currentLogFilename + " error. SAWS will stop.");
305  0 if (debugLevel > SAWSConstant.NoInfo) {
306    //adding log4j logging
307  0 sawsDebugLog.write(e.toString());
308    }
309  0 return -1;
310    }
311   
312    //Generate a secure random number. This number will participate in the secure hash calculation.
313  11 SecureRandom random = null;
314  11 try {
315  11 random = SecureRandom.getInstance("SHA1PRNG", "SUN");
316  11 random.nextBytes(secureRandomBytes);
317    } catch (Exception e1) {
318  0 this.showMessage("Generating random number error. SAWS will stop.",
319    SAWSTextOutputCallback.ERROR);
320   
321    //System.err.println("Generating random number error. SAWS will stop.");
322  0 if (debugLevel > SAWSConstant.NoInfo) {
323  0 sawsDebugLog.write(e1.toString());
324    }
325  0 return -1;
326    }
327   
328  11 try{
329  11 this.createSAWSRecord(new byte[]{this.hashAlgorithm}, SAWSConstant.SAWSHashAlgorithmType,
330    SAWSConstant.NoEncryptionFlag);
331   
332  11 KeyGenerator kgen = KeyGenerator.getInstance("AES");
333  11 kgen.init(128);
334  11 symmetricKeyInLog = kgen.generateKey();
335  11 byte[] rawKey = symmetricKeyInLog.getEncoded();
336   
337  11 createSAWSRecord(secureRandomBytes, SAWSConstant.SAWSSecretRandomNumberType,
338    SAWSConstant.AsymmetricEncryptionFlag) ;
339   
340  11 createSAWSRecord(rawKey, SAWSConstant.SymmetricEncryptionKeyType,
341    SAWSConstant.AsymmetricEncryptionFlag);
342   
343  11 createSAWSRecord( rawKey, SAWSConstant.SymmetricEncryptionKeyType, (byte) SAWSConstant.USERVT,
344    SAWSConstant.AsymmetricEncryptionFlag,
345    vtEncryptionPublicKey) ;
346   
347  11 Iterator idpkIt = UserIDPKMap.entrySet().iterator();
348  33 while ( idpkIt.hasNext() ) {
349  22 Map.Entry userIDPK = (Map.Entry) idpkIt.next();
350  22 byte uID = ((Byte) userIDPK.getKey() ).byteValue();
351  22 PublicKey pk = (PublicKey) userIDPK.getValue();
352   
353  22 createSAWSRecord( rawKey, SAWSConstant.SymmetricEncryptionKeyType,
354    (byte) uID,
355    SAWSConstant.AsymmetricEncryptionFlag,
356    pk) ;
357   
358    }
359   
360  11 createSAWSRecord(baSigningPublicKeyCert, SAWSConstant.SAWSCertificateType,
361    SAWSConstant.NoEncryptionFlag);
362    // now write a signature record to the log file
363  11 writeSignatureRecord(SAWSConstant.SAWSHeaderSignatureType);
364   
365    } catch (Exception e3) {
366  0 this.showMessage("Prepare new log error. SAWS will stop",
367    SAWSTextOutputCallback.ERROR);
368    //System.err.println("Prepare new log error. SAWS will stop");
369  0 if (debugLevel > SAWSConstant.NoInfo) {
370    //adding log4j logging
371  0 sawsDebugLog.write(e3.toString());
372    }
373  0 return -1;
374    }
375  11 return 0;
376   
377    }
378   
379   
380    /**
381    * This method is to write the log record into the log file.
382    *
383    * @param logRecord record to be written.
384    *
385    */
 
386  214 toggle private void writeLogRecord (byte[] logRecord){
387   
388  214 try{
389  214 rafCurrentLogFile.write(logRecord);
390    } catch (Exception e) {
391  0 if (debugLevel > SAWSConstant.NoInfo) {
392    //adding log4j logging
393  0 sawsDebugLog.write(e.toString());
394    }
395    }
396   
397  214 long currentTime = System.currentTimeMillis();
398    }
399   
400   
401    /**
402    * This method is to generate the record body of a last log file record.
403    *
404    * @param lastFilename the file name of the previous log file
405    * @param lastAccHash the accumulated hash of the previous log file
406    * @param lastSignature the signature of the previous log file
407    *
408    * @return byte[] the block of the lastFileRecord
409    */
 
410  11 toggle public void createLastFileRecord(String lastFilename, byte[] lastAccHash, byte[] lastSignature){
411  11 byte[] b1 = lastFilename.getBytes();
412  11 byte[] all = new byte[b1.length + lastAccHash.length + lastSignature.length + 4*3 ];
413  11 System.arraycopy(utility.intToByteArray(b1.length), 0, all, 0, 4); //
414  11 System.arraycopy(b1, 0, all, 4, b1.length); //
415   
416  11 System.arraycopy(utility.intToByteArray(lastAccHash.length), 0, all, 4 + b1.length , 4); //
417  11 System.arraycopy(lastAccHash, 0, all, 4 + b1.length + 4, lastAccHash.length); //
418   
419  11 System.arraycopy(utility.intToByteArray(lastSignature.length), 0, all, 4 + b1.length + 4
420    + lastAccHash.length , 4); //
421  11 System.arraycopy(lastSignature, 0, all,
422    4 + b1.length + 4 + lastAccHash.length + 4, lastSignature.length); //
423  11 if (debugLevel > SAWSConstant.NoInfo) {
424    //adding log4j logging
425  0 sawsDebugLog.write("\n last log file record created, length = " + all.length);
426    }
427   
428  11 createSAWSRecord(all, SAWSConstant.SAWSLastFileType, SAWSConstant.NoEncryptionFlag);
429    }
430   
431    /**
432    * This method is to create a Record header. count(SN): 4 bytes, UID: 1 byte !!, recordType: 1 byte,
433    * lastRecordLength: 4 bytes, thisRecordLength: 4 bytes, encryptionj: 1 byte !!.
434    * Between recordType and lastRecordLength, another parameter: (long)timeStamp (8 bytes) is
435    * automatically inserted into the byte array. Before the count, a 4 byte "0xf0" leading is
436    * inserted. So the total length for a header is 27!!.
437    *
438    * @param countN the SN
439    * @param recordType the record type
440    * @param UserID user ID ( it is 0x00 when SAWS is invoked by API interface)
441    * @param encrytionFlag the encryption flag.
442    * @param lastLength last record length
443    * @param thisLength this record length
444    *
445    * @return bytes of the record header.
446    */
 
447  214 toggle private byte[] createRecordHeader(int countN, byte recordType, byte UserID, byte encryptionFlag,
448    int lastLength, int thisLength)
449    {
450   
451  214 byte recordHeader[] = new byte[SAWSConstant.HeaderLength];
452  214 recordHeader[0] = (byte)0xf0;
453  214 recordHeader[1] = (byte)0xf0;
454  214 recordHeader[2] = (byte)0xf0;
455  214 recordHeader[3] = (byte)0xf0; //4 bytes
456   
457   
458  214 if (debugLevel > SAWSConstant.NoInfo) {
459    //System.out.println("\nSAWSWriter:createRecordHeader: count = " + countN);
460    //adding log4j logging
461  0 sawsDebugLog.write("\nSAWSWriter:createRecordHeader: count = " + countN);
462    //System.out.println("SAWSWriter:createRecordHeader: recordType = " + SAWSConstant.getRecordTypeString( recordType ));
463    //adding log4j logging
464  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: recordType = " + SAWSConstant.getRecordTypeString( recordType ));
465  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: LastLength = " + lastLength);
466  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: thisLength = " + thisLength);
467    }
468   
469  214 byte[] ba1 = utility.intToByteArray(countN);
470  214 System.arraycopy(ba1, 0, recordHeader,4, 4); //SN: 4 bytes
471   
472   
473  214 recordHeader[8] = recordType; // recordType: 1 byte
474  214 recordHeader[9] = UserID; // user ID: 1 byte
475  214 recordHeader[10] = encryptionFlag; // encryptionFlag: 1 byte
476   
477  214 long ltemp = System.currentTimeMillis();
478   
479  214 byte[] ba2 = utility.longToByteArray(ltemp );
480  214 if (debugLevel > SAWSConstant.NoInfo) {
481    //System.out.println("SAWSWriter:createRecordHeader: current time is: " + ltemp );
482    //adding log4j logging
483  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: current time is: " + ltemp );
484    //System.out.println("SAWSWriter:createRecordHeader: length of ba2 is: " + ba2.length );
485    //adding log4j logging
486  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: length of ba2 is: " + ba2.length );
487    //System.out.println("SAWSWriter:createRecordHeader: ba2 is: " + utility.toHexString(ba2) );
488    //adding log4j logging
489  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: ba2 is: " + utility.toHexString(ba2) );
490    }
491  214 System.arraycopy(ba2, 0, recordHeader,11, 8); //8 bytes
492   
493  214 if (debugLevel > SAWSConstant.NoInfo)
494    //System.out.println("SAWSWriter:createRecordHeader: after transmision: " + utility.byteArrayToLong(ba2) );
495    //adding log4j logging
496  0 sawsDebugLog.write("SAWSWriter:createRecordHeader: after transmision: " + utility.byteArrayToLong(ba2) );
497   
498   
499  214 ba1 = utility.intToByteArray(lastLength);
500  214 System.arraycopy(ba1, 0, recordHeader,19, 4); //4 bytes
501   
502  214 ba1 = utility.intToByteArray(thisLength );
503  214 System.arraycopy(ba1, 0, recordHeader,23, 4); //4 bytes
504   
505  214 return(recordHeader);
506   
507    }
508   
509    /**
510    * This method is to create a SAWS Record . It is a simplied invoke method of the following method.
511    *
512    * @return bytes of the record body.
513    */
 
514  88 toggle public void createSAWSRecord(byte[] messageBlock, byte recordType, byte encryptionFlag)
515    {
516  88 createSAWSRecord(messageBlock, recordType, (byte) 0x00, encryptionFlag);
517    }
518   
519   
520    /**
521    * This method is to create a SAWS Record . It is a simplied invoke method of the following method.
522    *
523    * @return bytes of the record body.
524    */
 
525  88 toggle public void createSAWSRecord(byte[] messageBlock, byte recordType, byte userID, byte encryptionFlag) {
526  88 createSAWSRecord( messageBlock, recordType, userID, encryptionFlag, sawsEncryptionPublicKey);
527    }
528   
529   
530    /**
531    * This method is to create a SAWS Record .
532    *
533    * @param messageBlock log data block (here it is the secret random number to be wrapped into a record.
534    * @param recordType record type
535    * @param userID user ID
536    * @param encryptionFlag encryption flag to indicate the encryption requirement.
537    * @param encryptionPublicKey the encryption public key used for assymmetric encryption.
538    * This could be the VT enc public key, or the SAWS enc public key
539    *
540    * @return bytes of the record body.
541    */
 
542  214 toggle public void createSAWSRecord(byte[] messageBlock, byte recordType, byte userID,
543    byte encryptionFlag, PublicKey encryptionPublicKey) {
544   
545  214 byte[] bodyTemp = null;
546  214 int thisRecordLength;
547  214 if (debugLevel > SAWSConstant.NoInfo)
548    //System.out.println("\nSAWSWriter:createSAWSRecord: currentCount = " + (currentRecordWriteCount+1) );
549    //adding log4j logging
550  0 sawsDebugLog.write("\nSAWSWriter:createSAWSRecord: currentCount = " + (currentRecordWriteCount+1) );
551   
552  214 java.security.MessageDigest md = null;
553  214 try {
554  214 md = java.security.MessageDigest.getInstance(this.hashAlgorithmName);
555   
556    } catch (Exception e) {
557  0 this.showMessage("Message digest error. SAWS will stop.",
558    SAWSTextOutputCallback.ERROR);
559    //System.err.println("Message digest error. SAWS will stop");
560  0 if (debugLevel > SAWSConstant.NoInfo) {
561    //adding log4j logging
562  0 sawsDebugLog.write(e.toString());
563    }
564  0 System.exit(-1);
565    }
566   
567  214 byte record[] = null;
568   
569  214 if (encryptionFlag == SAWSConstant.AsymmetricEncryptionFlag) { //asymmetric encryption is required.
570  55 int messageLength = messageBlock.length;
571  55 thisRecordLength = SAWSConstant.OUTPUTSIZE + SAWSConstant.HeaderLength + SAWSConstant.HashLength[this.hashAlgorithm] ;
572  55 record = new byte[thisRecordLength];
573   
574  55 ++ currentRecordWriteCount; // be prepared for the this record.
575  55 System.arraycopy(
576    createRecordHeader(currentRecordWriteCount, recordType, userID, encryptionFlag,
577    lastRecordLength, thisRecordLength),
578    0, record, 0, SAWSConstant.HeaderLength);
579  55 lastRecordLength = thisRecordLength;
580   
581  55 byte[] cipherText = null, c2=null;
582   
583  55 try{
584   
585  55 javax.crypto.Cipher c1 = javax.crypto.Cipher.getInstance(encryptionPublicKey.getAlgorithm()); //RSA
586   
587  55 c1.init(Cipher.ENCRYPT_MODE, encryptionPublicKey);
588  55 cipherText = c1.doFinal( messageBlock );
589  55 System.arraycopy(cipherText, 0, record,SAWSConstant.HeaderLength, SAWSConstant.OUTPUTSIZE); //OUTPUTSIZE bytes
590   
591  55 bodyTemp = new byte[SAWSConstant.HeaderLength+SAWSConstant.OUTPUTSIZE];
592  55 System.arraycopy(record, 0, bodyTemp,0, SAWSConstant.HeaderLength+SAWSConstant.OUTPUTSIZE); //OUTPUTSIZE bytes
593   
594  55 md.reset();
595  55 md.update(bodyTemp);
596  55 md.update(secureRandomBytes);
597  55 byte[] digest = md.digest();
598   
599  55 System.arraycopy(digest, 0, record,SAWSConstant.HeaderLength+SAWSConstant.OUTPUTSIZE,
600    SAWSConstant.HashLength[this.hashAlgorithm]); //4 bytes
601   
602    } catch(Exception e) {
603  0 this.showMessage("Asymmetric encryption error. SAWS will stop.",
604    SAWSTextOutputCallback.ERROR);
605    //System.err.println("Asymmetric encryption error. SAWS will stop");
606  0 if (debugLevel > SAWSConstant.NoInfo) {
607    //adding log4j logging
608  0 sawsDebugLog.write(e.toString());
609    }
610  0 System.exit(-1);
611  0 e.printStackTrace();
612    }
613    } // if AsymmetricEncryptionFlag
614   
615  214 if (encryptionFlag == SAWSConstant.SymmetricEncryptionFlag) { //Symmetric encryption is required.
616  65 int messageLength = messageBlock.length;
617  65 byte[] encrypted = null;
618   
619  65 try{
620  65 Cipher cipher = Cipher.getInstance("AES");
621  65 cipher.init(Cipher.ENCRYPT_MODE, symmetricKeyInLog);
622  65 encrypted = cipher.doFinal(messageBlock);
623    //System.out.println("encrypted string: " + toHexString(encrypted));
624  65 thisRecordLength = encrypted.length + SAWSConstant.HeaderLength + SAWSConstant.HashLength[this.hashAlgorithm] ;
625  65 record = new byte[thisRecordLength];
626   
627  65 ++ currentRecordWriteCount; // be prepared for this record.
628  65 System.arraycopy(
629    createRecordHeader(currentRecordWriteCount, recordType, userID,
630    encryptionFlag, lastRecordLength, thisRecordLength),
631    0, record, 0, SAWSConstant.HeaderLength);
632  65 lastRecordLength = thisRecordLength;
633   
634  65 System.arraycopy(encrypted, 0, record,SAWSConstant.HeaderLength, encrypted.length); //OUTPUTSIZE bytes
635   
636  65 bodyTemp = new byte[SAWSConstant.HeaderLength+encrypted.length];
637  65 System.arraycopy(record, 0, bodyTemp,0, SAWSConstant.HeaderLength+encrypted.length); //OUTPUTSIZE bytes
638   
639  65 md.reset();
640  65 md.update(bodyTemp);
641  65 md.update(secureRandomBytes);
642  65 byte[] digest = md.digest();
643   
644  65 System.arraycopy(digest, 0, record,SAWSConstant.HeaderLength+encrypted.length, SAWSConstant.HashLength[this.hashAlgorithm]); //20 bytes
645   
646    //System.out.println("Sym time: " + (new java.util.Date(System.currentTimeMillis()) ).toString() );
647   
648    } catch (Exception e) {
649  0 this.showMessage("Symmetric encryption error. SAWS will stop.",
650    SAWSTextOutputCallback.ERROR);
651    //System.err.println("Symmetric encryption error. SAWS will stop.");
652  0 if (debugLevel > SAWSConstant.NoInfo) {
653    //adding log4j logging
654  0 sawsDebugLog.write(e.toString());
655    }
656  0 System.exit(-1);
657    }
658    } // if Symmetric EncryptionFlag
659   
660  214 if (encryptionFlag == SAWSConstant.NoEncryptionFlag) { //No encryption is required.
661  94 int messageLength = messageBlock.length;
662   
663    //if (recordType != SAWSConstant.SAWSHashAlgorithmType) {
664  94 thisRecordLength = messageLength + SAWSConstant.HeaderLength + SAWSConstant.HashLength[this.hashAlgorithm] ;
665  94 record = new byte[thisRecordLength];
666   
667  94 ++ currentRecordWriteCount; // be prepared for the next record.
668  94 System.arraycopy(
669    createRecordHeader(currentRecordWriteCount, recordType, userID,
670    encryptionFlag, lastRecordLength, thisRecordLength),
671    0, record, 0, SAWSConstant.HeaderLength );
672  94 lastRecordLength = thisRecordLength;
673   
674  94 System.arraycopy(messageBlock, 0, record,SAWSConstant.HeaderLength , messageBlock.length);
675   
676  94 bodyTemp = new byte[SAWSConstant.HeaderLength +messageBlock.length];
677  94 System.arraycopy(record, 0, bodyTemp,0, SAWSConstant.HeaderLength +messageBlock.length);
678   
679  94 try{
680  94 md.reset();
681  94 md.update(bodyTemp);
682  94 md.update(secureRandomBytes);
683  94 byte[] digest = md.digest();
684   
685  94 System.arraycopy(digest, 0, record,SAWSConstant.HeaderLength +messageBlock.length, SAWSConstant.HashLength[this.hashAlgorithm]);//16); //20 bytes
686   
687    } catch (Exception e) {
688  0 this.showMessage("No-encryption record creating error. SAWS will stop.",
689    SAWSTextOutputCallback.ERROR);
690    //System.err.println("No-encryption record creating error. SAWS will stop.");
691  0 if (debugLevel > SAWSConstant.NoInfo)
692    //e.printStackTrace(System.err);
693    //adding log4j logging
694  0 sawsDebugLog.write(e.toString());
695  0 System.exit(-1);
696    }
697    /*} else {
698    thisRecordLength = messageLength + SAWSConstant.HeaderLength;
699    record = new byte[thisRecordLength];
700   
701    ++ currentRecordWriteCount; // be prepared for the next record.
702    System.arraycopy(
703    createRecordHeader(currentRecordWriteCount, recordType, userID,
704    encryptionFlag, lastRecordLength, thisRecordLength),
705    0, record, 0, SAWSConstant.HeaderLength );
706    lastRecordLength = thisRecordLength;
707   
708    System.arraycopy(messageBlock, 0, record,SAWSConstant.HeaderLength , messageBlock.length); //
709    }*/
710    } // if NoEncryptionFlag
711   
712  214 if ( ( recordType != SAWSConstant.SAWSAccumulatedHashType) && (recordType != SAWSConstant.SAWSLogFileSignatureType)) {
713  192 try{
714  192 accMD.update(record);
715  192 java.security.MessageDigest tc1 =(java.security.MessageDigest) accMD.clone();
716  192 if (this.accumulatedHash == null) {
717  11 this.accumulatedHash = new byte[SAWSConstant.HashLength[this.hashAlgorithm]];
718    }
719  192 accumulatedHash = tc1.digest();
720    //System.out.println("accumulated hash is: " + utility.toHexString(accumulatedHash) );
721    } catch (Exception e){
722  0 if (debugLevel > SAWSConstant.NoInfo)
723    //e.printStackTrace(System.err);
724    //adding log4j logging
725  0 sawsDebugLog.write(e.toString());
726    }
727    }
728   
729  214 writeLogRecord (record);
730    }
731   
732    /**
733    * This method is to repair a log file. Its main input is logReadingException e.
734    *
735    * @param logRoot the log root
736    * @param logFilename the log filename to be repaired.
737    * @param secureRandomB byte[] is the secure random bytes for this log file
738    * @param logReadingException e is the exception class containing all the necessary information for the repair.
739    *
740    * @return int. 0 for success, -1 for failure.
741    */
 
742  0 toggle public int repairLog(String logRoot, String logFilename, byte[] secureRandomB, logReadingException e) {
743  0 File logFile = new File(logRoot, logFilename);
744   
745  0 if ( e.getErrorCode() != SAWSConstant.LogFileIncompleteErrCode ) {
746   
747  0 this.showMessage("This broken log file " + logFilename + "cannot be recovered. ",
748    SAWSTextOutputCallback.WARNING);
749   
750    /*Object[] options = { "Confirm" };
751    int select = JOptionPane.showOptionDialog(null,
752    "This broken log file " + logFilename + "cannot be recovered. ",
753    "Warning",
754    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
755    null, options, options[0]);*/
756  0 return -1;
757    }
758   
759  0 try{
760  0 rafCurrentLogFile = new RandomAccessFile(logFile, "rw");
761  0 rafCurrentLogFile.seek(rafCurrentLogFile.length());
762    } catch (Exception e2) {
763  0 if (debugLevel > SAWSConstant.NoInfo)
764    //e2.printStackTrace(System.err);
765    //adding log4j logging
766  0 sawsDebugLog.write(e2.toString());
767  0 return -1;
768    }
769   
770  0 accMD = e.getAccMD();
771   
772  0 if (this.accumulatedHash == null) {
773  0 accumulatedHash = new byte[SAWSConstant.HashLength[this.hashAlgorithm]];
774    }
775   
776  0 accumulatedHash = e.getAccumulatedHash();
777  0 currentRecordWriteCount = e.getSequence();
778  0 secureRandomBytes = secureRandomB;
779   
780  0 String s1 = new String("" + SAWSConstant.LogFileIncompleteErrCode + ";log file is recovered here.");
781  0 try{
782  0 createSAWSRecord( s1.getBytes(), SAWSConstant.SysAuditorNotificationType,
783    (byte) SAWSConstant.USERSAWS, SAWSConstant.NoEncryptionFlag,
784    null) ;
785  0 finalizeLogFile();
786    } catch (Exception e3) {
787  0 if (debugLevel > SAWSConstant.NoInfo)
788    //e3.printStackTrace(System.err);
789    //adding log4j logging
790  0 sawsDebugLog.write(e3.toString());
791  0 return -1;
792    }
793  0 return 0;
794    }
795   
796   
797    /**
798    * This method is called to finalize the log file, i.e. write the accumulated hash and
799    * the signature to the log file.
800    * @param null
801    */
 
802  11 toggle public void finalizeLogFile(){
803  11 if (debugLevel > 0)
804    //System.err.println("\n\t ****************SAWSWriter:finalizeLogfile()******************* \n");
805    //adding log4j logging
806  0 sawsDebugLog.write("\n\t ****************SAWSWriter:finalizeLogfile()******************* \n");
807  11 createSAWSRecord(accumulatedHash, SAWSConstant.SAWSAccumulatedHashType, SAWSConstant.NoEncryptionFlag) ;
808  11 writeSignatureRecord(SAWSConstant.SAWSLogFileSignatureType);
809   
810    // write signature into the log file
811    }
812   
813    /**
814    * This method is called to write a signature record to the log file after initialisation
815    * is finished.
816    *
817    * @param null
818    */
 
819  22 toggle public void writeSignatureRecord(byte signatureType){
820  22 if (debugLevel >= SAWSConstant.VerboseInfo)
821    //System.err.println("\n*********** SAWSWriter:writeSignatureRecord() ******************* \n");
822    //adding log4j logging
823  0 sawsDebugLog.write("\n*********** SAWSWriter:writeSignatureRecord() ******************* \n");
824   
825    // write signature into the log file
826  22 try{
827  22 Signature sig = Signature.getInstance(sawsSigningPrivateKey.getAlgorithm());//signingAlgName);
828   
829  22 sig.initSign(sawsSigningPrivateKey);
830  22 sig.update(accumulatedHash);
831  22 finalSignature = sig.sign();
832  22 createSAWSRecord(finalSignature, signatureType /*SAWSConstant.SAWSLogFileSignatureType*/, SAWSConstant.NoEncryptionFlag);
833    } catch (Exception e){
834  0 if (debugLevel >= SAWSConstant.ErrorInfo)
835    //e.printStackTrace(System.err);
836    //adding log4j logging
837  0 sawsDebugLog.write(e.toString());
838    }
839    }
840   
841    /**
842    * Method to create the callback (SAWSTextOutputCallback) with the message to be
843    * presented to the user and send it to the callback handler.
844    *
845    * @param message The message to be presented.
846    * @param type The type of the message (SAWSTextOutputCallback.WARNING,
847    * SAWSTextOutputCallback.ERROR, SAWSTextOutputCallback.INFORMATION)
848    */
 
849  0 toggle private void showMessage(String message, int type) {
850  0 Callback[] cbs = new Callback[1];
851  0 cbs[0] = new SAWSTextOutputCallback(type, message);
852  0 try {
853  0 this.callbackHandler.handle(cbs);
854    }
855    catch (Exception e) {
856  0 System.err.println(e.getMessage());
857  0 sawsDebugLog.write(e);
858    }
859    }
860    }