美文网首页
IOS 常见加密算法

IOS 常见加密算法

作者: panzhangbao | 来源:发表于2017-06-06 17:28 被阅读194次

    背景

    粗略总结了下几个常用的加密算法,一为方便自己查阅,二为他人参考,如有很 low 或者错误的地方,还望指正
    这里总结的算法有:Base64、MD5、SHA1、HMAC、AES 算法。
    废话少说,开始:

    一、 Base64

    Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一

    /** Base64 加密 */
    - (NSString *)Base64EnCrypt
    {
        NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
        NSString *base64String = [data base64EncodedStringWithOptions:0];
        
        NSLog(@"Base64加密:%@", base64String);
        
        return base64String;
    }
    
    /** Base64 解密 */
    - (NSString *)Base64DeCrypt
    {
        NSData *baseData = [[NSData alloc] initWithBase64EncodedString:self options:0];
        NSString *baseStr = [[NSString alloc] initWithData:baseData encoding:NSUTF8StringEncoding];
        
        NSLog(@"Base64解密:%@", baseStr);
        
        return baseStr;
    }
    

    二、MD5

    MD5加密是最常用的加密方法之一,是从一段字符串中通过相应特征生成一段32位的数字字母混合码。
    MD5主要特点是 不可逆,相同数据的MD5值肯定一样,不同数据的MD5值不一样(也不是绝对的,但基本是不能一样的)。
    MD5算法还具有以下性质:
    1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
    2、容易计算:从原数据计算出MD5值很容易。
    3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
    4、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
    5、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
    MD5虽然说是不可逆的,但是由于有网站http://www.cmd5.com的存在,专门用来查询MD5码 所以有的简单的MD5码是可以在这里搜到源码的。为了让MD5码更加安全 涌现了很多其他方法 如加盐。 盐要足够长足够乱 得到的MD5码就很难查到。

    /** MD5 加密 */
    - (NSString *)MD5
    {
        const char *str = self.UTF8String;
        uint8_t buffer[CC_MD5_DIGEST_LENGTH];
        
        CC_MD5(str, (CC_LONG)strlen(str), buffer);
        
        NSLog(@"MD5加密:%@", [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]);
                            
        return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
    }
    

    三、 SHA

    安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。
    SHA1有如下特性:
    不可以从消息摘要中复原信息;
    两个不同的消息不会产生同样的消息摘要。

    /** SHA1 加密 */
    - (NSString *)SHA1
    {
        const char *str = self.UTF8String;
        uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
        
        CC_SHA1(str, (CC_LONG)strlen(str), buffer);
        
        NSLog(@"SHA1:%@", [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH]);
        
        return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
    }
    
    /** SHA256 加密 */
    - (NSString *)SHA256
    {
        const char *str = self.UTF8String;
        uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
        
        CC_SHA256(str, (CC_LONG)strlen(str), buffer);
        
        NSLog(@"SHA256:%@", [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH]);
        
        return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
    }
    
    /** SHA512 加密 */
    - (NSString *)SHA512
    {
        const char *str = self.UTF8String;
        uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
        
        CC_SHA512(str, (CC_LONG)strlen(str), buffer);
        
        NSLog(@"SHA512:%@", [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH]);
        
        return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
    }
    

    四、HMAC

    HMAC是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法,

    • 以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
    • 作用:
      (1)验证TPM接受的授权数据和认证数据;
      (2)确认TPM接受到的命令请求是已授权的请求,并且,命令在传送的过程中没有被改动过。
    - (NSString *)hmacMD5StringWithKey:(NSString *)key
    {
        const char *keyData = key.UTF8String;
        const char *strData = self.UTF8String;
        uint8_t buffer[CC_MD5_DIGEST_LENGTH];
        
        CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
        
        NSLog(@"HMACMD5:%@", [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]);
        
        return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
    }
    
    /** hmacSHA1 加密 */
    - (NSString *)hmacSHA1StringWithKey:(NSString *)key
    {
        const char *keyData = key.UTF8String;
        const char *strData = self.UTF8String;
        uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
        
        CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer);
        
        NSLog(@"HMACSHA1:%@", [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]);
    
        return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
    }
    
    /** hmacSHA256 加密 */
    - (NSString *)hmacSHA256StringWithKey:(NSString *)key
    {
        const char *keyData = key.UTF8String;
        const char *strData = self.UTF8String;
        uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
        
        CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer);
        
        NSLog(@"HMACSHA256:%@", [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]);
    
        return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
    }
    
    /** hamcSHA512 */
    - (NSString *)hmacSHA512StringWithKey:(NSString *)key
    {
        const char *keyData = key.UTF8String;
        const char *strData = self.UTF8String;
        uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
        
        CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer);
        
        NSLog(@"HMACSHA512:%@", [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH]);
    
        return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
    }
    

    五、AES 加密

    #warning 注意:中文字符暂未处理好
    #pragma mark - AES 加密与解密
    /** AES256 加密 */
    - (NSString *)AES256EnCrypt:(NSString *)key
    {
        // 将字符串转化为 NSData 数据
        const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
        NSData *data = [NSData dataWithBytes:cstr length:self.length];
        
        //对数据进行加密
        char keyPtr[kCCKeySizeAES256 + 1];
        bzero(keyPtr, sizeof(keyPtr));
        [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
        
        NSUInteger dataLength = [data length];
        size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void *buffer = malloc(bufferSize);
        size_t numBytesEncrypted = 0;
        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                              kCCAlgorithmAES128,
                                              kCCOptionPKCS7Padding | kCCOptionECBMode,
                                              keyPtr,
                                              kCCBlockSizeAES128,
                                              NULL,
                                              [data bytes],
                                              dataLength,
                                              buffer,
                                              bufferSize,
                                              &numBytesEncrypted);
        
        if (cryptStatus == kCCSuccess) {
            NSData *baseData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
            
            if (baseData && baseData.length > 0) {
                Byte *datas = (Byte*)[baseData bytes];
                int length = (int)baseData.length;
                NSString *value = [self stringFromBytes:datas length:length];
                [value stringByRemovingPercentEncoding];
                NSLog(@"AES 加密:%@", value);
                
                return value;
            }
        }
        free(buffer);
        
        return nil;
    }
    
    /** AES256 解密 */
    - (NSString *)AES256Decrypt:(NSString *)key
    {
        //转换为2进制Data
        NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
        unsigned char whole_byte;
        char byte_chars[3] = {'\0','\0','\0'};
        int i;
        for (i = 0; i < [self length] / 2; i++) {
            byte_chars[0] = [self characterAtIndex:i*2];
            byte_chars[1] = [self characterAtIndex:i*2+1];
            whole_byte = strtol(byte_chars, NULL, 16);
            [data appendBytes:&whole_byte length:1];
        }
        
        
        char keyPtr[kCCKeySizeAES256 + 1];
        bzero(keyPtr, sizeof(keyPtr));
        [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
        NSUInteger dataLength = [data length];
        size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void *buffer = malloc(bufferSize);
        size_t numBytesDecrypted = 0;
        CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                              kCCAlgorithmAES128,
                                              kCCOptionPKCS7Padding | kCCOptionECBMode,
                                              keyPtr,
                                              kCCBlockSizeAES128,
                                              NULL,
                                              [data bytes],
                                              dataLength,
                                              buffer,
                                              bufferSize,
                                              &numBytesDecrypted);
        if (cryptStatus == kCCSuccess) {
            NSData *baseData = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
            
            if (baseData && baseData.length > 0) {
                NSString *value = [[NSString alloc] initWithData:baseData encoding:NSUTF8StringEncoding];
                NSLog(@"AES 解密:%@", value);
                
                return value;
            }
            
        }
        free(buffer);
        return nil;
    }
    

    参考资料

    si1ence的简书:iOS常见的几种加密方法
    李大仁的博客:iOS开发之Objective-c的AES加密和解密算法的实现

    Github 项目:EncryptionAlgorithm

    相关文章

      网友评论

          本文标题:IOS 常见加密算法

          本文链接:https://www.haomeiwen.com/subject/umcnfxtx.html