iOS加密-AES-PKCS5_PBKDF2_HMAC_SHA1使用

1.公司要求实现AES加密算法,对于java,js及PHP,网上有现成的demo。唯独没有iOS的。气的一笔。没办法只能自己慢慢摸索了。

附上java及JS的实现地址 https://github.com/mpetersen/aes-example (开源项目)

java部分源代码:

private static final int KEY_SIZE = 128;

    private static final int ITERATION_COUNT = 10000;

    private static final String IV = "F27D5C9927726BCEFE7510B1BDD3D137";

    private static final String SALT = "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55";

    private static final String PLAIN_TEXT = "abc";

    private static final String PASSPHRASE = "1234567890";

 

    static void test1() throws Exception

    {

        AesUtil util = new AesUtil(KEY_SIZE,ITERATION_COUNT);

        String encrypt = util.encrypt(SALT, IV, PASSPHRASE, PLAIN_TEXT);

        System.out.println(encrypt);  // 密文: izGCdsKok+u/x3UwTy9fDg==

        String decrypt = util.decrypt(SALT, IV, PASSPHRASE, encrypt);

        System.out.println(decrypt);

    } 

网上搜了一堆demo,但是都不太符合要求。因为网上的demo,都要求key和偏移量是16位字符串。而我们采用的是AES-128-CBC-kCCOptionPKCS5Padding -base64模式,key值的产生由密码和SALT产生。关键的地方是key的产生不是16位的字符串,这就蛋疼了.网上搜了很久,忽然发现openssl已经实现了PKCS5_PBKDF2_HMAC_SHA1加密算法。很开心。

