help for simple encryption and decryption?

Discussion in 'Mac Programming' started by newformac, May 29, 2011.

  1. macrumors regular

    Joined:
    May 24, 2011
    #1
    hi all,

    i m creating a html file in my application.

    is there any classes in Cocoa for simple file encryption/decryption? I just need something I can point at a file on disk and do simple encryption without a password or key and then decode it later. Doesn't have to be fancy or even all that secure - just something simple and easy to use.

    please help me for this.

    if possible please provide me any example.

    thanks in advance.
     
  2. SidBala, May 30, 2011
    Last edited: May 30, 2011

    macrumors 6502a

    Joined:
    Jun 27, 2010
    #2
    I don't much about cocoa libraries, but I can recommend a few simple methods that you can implement yourself.

    Simplest way I can think of is to reverse the file. What file do you need to encrypt? If it is just html, load it up as a string, then reverse it and save it back. Decryption, do the exact same thing.

    A slightly more complex yet still very simple approach would be to XOR the whole file against a key. Hard code the key if you need to. Decryption, again do the exact same thing to get the original file back.
     
  3. macrumors regular

    Joined:
    Jun 15, 2010
    Location:
    Kyiv
    #3
  4. thread starter macrumors regular

    Joined:
    May 24, 2011
    #4
    i m new for cocoa can u please provide me any example for this.

    i m tankful to u.
     
  5. macrumors 603

    Joined:
    Aug 9, 2009
    #5
    1. Load the file into an NSMutableData.
    2. For each byte of the NSMutableData, XOR it with 0x55.
    3. Write the NSMutableData back to the file.

    This is not a difficult problem. You should read the class reference docs for NSMutableData and NSData. If you can't figure it out, then you probably need to study the fundamentals some more.
     
  6. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #6
    Simple encryption
    • Start with a key of at least 8 bytes (preferably many more)
    • Take the low order 3 bits from the first byte
    • Use that as a skew value to rotate each byte in the key (easier to do in ML than in a language like C)
    • Use the high-order bit of the first byte as your reference starter
    • Now start decomposing the bytes contiguously into fields of 3+ bits, each with odd parity (must not be 0 or all 1s)
    • Starting with the reference bit, scan through the target data in high-to-low bit order
    • Using bit fields that match the widths of the fields taken from the key, record the number of consecutive bits of a given state (all ones or all zeros)
    • Continue using a field until you encounter a number of consecutive bits that matches its value, then begin using the next field
    • Cycle or pogo through the key, perhaps using an elaborate algorithm to conditionally choose direction, until the target data has been converted
    • Maybe add some random-ish bytes to the end

    To decrypt, reverse the process
     
  7. newformac, May 31, 2011
    Last edited by a moderator: May 31, 2011

    thread starter macrumors regular

    Joined:
    May 24, 2011
    #7
    when i m trying to get data of file in NSMutableData its return 0 bytes while file length is 600 bytes.

    NSMutableData* nsdata=[NSData dataWithContentsOfFile:mad:"~/Desktop/in.htm"];
     
  8. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #8
    You can't use ~. Use /Users/whatever/ instead.

    Really you should use the NSSearchPathForDirectoriesInDomains function to get the path of the user's Desktop.

    BTW It's not returning zero bytes. What you've actually got is nsdata being nil. When you send a message to nil, the result is zero. You really need to start putting in error checking and handling code. For example:

    Code:
    NSMutableData* nsdata=[NSData dataWithContentsOfFile:@"/Users/whatever/Desktop/in.htm"];
    if (nsdata == nil) {
       /* Do error handling here, such as report the error */
       /* Don't do any more processing */
    }
    
     
  9. thread starter macrumors regular

    Joined:
    May 24, 2011
    #9
    yes now its contains 600 bytes.

    now please tell me how can i xor to its each byte.
     
  10. thread starter macrumors regular

    Joined:
    May 24, 2011
    #10
    can u please explain this with any example...
     
  11. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #11
    The XOR operator in Objective-C is ^.

    LOL. I love copy'n'paste coders. I wonder if the OP is a copy'n'paste poster, or if this sentence is being typed in again and again and again and.....
     
  12. macrumors 6502a

    Joined:
    Jun 27, 2010
    #12
    Nah. I think he is just a non-native English speaker.

    Basically, XOR is the operator ^

    So, for every byte in your file, you do:

    encryptedbyte = databyte ^ key;

    again, I am not not familiar with Cocoa classes, so I don't know how you exactly would access individual bytes from the data object. But that would be a very easy look up on the docs.
     
  13. thread starter macrumors regular

    Joined:
    May 24, 2011
    #13
    when i encrypt and decrypt full file its working fine.

    Code:
    - (void)transform:(NSData *)input
    {
    	NSString* key = @"ABCDEFG";
    	unsigned char* pBytesInput = (unsigned char*)[input bytes];
    	unsigned char* pBytesKey   = (unsigned char*)[[key dataUsingEncoding:NSUTF8StringEncoding] bytes];
    	unsigned int vlen = [input length];
    	unsigned int klen = [key length];
    	unsigned int v = 0;
    	unsigned int k = vlen % klen;
    	unsigned char c;
    	
    	for (v; v < vlen; v++)
    	{
    		c = pBytesInput[v] ^ pBytesKey[k]; 
    		pBytesInput[v] = c;
    		
    		k = (++k < klen ? k : 0);
    	}
    }
    
    but in my app i write file line by so i encrypt the string that is ready to written in file and after completion trying to decrypt this but its not decrypt in correct format as input.
     
  14. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #14
    How are you writing the bytes out?

    How are you reading the bytes in?
     
  15. thread starter macrumors regular

    Joined:
    May 24, 2011
    #15
    Code:
    
    NSString fmt;
    
     // Find amount of arguments
      va_start(vl, fmt);
      NSString* msg = [[NSString alloc] initWithFormat:fmt arguments: vl];
      va_end(vl);
      
      // Get UTF8 string from msg
      NSData* msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
      if (msgData)
      {
    	  // 'encrypt', the 'data' buffer is transformed in-place.
    	  [self transform:msgData];
    
        fwrite([msgData bytes], [msgData length], 1, mFile); 
        //[mOutputStream write: (uint8_t*)[msgData bytes] maxLength:[msgData length]];
      
      }  
    	fflush(mFile);
    
    write like this whenever application have any data that has to written in file.

    and at reading time

    Code:
    NSMutableData* ns_data=[NSData dataWithContentsOfFile:@"written file
    "];
    	if (ns_data == nil)
    	{
    		/* Do error handling here, such as report the error */
    		/* Don't do any more processing */
    	}
    	
    	
        [self transform:ns_data];
    	
        
        [ns_data writeToFile:@"new decrypt file." atomically:YES];
    
     
  16. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #16
    The transform algorithm you're using depends on the length of the string. You can't encrypt line-by-line, and then decrypt as a single chunk. Either read and decrypt line-by-line, or buffer the output unencrypted then encrypt and write as a single chunk and then you'll be able to read and decrypt as a single chunk.

    BTW You're not supposed to modify the bytes returned by the bytes method of an NSData object. If you want to modify the bytes, you're meant to have an NSMutableData object and use the mutableBytes method. If you have an NSData object, call the mutableCopy method to get an NSMutableData object.
     
  17. thread starter macrumors regular

    Joined:
    May 24, 2011
    #17
    please help me how can i do this?

    in my app writing process is not possible in single chunk.

    please help me wat can i do in this situation,

    file has to be written by apps as it received any data to be written .

    and when i want to view this file using app now i need to decrypt the file and open file in correct and readable format.

    please help me for this.

    thanks in advance.
     
  18. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #18
    Try and use the following class instead of the transform method.

    MyTransformer.h
    Code:
    #import <Foundation/Foundation.h>
    
    @interface MyTransformer : NSObject
    {
    @private
        NSData *theKeyAsUTF8;
        NSUInteger theKeyIndex;
    }
    
    - (id)initWithKey:(NSString *)aKey;
    
    - (void)reset;
    
    - (NSData *)transform:(NSData *)anInput;
    - (void)transformInPlace:(NSData *)aDataBuffer;
    
    @end
    
    MyTransfomer.m
    Code:
    #import <Foundation/Foundation.h>
    #import "MyTransformer.h"
    
    
    
    @implementation MyTransformer
    
    - (id)init
    {
        [self release];
        NSException *err =
            [NSException exceptionWithName:@"MyMethodNotSupportedException"
                                    reason:@"init: on MyTransformer is not supported, use initWithKey: instead"
                                  userInfo:[NSDictionary dictionary]];
        @throw err;
    }
    
    
    - (id)initWithKey:(NSString *)aKey
    {
        NSAssert([aKey length] > 0, @"aKey is nil or has zero length");
        self = [super init];
        if (self) {
            theKeyAsUTF8 = [[aKey dataUsingEncoding:NSUTF8StringEncoding] retain];
            NSAssert(theKeyAsUTF8, @"failed to encode aKey in UTF-8");
            [self reset];
        }
        return self;
    }
    
    
    - (void)dealloc
    {
        [theKeyAsUTF8 release];
        [super dealloc];
    }
    
    
    - (void)reset
    {
        theKeyIndex = 0;
    }
    
    
    - (NSData *)transform:(NSData *)anInput
    {
        if ([anInput length] == 0) return anInput;
        NSMutableData *aDataBuffer = [[anInput mutableCopy] autorelease];
        NSAssert(aDataBuffer, @"failed to create a mutable copy of anInput");
        [self transformInPlace:aDataBuffer];
        return aDataBuffer;
    }
    
    
    - (void)transformInPlace:(NSMutableData *)aDataBuffer;
    {
        if ([aDataBuffer length] == 0) return;
        uint8_t *dataBufferBytes = [aDataBuffer mutableBytes];
        const uint8_t *keyBytes = [theKeyAsUTF8 bytes];
        const NSUInteger vlen = [aDataBuffer length];
        const NSUInteger klen = [theKeyAsUTF8 length];
        NSUInteger k = theKeyIndex;
        for (NSUInteger v = 0; v < vlen; v++) {
            uint8_t c = dataBufferBytes[v] ^ keyBytes[k]; 
            dataBufferBytes[v] = c;		
            k = (k + 1) % klen;
        }
        theKeyIndex = k;
    }
    
    @end
    
    Basically what I've done is move your transform: method into the transformInPlace: method of this new MyTransformer class. The reason I did this was to move k in your transform: method outside of it (called theKeyIndex) so it can be saved between calls to transformInPlace: as you encrypt each chunk. This way after the chunks are concatenated into your file, they can be decrypted as a single chunk.

    I refactored the key parameter of your transform: method out into an instance variable of MyTransformer so it can be used across calls to transformInPlace:. I optimised by storing only the UTF8 encoding of the key (in theKeyAsUTF8) as need by transformInPlace:.

    Note that transformInPlace takes an NSMutableData object. There's also a transform method which takes an NSData object. NSData objects are read-only (immutable), so it returns another auto-released NSData object containing the transformed data.

    Finally there's a reset method that can be used to reset the transformer if you want to reuse it between writing and reading, or between writing/reading different files using the same key.

    The general usage of this class is to alloc and then call initWithKey: passing in the key. Then call transform: and/or transformInPlace: as necessary.

    Below is an example main which uses the class. It encrypts lines into a memory buffer as small chunks and then decrypts the whole buffer as a single chunk.

    main.m
    Code:
    #import <Foundation/Foundation.h>
    #import "MyTransformer.h"
    
    
    
    int main (int argc, const char *argv[])
    {
        
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        
        NSArray *startLines =
            [NSArray arrayWithObjects:
                @"Hello world\n",
                @"Second line\n",
                @"Third line\n",
                @"Last line\n",
                nil];
    
        MyTransformer *transformer = 
            [[MyTransformer alloc] 
                initWithKey:@"ABCDEFG"];    
        
        /* Simmulate writing by writing out the lines into a memory buffer */
        NSOutputStream *outputStream = [NSOutputStream outputStreamToMemory];
        [outputStream open];
    
        for (NSString *line in startLines) {
            NSData *lineAsUTF8 = [line dataUsingEncoding:NSUTF8StringEncoding];
            NSData *encryptedLine = [transformer transform:lineAsUTF8];
            [outputStream write:[encryptedLine bytes] 
                      maxLength:[encryptedLine length]]; 
        }
        
        [outputStream close];
        
        
        /* Simulate reading by gets the pointer to the memory buffer */
        NSData *encryptedBytes = 
            [outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
        
        [transformer reset];
        NSData *decryptedBytes = [transformer transform:encryptedBytes];
        NSString *decryptedString = 
            [[NSString alloc] 
                    initWithData:decryptedBytes 
                        encoding:NSUTF8StringEncoding];
        
        NSLog(@"%@", decryptedString);
        
        
        [decryptedString release];
        [transformer release];
        
        
        [pool drain];
        return 0;
        
    }
    
     
  19. thread starter macrumors regular

    Joined:
    May 24, 2011
    #19
    thanks its working fine.

    but what about my files?i can't write every thing in memory buffer it can be too long.

    how can do this with file reading writing?
     
  20. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #20

    Just write to / read from your file instead of the memory buffer. The memory buffer was just for testing the transformer.
     
  21. macrumors 6502a

    Joined:
    Sep 30, 2001
    #21
    You guys should be getting paid :)
     
  22. macrumors 6502

    Joined:
    Mar 8, 2004
    #22
    I think the guy genuinely wants to learn and this isn't a "please do my homework for me" thread. He provided source code he cooked up himself after all ;). It's helpful to have a mentor (or forum of them).
     
  23. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #23
    But this is the first time he's done it. Every other time, including this thread, his response to every suggestion was "please explain with an example". I don't think I'm unreasonable is reading into it that he's fishing for code and isn't willing to actually working through writing the code himself. In fact his last post to this thread reaffirms this opinion to my books.
     
  24. thread starter macrumors regular

    Joined:
    May 24, 2011
    #24
    its not properly decrypt the file :

    i m applying it like this in my application

    Code:
    //i m using this function to write file whenever applications write something in file.
    
    - (void) write_file: (NSString*)fmt, ...
    {
      if (!mFile)
        return;
      
      if (mIdleLogged)
        return;
      
      
      va_list vl;
      
      // Find amount of arguments
      va_start(vl, fmt);
      NSString* msg = [[NSString alloc] initWithFormat:fmt arguments: vl];
      va_end(vl);
      
      // Get UTF8 string from msg
      NSData* msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
      if (msgData)
      {
    	  //---------Encrypt Log Data--------------------------------
    	 
    	   //[self transform:msgData];
    	  
    	  MyTransformer *transformer = [[MyTransformer alloc] initWithKey:@"ABCDEFG"];
    
    	  [transformer reset];
    	  
    	  NSData *encryptedLine = msgData = [transformer transform:msgData];
    	  
    	  fwrite([encryptedLine bytes], [encryptedLine length], 1, mFile);
    	  
    	 //---------/Encrypt Log Data--------------------------------
    	  
       
      
      }  
    	fflush(mFile);
      
    }
    
    //and using below to create decrypted file from the encrypted file.
    
    MyTransformer *transformer = [[MyTransformer alloc] initWithKey:@"ABCDEFG"];
    		
    NSString * days_file_str=[NSString stringWithContentsOfFile:[[mLogFile filename] stringByExpandingTildeInPath]];
    NSData* ns_data=[NSData dataWithContentsOfFile:[mLogFile filename]];
    				
    [transformer reset];
    		
    NSData *decryptedBytes_1 = [transformer transform:ns_data];
    NSString *decryptedString_1 = [[NSString alloc] initWithData:decryptedBytes_1 encoding:NSUTF8StringEncoding];
    			    		
    [decryptedBytes_1 writeToFile:@"/Users/Desktop/new_log.htm" atomically:YES];
    		
    NSString * str2=[NSString stringWithContentsOfFile:[@"/Users/Desktop/new_log.htm" stringByExpandingTildeInPath]];
    NSData* d2=[NSData dataWithContentsOfFile:@"/Users/Desktop/new_log.htm"];
    
    
    now please guide me where i m wrong?

    thanks in advance.
     
  25. jiminaus, Jun 1, 2011
    Last edited: Jun 1, 2011

    macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #25
    When you write, you need a single MyTransformer that you reuse across calls to write_file.

    Add MyTransformer *mTransformer to the class's instance variables.

    Wherever mFile is being opened, allocate and initialize mTransformer.

    Wherever mFile is being closed, release mTransformer.

    Then write_file becomes:
    Code:
    - (void) write_file: (NSString*)fmt, ...
    {
      if (!mFile)
        return;
      
      if (mIdleLogged)
        return;
      
      
      va_list vl;
      
      // Find amount of arguments
      va_start(vl, fmt);
      NSString* msg = [[NSString alloc] initWithFormat:fmt arguments: vl];
      va_end(vl);
      
      // Get UTF8 string from msg
      NSData* msgData = [msg dataUsingEncoding:NSUTF8StringEncoding];
      if (msgData)
      {
    	  //---------Encrypt Log Data--------------------------------
    	 
    	  //[self transform:msgData];
    	  	  
    	  NSData *encryptedLine = [mTransformer transform:msgData];
    	  
    	  fwrite([encryptedLine bytes], [encryptedLine length], 1, mFile);
    	  
    	 //---------/Encrypt Log Data--------------------------------  
      }
      fflush(mFile);
      [msg release];
    }
    
     

Share This Page