iOS加密算法总结

常用加密算法


  • DES:Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。
  • DES(数据加密标准)原理:

      DES是一个分组加密算法,它以64位为分组对数据加密。64位一组的明文从算法的一端输入,64位的密文从另一段输出。它是一个对称算法:加密和解密用的是同一个算法。       密钥通常表示为64位的数,但每个第8位都用作奇偶校验,可以忽略,所以密钥长度为56位。密钥可以是任意的56位的数,且可在任意的时候改变。       DES算法只不过是加密的两个基本技术——混乱和扩散的组合,即先代替后置换,它基于密钥作用于明文,这是一轮(round),DES在明文分组上实施16轮相同的组合技术。

      DES现在用的比较少,因为它的加密强度不够,能够暴力破解!!还有一个3DES,原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度,但是要维护3个密钥,大大增加了维护成本!

  • AES:高级加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。高级加密标准已然成为对称密钥加密中最流行的算法之一。
  • AES:高级加密原理:

AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据 的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。Figure 1 显示了 AES 用192位密钥对一个16位字节数据块进行加密和解密的情形。

  • MD5:Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。这个应该是听到最多的算法,据说是已经被破解了。但是我觉得破解这个应该也要很久吧!
  • MD5加密原理:

对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值       目前破解MD5主要依靠大型字典的方法,将常用密码进行MD5后建立数据库,然后和MD5数值进行对比,通过这样的方法来“破解”MD5,因此,通常直接将密码进行MD5处理的话,

      一些弱密码很容易可以通过这种手段“破解”出 来。不过,如果在散列的过程中,加入足够长的salt(即干扰字符串),并且salt加入一些动态信息,例如username、随机码等,

      这样生成的MD5还是很难被破解的,因为仅仅从数据库无法看到MD5具体的处理过程,必须同时看到处理时的源代码才可以,这就给破解MD5带来相当大的难度。

  • Base64:Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一 标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。   
  • RSA 加密方式:

      RSA 加密方式相信每一个对接过支付宝SDK的同学都听过这个RSA加密,因为支付宝SDK的加密方式采用的就是这种。

      它的一个大致额历程是这样:

      1、生成你的公钥给支付宝,注册支付宝SDK之后你也可以拿到支付宝公钥。

      2、上传你的公钥到支付宝,用你的私钥加密你的信息,支付包用你上传的公钥解密你传给支付宝的信息。

      3、用你拿到的支付宝的公钥解密支付宝回调给你的信息。

      注意:不要把这新秘钥信息存放在客户端,存放在服务端也建议不要使用明文的形式存储,安全问题!有些说把秘钥制作成.a文件的形式存放的客户端,问题反编译之后直接拿到你这份.a文件是不是也可以用用呢?

      RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,

      因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

加密模式 


      我们通过下面的两张图解释一下这俩种加密模式,因为在后面的代码解读中我们会涉及到这一点,要是不了解后面代码中有些点可能会犯迷糊:

      ECB:电子密码本,就是每个块都是独立加密的。 

      CBC:密码块链,使用一个密钥和一个初始化向量(IV)对数据执行加密转换。

重点说说它们的代码部分 


   (首先说明DES由于自身的缺陷,就不再去研究看它的代码了,我们这里研究的也不会特别深,主要是为了在项目中的使用)

     先说说这个类: CCCryptorStatus

     关于CCCryptorStatus,构造它可以使用CCCrypt、 CCCryptorCreateWithMode 、CCCryptorCreate等好多类构造,在使用这些类构造时对参数是比较多,我们看着它们的头文件,解读一下参数的含义,我们就用CCCrypt为例说明一下,下面是CCCrypt的结构代码:

