docs: function IEncrypt(options){
  	options = options || {};
  	var key = options.key ? new Buffer(options.key) : crypto.randomBytes(32);
  	var debug = options.debug || false;
  	
  	/**
  	 * Encryption method.
  	 * @param data - What to encrypt it can be an object, string or number.
  	 * @return {String} the encrypted text or null on fail
  	 */
  	this.encrypt = function(data){
  		try{
  			//serialize
  			var original = serialize(data);
  			
  			//if serialization failed throw an error
  			if(!original) throw new Error('Invalid type of object given for encryption');
  			
  			//initialization vector
  			var vector = new Buffer(crypto.randomBytes(16));
  			
  			//new cipher
  			var cipher = crypto.createCipheriv('aes256', key, vector);
  			
  			//the encrypted text
  			var encrypted = cipher.update(original,'utf8','base64') + cipher.final('base64');
  			
  			//the signature for the combination of encrypted text and initialization vector
  			var hash = this.sign(encrypted+vector.toString('base64'));
  			
  			//return token ecrypted.vector.hash
  			return encrypted + "." + vector.toString('base64') + "." + hash;
  		}
  		catch(e){
  			if(debug) console.error('An error occured while encrypting : %s',e.stack);
  			return null;
  		}
  	};
  	
  	/**
  	 * Decryption method.
  	 * @param text {String} to encrypt
  	 * @returns {Object} || {String} || {Number} || null on fail
  	 */
  	this.decrypt = function(text){
  		var decipher,
  			original,
  			t,
  			encrypted,
  			vector,
  			hash,
  			new_hash;
  		try{
  			// split text and save each value (encrypted text,vector,hash)
  			t=text.split(".");
  			encrypted = t[0];
  			vector = new Buffer(t[1], 'base64');
  			hash = t[2];
  			
  			//check data integrity by validating signature 
  			if(!this.validate(encrypted+t[1], hash)){
  				throw new Error('Could not verify signature');
  			}
  			
  			//new decipher
  			decipher = crypto.createDecipheriv('aes256', key, vector);
  		    
  			//return the resulted object
  			original = decipher.update(encrypted, 'base64', 'utf8') + decipher.final('utf8');
  			try{
  				return JSON.parse(original);
  			}
  			catch(e){
  				return (!isNaN(parseFloat(original)) && isFinite(original) ? parseFloat(original) : original);
  			}
  		}
  		catch(e){
  			if(debug) console.error('An error occured while decrypting : %s',e.stack);
  			return null;
  		}
  	};
  	
  	/**
  	 * Produce a signature for the given object
  	 * @param data {Object} || {String} || {Number}
  	 * @param format {string} The format of the signature - Default is 'base64'
  	 * @returns {String} the signature or null on fail
  	 */
  	this.sign = function(data, format){
  		try{
  			// Serialize data
  			var serialized = serialize(data);
  			
  			// If not serialized properly throw an Error
  			if(!serialized) throw new Error('Cannot serialize given type of object');
  			
  			// Set formating
  			format = format || 'base64';
  			
  			// Generate and return HMAC
  			return crypto.createHmac('sha256', key).update(serialized).digest(format);
  		}
  		catch(e){
  			if(debug) console.error('An error occured while signing : %s',e.stack);
  			return null;
  		}
  	}
  	
  	/**
  	 * Validate data signature
  	 * @param data  {Object} || {String} || {Number}
  	 * @param signature {String} the produced signature for the data
  	 * @param format {String} format of the signature. Default is 'base64'
  	 * @return {Boolean}
  	 */
  	this.validate = function(data, signature, format){
  		var new_sign = this.sign(data,format);
  		return new_sign?compare(signature,new_sign):false;
  	}
  	
  	/**
  	 * Private serialization method
  	 * @private
  	 * @param data {Object} || {String} || {Number}
  	 * @returns {String} or null on fail
  	 */
  	var serialize = function(data){
  		return typeof data === 'object' 
  			? JSON.stringify(data) 
  			: (typeof data === 'string' || typeof data === 'number' ? String(data) : null);
  	}
  }