17/12/2013

[Java] Hashing with SHA-256

As for the cryptography algorithms, Java offers native libraries for hashing too.

In this example I'll describe how to use apply the SHA-256 hashing to a file. However, following the example found in Coursera's cryptography I course, we won't compute the whole file's hash at once; instead, we'll break the file into 1KB blocks (1024 bytes). Then we'll compute the hash of the last block and appended said value to the second to last block. Then again we'll compute the hash of this augmented second to last block and the resulting hash is appended to the third block from the end, and so on..

Update: Hashing this way doesn't make the hash stronger or weaker, but allows us to stream the file while hashing instead of having to wait for the whole operation to complete.

As usual, auxiliary functions such as string2Hex can be found here.
The basic imports are:
 import java.io.ByteArrayInputStream;  
import java.io.DataInputStream;  
import java.io.File;  
import java.security.MessageDigest;  
import java.util.LinkedList;  
import java.util.List;  
import javax.xml.bind.DatatypeConverter;  
import org.apache.commons.io.FileUtils;  

Also note, we're using Apache commons library to handle our File operations
 public static void sha256() throws Exception{  
      File video = new File("PATH_TO_FILE");//sample video file  
        
      //define the hashing we're using  
      MessageDigest digest = MessageDigest.getInstance("SHA-256");  
        
      //data structures we'll need  
      byte [] videoBytes = FileUtils.readFileToByteArray(video);  
      byte[] hash = null;  
      byte [] myByteArray;  
      byte [] myByteHashArray;  
      //file chunks order is important for our example  
      List chunks = new LinkedList();  
        
      //split the file in 1KB blocks  
      DataInputStream data = new DataInputStream(new ByteArrayInputStream(videoBytes));  
      while(data.available()>0){  
           //read 1024 bytes blocks, if less then read what's left  
           int av = data.available();  
           if(av>1024)myByteArray = new byte[1024];  
           else myByteArray = new byte[av];  
           try{  
                data.readFully(myByteArray);  
                chunks.add(myByteArray);  
           }catch(Exception e){  
                e.printStackTrace();  
           }  
      }  
        
      //start hashing from last chunk  
      for(int i = chunks.size()-1; i>=0; i--){  
           myByteArray = (byte[])chunks.get(i);  
           //new hash is new block+last block hash  
           if(hash!=null){  
                //hash is appended to the new block  
                myByteHashArray = new byte[myByteArray.length + hash.length];//expand the block to host our computed hash at the end  
                //and append it  
                System.arraycopy(myByteArray, 0, myByteHashArray, 0, myByteArray.length);  
                System.arraycopy(hash, 0, myByteHashArray, myByteArray.length, hash.length);  
           }  
           //first block has no previous hash, so no funny extension+appending  
           else myByteHashArray=myByteArray;  
             
           //compute chunk's hash  
           hash = digest.digest(myByteHashArray);  
      }  
        
      String out = DatatypeConverter.printHexBinary(hash);  
      String hexOut=string2Hex(out);  
      String outStr=hex2String(hexOut);  
      //print out the final computed hash  
      System.out.println(outStr);  
 }  

No comments:

Post a Comment

With great power comes great responsibility