CCCryptorStatus CCCrypt(
    CCOperation op,         /* kCCEncrypt, etc. */
    CCAlgorithm alg,        /* kCCAlgorithmAES128, etc. */
    CCOptions options,      /* kCCOptionPKCS7Padding, etc. */
    const void *key,
    size_t keyLength,
    const void *iv,         /* optional initialization vector */
    const void *dataIn,     /* optional per op and alg */
    size_t dataInLength,
    void *dataOut,          /* data RETURNED here */
    size_t dataOutAvailable,
    size_t *dataOutMoved)
    __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);

      理解了它的参数在我们写AES加密代码的时候是有很大的帮助的,下面是它的头文件中Apple给的参数解释,我们解释一下:

 // 设置加密参数
        /*!
         @function   CCCrypt
         @abstract   Stateless, one-shot encrypt or decrypt operation.
         This basically performs a sequence of CCCrytorCreate(),
         CCCryptorUpdate(), CCCryptorFinal(), and CCCryptorRelease().
         
         @param      alg     Defines the encryption algorithm.定义加密的算法
         alg:
         enum {
         kCCAlgorithmAES128 = 0,
         kCCAlgorithmAES = 0,
         kCCAlgorithmDES,
         kCCAlgorithm3DES,
         kCCAlgorithmCAST,
         kCCAlgorithmRC4,
         kCCAlgorithmRC2,
         kCCAlgorithmBlowfish
         };
         
         
         @param      op         Defines the basic operation: kCCEncrypt or kCCDecrypt.  定义加密还是解密
         
         下面是补码方式
         enum {
               kCCOptionPKCS7Padding   = 0x0001,
               kCCOptionECBMode        = 0x0002};
         @param      options    A word of flags defining options. See discussion for the CCOptions type.
         
         // 加密的key
         @param      key        Raw key material, length keyLength bytes.
         // 加密的key的长度
         @param      keyLength  Length of key material. Must be appropriate for the select algorithm. Some algorithms may
         provide for varying key lengths.
         
         
         // IV 向量
         @param      iv          Initialization vector, optional. Used for
                                 Cipher Block Chaining (CBC) mode. If present,
                                 must be the same length as the selected
                                 algorithm's block size. If CBC mode is
                                 selected (by the absence of any mode bits in
                                 the options flags) and no IV is present, a
                                 NULL (all zeroes) IV will be used. This is
                                 ignored if ECB mode is used or if a stream
                                 cipher algorithm is selected. For sound encryption,
                                 always initialize IV with random data.
         
                                 IV向量:大概意思说,此属性可选,但只能用于CBC模式。
                                 如果出现那么他的长度必须和算法的block size保持一致。
                                 如果是因为默认选择的CBC模式而且向量没有定义,那么向量会被定义为NULL。
                                 如果选择了ECB模式或是其他的流密码算法,之前所说的逻辑都不成立。
         
                                 NOTE**** 如果你想使用密钥偏移量IV 那你的加密模式必须为CBC,不能使用别的模式
         
         // 需要加密或者解密处理的data以及data的长度
         @param      dataIn          Data to encrypt or decrypt, length dataInLength bytes.
         @param      dataInLength    Length of data to encrypt or decrypt.
         
         // 加密或者解密后的数据会写在这个data中  以及它的长度
         @param      dataOut         Result is written here. Allocated by caller. Encryption and decryption can be performed "in-place",
                                     with the same buffer   used for input and output.
         @param      dataOutAvailable The size of the dataOut buffer in bytes.
         //
         @param      dataOutMoved    On successful return, the number of bytes written to dataOut.
                                     If kCCBufferTooSmall is returned as a result of insufficient  buffer
                                     space being provided, the required buffer space is returned here.
         //几种错误情况的说明
         @result     kCCBufferTooSmall      indicates insufficent space in the dataOut buffer.(表明dataOut的空间不足) In this case, the *dataOutMoved
                                            parameter will indicate the size of the buffer needed to complete the operation.
                                            The operation can be retried with minimal runtime penalty.
                     kCCAlignmentError      indicates that dataInLength was not properly
                                            aligned. This can only be returned for block
                                            ciphers, and then only when decrypting or when
                                            encrypting with block with padding disabled.
                     kCCDecodeError         Indicates improperly formatted ciphertext or a "wrong key" error; occurs only during decrypt operations.
         
         我们可以通过下面的解释解读一下这个result、具体的结果可以看下面的解释
         @enum       CCCryptorStatus
         @abstract   Return values from CommonCryptor operations.
         enum {
                     kCCSuccess          Operation completed normally.
                     kCCParamError       Illegal parameter value.
                     kCCBufferTooSmall   Insufficent buffer provided for specified operation.
                     kCCMemoryFailure    Memory allocation failure.
                     kCCAlignmentError   Input size was not aligned properly.
                     kCCDecodeError      Input data did not decode or decrypt properly.
                     kCCUnimplemented    Function not implemented for the current algorithm.
         }
         */

