DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

OnePad, RC4 Encrypt/decrypt

07.27.2011
| 1769 views |
  • submit to reddit
        // description of your code here

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;

/**
 * 
 */

/**
 * @author Micheal Vu
 *
 * 9600278
 */
public class cCipherAss {

	/*
	 * Loads file and store in a byte-array
	 * An IOException will be throw if opening file occurred error (file not found, has no reading permission)
	 * @param sFileName The filename (full-path) which will be load.
	 * @return an array of bytes if file-size <   Integer.MAX_VALUE. Otherwise return null
	 */
	private static byte[] loadTextFile( String sFileName) throws IOException{
		File fTmp = new File( sFileName);
		InputStream isFile = new FileInputStream(fTmp);
		long lFileSize = fTmp.length();
		if( lFileSize > Integer.MAX_VALUE){
			// raise error here
		}
		else{
			int iFileSize = (int)lFileSize;
			byte[] buffRet = new byte[iFileSize];
			int iNumberRead =0;
			int iCurrentRead=1;
			while( iCurrentRead >0){
				iCurrentRead = isFile.read(buffRet, iNumberRead, iFileSize-iNumberRead);
				iNumberRead+= iCurrentRead;
			}
			isFile.close();
			return buffRet;
		}
		return null;
	}
	
	/*
	 * Encrypt/Decrypt data by the OnePad Cipher Algorithm. This function uses XOR-bit operator to encrypt/decrypt.
	 * @param bufSrc Source data which want to be encrypted/decrypted.
	 * @param bufKey Key which will be used to encrypt/decrypt
	 * @param iSeg Start-position of source data 
	 * @param iLen The number of bytes which want to be encrypted/decrypted
	 * @return the data after encrypting/decrypting
	 */
	
	private static byte[] encrypOnePadByte( byte[] bufSrc, byte[] bufKey, int iSeg, int iLen){
		byte[] bufRet = null;
		if( iSeg<0 || iLen <0 || iSeg+iLen> bufSrc.length){
			//raise error here
		}
		else{
			bufRet = new byte[ iLen];
			for( int i=iSeg, k=0; i< iLen; i++, k++){
				bufRet[k] =(byte)( bufSrc[i] ^ bufKey[i]);
			}
		}
		return bufRet;
	}

	/*
	 * Encrypt/Decrypt data in file by the OnePad Cipher Algorithm. This function uses XOR-bit operator to encrypt/decrypt.
	 * @param sSrcFile Source data file which want to be encrypted/decrypted.
	 * @param sKeyFile Key file which will be used to encrypt/decrypt. The length of key-file must be greater or equal the one of  source file.
	 * @return filename (full path) which stores the data after encrypting/decrypting (it's will be stored temporary-folder). An empty String will be return if it has any error (read error message at ERR STANDARD OUTPUT).
	 */
	
	public static String encryptOnePadFile( String sSrcFile, String sKeyFile){
		try{
			//missing check existed of files here
			
			File fSrc = new File(sSrcFile);
		
			File fTmp = File.createTempFile(fSrc.getName(), ".enc");
			byte[] bufSrc = loadTextFile(sSrcFile);
			byte[] bufKey = loadTextFile(sKeyFile);
			if( bufKey.length< bufSrc.length){
			// raise error here
			
			}
			else{
				byte[] bufData = encrypOnePadByte(bufSrc, bufKey, 0, bufSrc.length);
				OutputStream osFile = new FileOutputStream(fTmp);
				osFile.write(bufData);
				osFile.close();	
			}
			return fTmp.getAbsolutePath();
		}
		catch( IOException e){
			//raise error here
			System.err.println(e.getMessage());
			return "";
		}	
	}
	
