ios加解密

iOS常用加密方法:

iOS开发过程中,可能会遇到一些信息加密问题。这里提供一些可用的iOS加解密方法。

1 md5加密:最终会得到一个32位的字符串,不可逆;
2 AES128,AES256加解密
AES128/256加解密的性能和选择:http://blog.csdn.net/newizan/article/details/45461347
AES256比AES128加密多耗时40左右,但是经得起暴力破解,AES128据说已经无法抵抗暴力破解。
3 DES加解密
AES与DES加密比较:http://wenku.baidu.com/link?url=m8c8S5vVM29ji4kXaR7tu5gyuNMRa7ekURwY7i0DP-ibCHyUR2VOGRXeSmoWvDot9Bnuj9DB9m0ovXxbbck9jZKR15jKNw-xe_vvJFKO5UK
总之,AES算法汇聚了安全性、效率高、易实现性和灵活性等优点,是一种较DES更好的算法。经过对DES 算法和AES 算法的比较分析,我们可以得出结论, 后者的效率明显高于前者, 而且由于AES 算法的简洁性,使得它的实现更为容易。AES 作为新一代的数据加密标准, 其安全性也远远高于DES 算法。更为重要的是,AES 算法硬件实现的速度大约是软件实现的3倍, 这就给用硬件实现加密提供了很好的机会。

加解密类

此加解密类实现了AES128,AES256和DES三种加密方式,具体选择哪种加密方式可以到.m 文件CCCrypt方法中进行参数修改(第二个参数可能需要相应修改)。
NSData+AES128.h

import <Foundation/Foundation.h>

@interface NSData (AES128)

//加密,kev和iv最多16位
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv;

//解密
- (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv;

@end

NSData+AES128.m

#import "NSData+AES128.h"

#import <CommonCrypto/CommonCrypto.h>

@implementation NSData (AES128)

- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
    return [self AES128Operation:kCCEncrypt key:key iv:iv];
}

- (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv
{
    return [self AES128Operation:kCCDecrypt key:key iv:iv];
}

- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
    //一个char数组,kCCKeySizeAES128 = 16
    char keyPtr[kCCKeySizeAES128 + 1];
    //把数组全部设置为0,
    memset(keyPtr, 0, sizeof(keyPtr));
    //把NSString存放到字符数组里面,字符数组最多是16位
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    //创建一个字符数组,kCCBlockSizeAES128 = 16
    char ivPtr[kCCBlockSizeAES128 + 1];
    //把字符数组全部值为 0
    memset(ivPtr, 0, sizeof(ivPtr));
    //把NSString 放进字符数组里面,最多16位 17位的话,最后一个不晓得要不要存放"\0"
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    //取出要加密的数据的长度
    NSUInteger dataLength = [self length];
    //把该长度加上 kCCBlockSizeAES128 = 16
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    //从内存中开辟一个bufferSize大小的空间,指针给buffer (void *) 任意类型
    void * buffer = malloc(bufferSize);

    //numBytesCrypted 接收加密解密后的数据的长度
    size_t numBytesCrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,//此参数可能由加密参数不同需要相应修改
                                          kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kCCBlockSizeAES128,
//                                          kCCKeySizeAES256,
//                                          kCCKeySize3DES,
                                          ivPtr,
                                          [self bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);
    if (cryptStatus == kCCSuccess)
    {
        //注意,此时的buffer是一个局部变量
        NSData * cryptData=[NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
        //这里的buffer没有free哦
        return cryptData;
    }
    //buffer是malloc出来的,要释放掉
    free(buffer);
    return nil;
}

一般情况下我们在客户端加密数据,在服务器端进行解密,所以我们需要把加密的二进制数据再转化成字符串进行传输(便于传输解析),服务器收到我们传过去的字符串后再转化成加密的二进制数据,再对解析的加密数据的数据解析成正常的数据。
客户端:
123456->正常二进制加密数据->转化成正常字符串如:#klhg@Lifn进行传输

服务器:#klhg@Lifn->转化成正常二进制加密数据->123456

二进制和字符串数据相互转化的类如下:
ZGYBase64Encode.h

#import <Foundation/Foundation.h>

@interface ZGYBase64Encode : NSObject

//nsdata转换成base64编码字符串
+(NSString *)base64StrFromData:(NSData *)data;

//把base64编码的字符串转换成nsdata
+(NSData *)dataFromBase64Str:(NSString *)base64Str;

@end

ZGYBase64Encode.m

#import "ZGYBase64Encode.h"

@implementation ZGYBase64Encode

+(NSString *)base64StrFromData:(NSData *)data{
    return [self encode:(const uint8_t*) data.bytes length:data.length];
}

+(NSData *)dataFromBase64Str:(NSString *)base64Str{
    return [self decode:[base64Str cStringUsingEncoding:NSASCIIStringEncoding] length:base64Str.length];
}


#pragma mark - 具体实现 -
//这是一个静态的char数组,
static char zgyDecodingTable[128];

#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))

+ (void) initialize
{
    //一串char数组,用来初始化efunDecodingTable
    char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    if (self == [ZGYBase64Encode class])
    {
        //把char 数组清零
        memset(zgyDecodingTable, 0, ArrayLength(zgyDecodingTable));
        //利用 encodingTable,循环初始化,efunDecodingTable 数组的一部分char,值是xxx
        for (NSInteger i = 0; i < ArrayLength(encodingTable); i++)
        {
            zgyDecodingTable[encodingTable[i]] = i;
        }
    }
}

+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length
{
    char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    // 声明一个可变的OC数据
    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    //uint8_t 你会发现是一个unsign char;但是,这里还有一个*
    uint8_t * output = (uint8_t*)data.mutableBytes;

    //注意这个循环,每次跳跃仨
    for (NSInteger i = 0; i < length; i += 3)
    {
        NSInteger value = 0;
        for (NSInteger j = i; j < (i + 3); j++)
        {
            value <<= 8;

            if (j < length)
            {
                value |= (0xFF & input[j]);
            }
        }
        NSInteger index = (i / 3) * 4;
        output[index + 0] =                    encodingTable[(value >> 18) & 0x3F];
        output[index + 1] =                    encodingTable[(value >> 12) & 0x3F];
        output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6)  & 0x3F] : '=';
        output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0)  & 0x3F] : '=';
    }
    //他妈,之前没有autorelease,函数返回值,一定记得autorelease,内存不能坑爹有木有
    return [[[NSString alloc] initWithData:data
                                  encoding:NSASCIIStringEncoding]autorelease];
}