安装openSSL,github上已经有大神已经封装过了(https://github.com/x2on/OpenSSL-for-iPhone)。只需要终端运行响应命令即可。

安装过程:

1.github上下载OpenSSL-for-iPhone

2.运行 ./build-libssl.sh 此过程时间比较长,3-5分钟可以喝杯茶。加载的好像是1.0.2版本。如果要最新的版本加上版本号运行命令./build-libssl.sh --version=1.1.0f。完成后在相应文件夹下。即可看到文件。(如果你在安装的时候发现,相应的目录下面没有相应的文件或者用了相应的文件,不是你本地运行命令建立的文件报了一堆错,或者你安装了多了xcode的导致文件的路径不对,请换一台能用的电脑,创建openssl的文件,然后导入工程中),我当时就是在此处出现了很多问题,以为这个大神封装的库有问题呢,装逼装过头了。后来换了一台电脑,我擦,竟然好了。可能跟我安装了两个xcode有关。

使用步骤:

1.将OpenSSL-for-iPhone文件下include头文件夹copy 到项目中,

2.将lib下的libcrypto.a,libssl.a复制到工程中

3.修改Header Search Paths  设置“$(SRCROOT)/$(PROJECT_NAME)/openssl/include” 设置为recursive;

4.查看build Phases的link Binary with libraries库中是否有libcrypto.a,libssl.a。

5.加入Security.framework库

验证很简单了,commend+B运行一下,不报错,恭喜你openssl已经完成集成。

下面就是AES加密算法的封装了。

实现一个加密方法

+ (NSString *)encryptedDataForData:(NSString *)plainText

                          password:(NSString *)password

                                iv:(NSData *)iv

                              salt:(NSData *)salt

                             error:(NSError *)error;

一个解密方法

+ (NSString *)decryptedDataForData:(NSString *)plainText

                          password:(NSString *)password

                                iv:(NSData *)iv

                              salt:(NSData *)salt

                             error:(NSError *)error  ;

//16进制转换为NSData

+ (NSData*)convertHexStrToData:(NSString*)str;

//NSData转换为16进制

+ (NSString*)convertDataToHexStr:(NSData*)data;

.m文件

定义算法参数

const CCAlgorithm kAlgorithm = kCCAlgorithmAES128;

const NSUInteger kAlgorithmKeySize = kCCKeySizeAES128;

const NSUInteger kAlgorithmBlockSize = kCCBlockSizeAES128;

实现方法

+ (NSData *)AESKeyForPassword:(NSString *)password

                         salt:(NSData *)salt {

    NSMutableData *

    derivedKey = [NSMutableData dataWithLength:kAlgorithmKeySize];

    int result = PKCS5_PBKDF2_HMAC_SHA1(password.UTF8String, (int)[password length],

                                        salt.bytes, (int)[salt length], 10000,

                                        (int)[derivedKey length], derivedKey.mutableBytes);

    NSAssert(result == 1,

             @"Unable to create AES key for password: %d", result);

 

    return derivedKey;

}

+ (NSString *)encryptedDataForData:(NSString *)plainText

                        password:(NSString *)password

                              iv:(NSData *)iv

                            salt:(NSData *)salt

                           error:(NSError *)error {

 

 

    const char *cstr = [plainText cStringUsingEncoding:NSUTF8StringEncoding];

    NSData *data = [NSData dataWithBytes:cstr length:plainText.length];

    NSData *key = [self AESKeyForPassword:password salt:salt];

 

    size_t outLength;

    NSMutableData *

    cipherData = [NSMutableData dataWithLength:data.length +

                  kAlgorithmBlockSize];

 

    CCCryptorStatus

    result = CCCrypt(kCCEncrypt, // operation

                     kAlgorithm, // Algorithm

                     kCCOptionPKCS7Padding, // options

                     key.bytes, // key

                     key.length, // keylength

                     (iv).bytes,// iv

                     data.bytes, // dataIn

                     data.length, // dataInLength,

                     cipherData.mutableBytes, // dataOut

                     cipherData.length, // dataOutAvailable

                     &outLength); // dataOutMoved

 

    if (result == kCCSuccess) {

        cipherData.length = outLength;

    }

    else {

        if (error) {

            error = [NSError errorWithDomain:@"error"

                                         code:result

                                     userInfo:nil];

        }

        return nil;

    }

 

    return [cipherData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];

}

+ (NSString *)decryptedDataForData:(NSString *)plainText

                        password:(NSString *)password

                              iv:(NSData *)iv

                            salt:(NSData *)salt

                           error:(NSError *)error {

    

    NSData *data = [[NSData alloc] initWithBase64EncodedString:plainText options:NSDataBase64DecodingIgnoreUnknownCharacters];

    

//    const char *cstr = [plainText cStringUsingEncoding:NSUTF8StringEncoding];

//    NSData *data = [NSData dataWithBytes:cstr length:plainText.length];

//

    NSData *key = [self AESKeyForPassword:password salt:salt];

    

    size_t outLength;

    NSMutableData *

    cipherData = [NSMutableData dataWithLength:data.length +

                  kAlgorithmBlockSize];

    

    CCCryptorStatus

    result = CCCrypt(kCCDecrypt,

                     kAlgorithm,

                     kCCOptionPKCS7Padding,

                     key.bytes,

                     key.length,

                     (iv).bytes ,

                     data.bytes,

                     data.length,

                     cipherData.mutableBytes,

                     cipherData.length,

                     &outLength);

    

    

    if (result == kCCSuccess) {

        cipherData.length = outLength;

    }

    else {

        if (error) {

            error = [NSError errorWithDomain:@"error"

                                         code:result

                                     userInfo:nil];

        }

        return nil;

    }

    

    return [[NSString alloc] initWithData:cipherData encoding:NSUTF8StringEncoding];

}

 

//16进制转换为NSData

+ (NSData*)convertHexStrToData:(NSString*)str {

    if (!str || [str length] ==0) {

        return nil;

    }

    

    NSMutableData *hexData = [[NSMutableData alloc]initWithCapacity:[str length]*2];

    NSRange range;

    if ([str length] %2==0) {

        range = NSMakeRange(0,2);

    } else {

        range = NSMakeRange(0,1);

    }

    for (NSInteger i = range.location; i < [str length]; i +=2) {

        unsigned int anInt;

        NSString *hexCharStr = [str substringWithRange:range];

        NSScanner *scanner = [[NSScanner alloc]initWithString:hexCharStr];

        

        [scanner scanHexInt:&anInt];

        NSData *entity = [[NSData alloc]initWithBytes:&anInt length:1];

        [hexData appendData:entity];

        

        range.location+= range.length;

        range.length=2;

    }

    //    NSLog(@"hexdata: %@", hexData);

    return hexData;

}

 

//NSData转换为16进制

+ (NSString*)convertDataToHexStr:(NSData*)data {

    if (!data || [data length] ==0) {

        return @"";

    }

    NSMutableString *string = [[NSMutableString alloc]initWithCapacity:[data length]/2];

    

    [data enumerateByteRangesUsingBlock:^(const void*bytes,NSRange byteRange,BOOL*stop) {

        unsigned char *dataBytes = (unsigned  char*)bytes;

        for (NSInteger i =0; i < byteRange.length; i++) {

            NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];

            if ([hexStr length] ==2) {

                [string appendString:hexStr];

            } else {

                [string appendFormat:@"0%@", hexStr];

            }

        }

    }];

    

    return string;

}

创建测试工程viewCtroller中导入头文件。

测试验证

NSString *IV = @"F27D5C9927726BCEFE7510B1BDD3D137";

    NSString *SALT = @"3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55";

    

    NSString *PLAIN_TEXT = @"abcd";

    NSString *PASSPHRASE = @"1234567890";

    NSData *HEX_IV = [AES convertHexStrToData:IV];

    NSData *HEX_SALT = [AES convertHexStrToData:SALT];

    NSString *str =    [AES encryptedDataForData:PLAIN_TEXT password:PASSPHRASE iv:HEX_IV salt:HEX_SALT error:nil];

    NSString *str2 = [AES decryptedDataForData:str password:PASSPHRASE iv:HEX_IV salt:HEX_SALT error:nil];

    NSLog(@"%@===%@",str,str2);

完事。

文章里面有参照别人的代码和方法,为了方便,不做封装了,引用之处往见谅。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值