What is the best way to implement BlowFish ECB encryption in iOS??? I have been googling a lot and found the library here. But there are no documentation of this library. Not sure how to use it.
I got Paul Kocher implementation from Bruce Schneier's website. And here is how an encryption method may look like:
#define PADDING_PHRASE @" "
#import "CryptoUtilities.h"
#import "blowfish.h"
#import "NSData+Base64Utilities.h"
@implementation CryptoUtilities
+ (NSString *)blowfishEncrypt:(NSData *)messageData usingKey:(NSData *)secretKey
{
NSMutableData *dataToEncrypt = [messageData mutableCopy];
if ([dataToEncrypt length] % 8) {
NSMutableData *emptyData = [[PADDING_PHRASE dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
emptyData.length = 8 - [dataToEncrypt length] % 8;
[dataToEncrypt appendData:emptyData];
}
// Here we have data ready to encipher
BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKey bytes], [secretKey length]);
NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;
for (int i = 0; i < [dataToEncrypt length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);
aLeftBox = [dataToEncrypt subdataWithRange:aLeftRange];
aRightBox = [dataToEncrypt subdataWithRange:aRightRange];
// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];
// Encipher
Blowfish_Encrypt(&ctx, &dl, &dr);
// Put bytes back
[dataToEncrypt replaceBytesInRange:aLeftRange withBytes:&dl];
[dataToEncrypt replaceBytesInRange:aRightRange withBytes:&dr];
}
return [dataToEncrypt getBase64String];
}
I am not really good in C, but it seems that my implementation works correctly. To decrypt you need just repeat same steps, but instead of Blowfish_Encrypt you need to call Blowfish_Decrypt.
Here is a source code for that (I assume that you just decrypt the cipher text, but don't deal with padding here):
+ (NSData *)blowfishDecrypt:(NSData *)messageData usingKey:(NSData *)secretKeyData
{
NSMutableData *decryptedData = [messageData mutableCopy];
BLOWFISH_CTX ctx;
Blowfish_Init (&ctx, (unsigned char*)[secretKeyData bytes], [secretKeyData length]);
NSRange aLeftRange, aRightRange;
NSData *aLeftBox, *aRightBox;
unsigned long dl = 0, dr = 0;
for (int i = 0; i< [decryptedData length]; i += 8) { // Divide data into octets...
// …and then into quartets
aLeftRange = NSMakeRange(i, 4);
aRightRange = NSMakeRange(i + 4, 4);
aLeftBox = [decryptedData subdataWithRange:aLeftRange];
aRightBox = [decryptedData subdataWithRange:aRightRange];
// Convert bytes into unsigned long
[aLeftBox getBytes:&dl length:sizeof(unsigned long)];
[aRightBox getBytes:&dr length:sizeof(unsigned long)];
// Decipher
Blowfish_Decrypt(&ctx, &dl, &dr);
// Put bytes back
[decryptedData replaceBytesInRange:aLeftRange withBytes:&dl];
[decryptedData replaceBytesInRange:aRightRange withBytes:&dr];
}
return decryptedData;
}
You might want to return pure bytes or Base64 string. For the last case I have a category, which adds an initialiser, which initialises NSData object with Base64 string and a method, which allows to get Base64 string from NSData.
You should also think about playing with PADDING_PHRASE, for example, what if you want to add not just several spaces, but some random bytes? In this case you should send a padding length somehow.
Update: Actually, you should not use PADDING_PRASE in your process. Instead, you should use one of the standard algorithms for block ciphers described on Wikipedia page
Apple's own CommonCrypto API provides (among other things) a Blowfish implementation. You can encrypt and decrypt in either CBC (the default) or ECB modes.
See CommonCrypto.h, CommonCryptor.h, and the CommonCrypto manpage for documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With