	/*
	 * generates the KSA
	 * @param sKey the key as a seed for key-string generator
	 * @param iLen the length of KSA
	 * @return key-stream (array of byte) 
	 */
	private static byte[] genKSAKeyStream(String sKey, int iLen){
		if( iLen<1|| iLen>256){
			iLen= 256;
		}
		if(sKey== null || sKey.length()==0){
			sKey = "MichealVu";
		}
		byte[] bufKeyStream = new byte[iLen];
		byte[] bufKeySeeder = sKey.getBytes();
		int iSLen = bufKeySeeder.length;
		byte bTmp;
		// init KeyStream
		for( int i=0; i<iLen; i++){
			bufKeyStream[i] = (byte) i;
		}
		//swapping
		for(int i=0, k=0; i<iLen; i++){
			// byte in java is signed-number
			k=(k + bufKeyStream[i]+ bufKeySeeder[i% iSLen]+ iLen) % iLen;
			bTmp = bufKeyStream[i];
			bufKeyStream[i] = bufKeyStream[k];
			bufKeyStream[k] = bTmp;
		}
		return bufKeyStream;
	}
	
	private static final int KS_LEN = 256;
	/*
	 * Encrypt/Decrypt data by the RC4 Cipher Algorithm. This function uses XOR-bit operator to encrypt/decrypt.
	 * @param bufSrc Source data which want to be encrypted/decrypted.
	 * @param sKey key which will be used to generate the key stream
	 * @return the data after encrypting/decrypting
	 */

	private static byte[] encryptRC4Byte( byte[] bufSrc, String sKey){
		byte[] bufRet = null;
		int iLen = bufSrc.length;
		bufRet = new byte[ iLen];
		byte[] bufKeyStream = genKSAKeyStream(sKey, KS_LEN);
		for( int i=0; i< iLen; i++){
				bufRet[i] =(byte)( bufSrc[i] ^ bufKeyStream[i% KS_LEN]);
		}
		return bufRet;
	}

	/*
	 * Encrypt/Decrypt data in file by the RC4 Cipher Algorithm. This function uses XOR-bit operator to encrypt/decrypt.
	 * @param sSrcFile Source data file which want to be encrypted/decrypted.
	 * @param sKey Key String which will be used to generate the key-stream. The length of key-stream is KS_LEN .
	 * @return filename (full path) which stores the data after encrypting/decrypting (it's will be stored temporary-folder). An empty String will be return if it has any error (read error message at ERR STANDARD OUTPUT).
	 */

	public static String encryptRC4File( String sSrcFile, String sKey){
		try{
			//missing check existed of files here
			
			File fSrc = new File(sSrcFile);
		
			File fTmp = File.createTempFile(fSrc.getName(), ".enc");
			byte[] bufSrc = loadTextFile(sSrcFile);
			byte[] bufData = encryptRC4Byte(bufSrc, sKey);
			OutputStream osFile = new FileOutputStream(fTmp);
			osFile.write(bufData);
			osFile.close();	
			return fTmp.getAbsolutePath();
		}
		catch( IOException e){
			//raise error here
			System.err.println( e.getMessage());
			return "";
		}	
		
	}
	/*
	 * Testing encryptOnePadFile function
	 */
	private static void encryptOnePadFileDemo(){
		Scanner in = new Scanner(System.in);
		String sSrcFile, sKeyFile;
		System.out.print("Input Source File:"); sSrcFile = in.nextLine();
		System.out.print("Input Key File:"); sKeyFile = in.nextLine();
		String sFileName = encryptOnePadFile(sSrcFile, sKeyFile);
		System.out.println( "Result file: "+ sFileName);
		
	}

	/*
	 * Testing encryptRC4File function
	 */
	private static void encryptRC4FileDemo(){
		Scanner in = new Scanner(System.in);
		String sSrcFile, sKey;
		System.out.print("Input Source File:"); sSrcFile = in.nextLine();
		System.out.print("Input Key :"); sKey = in.nextLine();
		String sFileName = encryptRC4File(sSrcFile, sKey);
		System.out.println( "Result file: "+ sFileName);
		
	}
	
	private static void encryptRC4ByteDemo(){
		Scanner in = new Scanner(System.in);
		String sMsg, sKey;
		System.out.print("Input Message:"); sMsg = in.nextLine();
		System.out.print("Input Key :"); sKey = in.nextLine();
		byte[] bufData = encryptRC4Byte(sMsg.getBytes(), sKey);
		for(int i=0; i<bufData.length; i++){
			System.out.print(Integer.toHexString(bufData[i]));
		}		
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//encryptOnePadFileDemo();
		encryptRC4FileDemo();
		//encryptRC4ByteDemo();
	}

}