Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
636 views
in Technique[技术] by (71.8m points)

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...