Ratikanta Patra
Ratikanta Patra

Reputation: 1177

How to implement Blowfish algorithm in iOS

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.

Upvotes: 6

Views: 6443

Answers (3)

Can Tecim
Can Tecim

Reputation: 587

I've written a native implementation for blowfish algorithm since there was no implementation to fit my needs some time ago

Maybe this is an old question but i want to help someone who needs a native class for blowfish algorithm.

Its works fully compatible with PHP

An Objective-C Blowfish Implementation

  • Supports EBC and CBC mode
  • Supports padding RFC and Zero padding
  • Works compatible with PHP's Mcrypt
  • Originally coded for iOS SDK. It may work also for OS X SDK

More on github;

https://github.com/cantecim/FclBlowfish

Upvotes: 2

Peter Hosey
Peter Hosey

Reputation: 96333

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.

Upvotes: 2

Stas
Stas

Reputation: 641

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

Upvotes: 5

Related Questions