PDA

View Full Version : help for simple encryption and decryption?




newformac
May 30, 2011, 01:05 AM
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.



SidBala
May 30, 2011, 03:57 AM
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.

Nikh
May 30, 2011, 04:44 AM
Here you can find example of AES encryption for Cocoa: http://stackoverflow.com/questions/2039940/any-cocoa-source-code-for-aes-encryption-decryption

However, as SidBala mentioned, implementing simple XOR will be enough for your purpose.

newformac
May 31, 2011, 12:41 AM
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.

chown33
May 31, 2011, 01:19 PM
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.

Sydde
Jun 1, 2011, 01:01 AM
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

newformac
Jun 1, 2011, 01:24 AM
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:@"~/Desktop/in.htm"];

jiminaus
Jun 1, 2011, 02:15 AM
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:@"~/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:


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 */
}

newformac
Jun 1, 2011, 02:20 AM
yes now its contains 600 bytes.

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

newformac
Jun 1, 2011, 02:28 AM
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...

jiminaus
Jun 1, 2011, 02:30 AM
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.....

SidBala
Jun 1, 2011, 03:30 AM
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.

newformac
Jun 1, 2011, 03:52 AM
when i encrypt and decrypt full file its working fine.


- (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.

jiminaus
Jun 1, 2011, 04:40 AM
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?

newformac
Jun 1, 2011, 04:51 AM
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


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];

jiminaus
Jun 1, 2011, 05:07 AM
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.

newformac
Jun 1, 2011, 05:14 AM
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.

jiminaus
Jun 1, 2011, 06:13 AM
Try and use the following class instead of the transform method.

MyTransformer.h

#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

#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

#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;

}

newformac
Jun 1, 2011, 07:32 AM
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?

jiminaus
Jun 1, 2011, 07:34 AM
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.

holmesf
Jun 1, 2011, 08:47 PM
Just write to / read from your file instead of the memory buffer. The memory buffer was just for testing the transformer.

You guys should be getting paid :)

Mac_Max
Jun 1, 2011, 10:22 PM
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).

jiminaus
Jun 2, 2011, 12:17 AM
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.

newformac
Jun 2, 2011, 01:34 AM
its not properly decrypt the file :

i m applying it like this in my application


//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.

jiminaus
Jun 2, 2011, 01:49 AM
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:

- (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];
}

newformac
Jun 2, 2011, 02:59 AM
thank u so much.

everything is working fine.

but one problem is occurred when i reopen the file after closing previous one and again start writing with encryption.

and same when i restart my application and again trying to encryption/decryption of last saved file.

i m using a WriteEncFile class that is derived from NSObject to write file,here diffrent function for initialize,open,write and close the file.

i m initialize MyTransformer in open function where i open the file,and release it in close function where i close the file.

and executing the these function from different class.

so when i close the file so MyTransformer is release and again initialize when i open the file.

like:



- (void) open
{
mTransformer = [[MyTransformer alloc] initWithKey:@"ABCDEFG"];

mFile = fopen([filename fileSystemRepresentation], "a");

}

- (void) close
{

if (mFile)
{
fclose(mFile);
mFile = NULL;

[mTransformer release];
}
}


now i dont understand now where i m wrong please guide me for this

thanks in advance.

jiminaus
Jun 4, 2011, 05:12 AM
thank u so much.

everything is working fine.

but one problem is occurred when i reopen the file after closing previous one and again start writing with encryption.

and same when i restart my application and again trying to encryption/decryption of last saved file.

i m using a WriteEncFile class that is derived from NSObject to write file,here diffrent function for initialize,open,write and close the file.

i m initialize MyTransformer in open function where i open the file,and release it in close function where i close the file.

and executing the these function from different class.

so when i close the file so MyTransformer is release and again initialize when i open the file.

like:



- (void) open
{
mTransformer = [[MyTransformer alloc] initWithKey:@"ABCDEFG"];

mFile = fopen([filename fileSystemRepresentation], "a");

}

- (void) close
{

if (mFile)
{
fclose(mFile);
mFile = NULL;

[mTransformer release];
}
}


now i dont understand now where i m wrong please guide me for this

thanks in advance.

If you want to append to an encrypted file, you'll need to reinitialise theKeyIndex in MyTransformer to the correct value after you re-open the file.

Firstly remove the reset method in MyTransformer. You don't need it, and it's about to be broken.

Add a new initialiser to MyTransformer and add a declaration for it the header file.

- (id)initWithKey:(NSString *)aKey keyIndex:(NSUInteger)aKeyIndex
{
NSAssert([aKey length] > 0, @"aKey is nil or has zero length");
NSAssert(aKeyIndex >= 0 && aKeyIndex < [aKey length], @"aKeyIndex is out of range");
self = [super init];
if (self) {
theKeyAsUTF8 = [[aKey dataUsingEncoding:NSUTF8StringEncoding] retain];
NSAssert(theKeyAsUTF8, @"failed to encode aKey in UTF-8");
theKeyIndex = aKeyIndex;
}
return self;
}


Change initWithKey: in MyTransformer to:

- (id)initWithKey:(NSString *)aKey
{
return [self initWithKey:aKey keyIndex:0];
}


Then in your open method:

- (void) open
{
mFile = fopen([filename fileSystemRepresentation], "a");
// TODO: Handle error when fopen returns NULL
NSString *key = @"ABCDEFG";
long fileLength = ftell(mFile);
// TODO: Handle error when ftell returns -1
NSUInteger keyIndex = fileLength % [key length];
mTransformer = [[MyTransformer alloc] initWithKey:key keyIndex:keyIndex];
}


This uses the length of the file to calculate what theKeyIndex was before the file was last closed.

newformac
Jun 4, 2011, 06:36 AM
i m so so thankful to u.

:)