+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength
{
    //如果字符串为空,或者长度不是4的整数倍,直接返回空。
    if ((string == NULL) || (inputLength % 4 != 0)) {
        return nil;
    }
    //去掉字符串后面的所有“=”
    while (inputLength > 0 && string[inputLength - 1] == '=') {
        inputLength--;
    }

    NSInteger outputLength = inputLength * 3 / 4;
    NSMutableData* data = [NSMutableData dataWithLength:outputLength];
    uint8_t* output = data.mutableBytes;

    NSInteger inputPoint = 0;
    NSInteger outputPoint = 0;
    while (inputPoint < inputLength)
    {
        char i0 = string[inputPoint++];
        char i1 = string[inputPoint++];
        char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A';
        char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';
        output[outputPoint++] = (zgyDecodingTable[i0] << 2) | (zgyDecodingTable[i1] >> 4);
        if (outputPoint < outputLength)
        {
            output[outputPoint++] = ((zgyDecodingTable[i1] & 0xf) << 4) | (zgyDecodingTable[i2] >> 2);
        }
        if (outputPoint < outputLength)
        {
            output[outputPoint++] = ((zgyDecodingTable[i2] & 0x3) << 6) | zgyDecodingTable[i3];
        }
    }
    return data;
}

@end

使用示例

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *password = @"123456";
    //字符串转换成nsdata
    NSData *pData = [password dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",pData);
    //对pData进行加密得到加密后的nsdata
    NSData *encryptData = [pData AES128EncryptWithKey:@"haha" iv:@"hehe"];
    NSLog(@"%@",encryptData);

    //把加密之后的nsdata进行64编码转换成字符串。解密未使用转化字符串,只是示例
    NSString *encryptStr = [ZGYBase64Encode base64StrFromData:encryptData];
    NSLog(@"%@",encryptStr);
    NSData *thedata = [ZGYBase64Encode dataFromBase64Str:encryptStr];
    NSLog(@"%@",thedata);


    //对encryptData进行解密,得到解密后的nsdata
    NSData *decryptData = [encryptData AES128DecryptWithKey:@"haha" iv:@"hehe"];
    NSLog(@"%@",decryptData);

    NSString *decryptStr = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
    NSLog(@"%@",decryptStr);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值