AES加密代码


      我们给出的就是具体的AES加密方式的代码,涉及到的其他的Base64编码方式等等这些我们就不在专门去写代码,这个在Demo中都有,需要的建议去翻翻Demo:

- (NSData *)aes256_encrypt:(NSString *)key   //加密
{
    // kCCKeySizeAES256是加密位数
    /*
     enum {
     kCCKeySizeAES128          = 16,
     kCCKeySizeAES192          = 24,
     kCCKeySizeAES256          = 32,
     kCCKeySizeDES             = 8,
     kCCKeySize3DES            = 24,
     kCCKeySizeMinCAST         = 5,
     kCCKeySizeMaxCAST         = 16,
     kCCKeySizeMinRC4          = 1,
     kCCKeySizeMaxRC4          = 512,
     kCCKeySizeMinRC2          = 1,
     kCCKeySizeMaxRC2          = 128,
     kCCKeySizeMinBlowfish     = 8,
     kCCKeySizeMaxBlowfish     = 56,
     };
     */
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    //IV
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void * buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
   
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}


-(NSData *)aes256_decrypt:(NSString *)key   //解密
{
    //key 处理
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    /*IV
     char ivPtr[kCCBlockSizeAES128 + 1];
     bzero(ivPtr, sizeof(ivPtr));
     [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
     */
        
    // 输出对象
    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    
    //kCCDecrypt 解密
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }
    free(buffer);
    return nil;
}

最后:

      针对Base64位的编码方式有的第三方比如:GTMBase64

      或者是针对DES的第三方比如:SSkeychain

      这些网上文章的确比较多了,我们再总结也就没有了什么意义。下面是我参考也是收集的一下关于加密算法的总结,提供给大家。

1、iOS各种加密 Base64 MD5 DES AES RSA 

      2、 iOS中使用RSA加密

      3、iOS中的对称加密算法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏醒者呆

应用密码学初探

关键字:密码学,密码算法,单向哈希函数,对称加密,非对称加密,数字签名,数字证书,Merkle树,同态加密 在计算机科学中,密码学常常用来解决某些特定的难...

4718
来自专栏用户2442861的专栏

Qt学习之路_6(Qt局域网聊天软件)

http://www.cnblogs.com/tornadomeet/archive/2012/07/04/2576355.html

2712
来自专栏desperate633

数字签名和数字证书究竟是什么?

我们经常会见到数字签名和数字证书的身影,比如访问一些不安全的网站时,浏览器会提示,此网站的数字证书不可靠等。那么究竟什么是数字签名和数字证书呢?本文就将通过一个...

1231
来自专栏Android开发实战

Security "Crypto" provider deprecated in Android N

我们知道加密[算法]都是需要密钥的,比如 AES 算法支持128 比特、192 比特和 256 比特三种长度的密钥,通常这些密钥会被转化成字节数组明文写在代码中...

1455
来自专栏蔡卓伦的专栏

深入浅出 HTTPS 工作原理

HTTPS 涉及到了很多概念,比如 SSL/TSL,数字证书、数字签名、加密、认证、公钥和私钥等,比较容易混淆。我们先从一次简单的安全通信故事讲起吧,其中穿插复...

8952
来自专栏技术换美食换不换

TOB服务部署安全模块

1384
来自专栏岑志军的专栏

数据安全及各种加密算法对比

1953
来自专栏web开发

前端AES的加密和解密

在工作的过程中,经常要对一些数据做一些加密,当然有复杂的加密和简单的加密,也有对称加密等等。总之加密的方式有很多。今天在这里,我只是简单的分享一个我最近遇到的加...

1.6K8
来自专栏Keegan小钢

读《图解密码技术》(一):密码

以前,对一些密码技术,虽然懂得怎么用,但对其原理却一直不甚了解,比如,用公钥加密后,为什么用私钥就可以解密?DES和AES加密时为什么需要一个初始化向量?想要了...

2562
来自专栏撸码那些事

【封装那些事】 缺失封装

1603

扫码关注云+社区

领取腾讯云代金券