Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

newformac

macrumors regular
Original poster
May 24, 2011
107
0
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.
 
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.
 
Last edited:
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.

i m new for cocoa can u please provide me any example for this.

i m tankful to u.
 
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.
 
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
 
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"];
 
Last edited by a moderator:
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"];

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 */
}
 
Last edited:
yes now its contains 600 bytes.

now please tell me how can i xor to its each byte.
 
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

can u please explain this with any example...
 
yes now its contains 600 bytes.

now please tell me how can i xor to its each byte.

The XOR operator in Objective-C is ^.

can u please explain this with any example...

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.....
 
Last edited:
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.....

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.
 
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.
 
when i encrypt and decrypt full file its working fine.

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.

How are you writing the bytes out?

How are you reading the bytes in?
 
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];
 
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.
 
Last edited:
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.
 
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;
    
}
 
Last edited:
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?
 
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?


Just write to / read from your file instead of the memory buffer. The memory buffer was just for testing the transformer.
 
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).
 
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).

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.
 
Last edited:
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.
 
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];
}
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.