iOS基于openssl 的AES-128-cbc-pkcs5 加解密

来源:互联网 发布:仿站长之家网站源码 编辑:程序博客网 时间:2024/05/16 17:33

前段时间自己写客户端加密解密,查了不少资料。现在把自己写的过程记录下来,分享出去让没写过 openssl aes 的小伙伴少闹点心

闲话不说进入正题 

1.AES加密和DES加密的区别这里就不提了,网上好多解释

2.AES加密的方式有很多 128 256 cbc ecb cfb 等等,这里介绍AES-128-cbc-pkcs5 加解密

你可以写一个公共的加密类 也可以给系统类写一个类的扩展 category

因为我的是给接口参数进行加密 所以我的就给NSString写了一个类扩展,如果你自己要写可根据自己情况写(比如给NSData写一个类扩展)

当时写AES的时候因为好长时间不碰C了,所以开辟空间和初始化的时候经常出问题,还有就是加密解密都是单线程的,所以加上了线程锁

解密的时候,最后不要忘了去除填充

好了不多说了直接上代码

4.AES-128-cbc-pkcs5 加密

-(NSString*)encryptAES:(NSString*)key{    @synchronized (self) {        const char *Source;        unsigned char *InputData=NULL;        unsigned char *EncryptData=NULL;        char *DecryptData=NULL;                unsigned char Key[AES_BLOCK_SIZE+1];//建议用unsigned char        unsigned char iv[17] = "****************";//加密的初始化向量,加密解密要一样就行 因为CBC 是循环加密方式 所以这个地方的加密向量一定要和解密端商量好        AES_KEY AesKey;                int DataLen=0,SetDataLen=0;        NSData *dat = [self dataUsingEncoding:NSUTF8StringEncoding];        Source = [self cStringUsingEncoding:NSUTF8StringEncoding];//要加密的数据        /**     ------------ warning warning warning warning ----------------         *strlen()计算的是char* 的长度,但是如果输入中间包括'\0'字符的话,         *那么只会加密'\0'前面啊的一段,所以这个strlen()在这个地方来计算加密解密长度 欠妥,         *故 以'\0'来判断字符串长度,不符合,这个地方暂时以NSData 的 length 来记录数据长度         *      ------------ warning warning warning warning ----------------         */        DataLen = dat.length;        memset(Key, 0x00, sizeof(Key));        memcpy(Key, [key cStringUsingEncoding:NSUTF8StringEncoding], AES_BLOCK_SIZE);                // set the encryption length        SetDataLen = 0;        if ((DataLen%AES_BLOCK_SIZE) == 0)        {            SetDataLen = DataLen + AES_BLOCK_SIZE;        }        else        {            SetDataLen = ((DataLen/AES_BLOCK_SIZE)+1) * AES_BLOCK_SIZE;        }        printf("SetDataLen:%d...\n", SetDataLen);//取16的倍数                InputData = (unsigned char *)malloc(SetDataLen + 1);        memset(InputData, 0, SetDataLen + 1);//注意要SetDataLen+1        if(InputData == NULL)        {            fprintf(stderr, "Unable to allocate memory for InputData\n");            exit(-1);        }        //计算填充数字        int nNumber;        if (DataLen % 16 > 0)            nNumber = SetDataLen - DataLen;        else            nNumber = 16;        //填充,PKCS5填充的规则 如果加密数据余16大于0 将余数填充到加密数据后面凑成待加密数据长度正好是16的整数倍,如果加密数据余16正好等于0,那么在加密数据后面填充16个16        memset(InputData, nNumber, SetDataLen);        //拷贝资源        memcpy(InputData, Source, DataLen);        //开辟加密后的数据空间        EncryptData = (unsigned char *)malloc(SetDataLen+1);        if(EncryptData == NULL)//注意要SetDataLen+1        {            fprintf(stderr, "Unable to allocate memory for EncryptData\n");            exit(-1);        }        memset(EncryptData, 0, SetDataLen+1);        //设置加密密钥        memset(&AesKey, 0x00, sizeof(AES_KEY));        if(AES_set_encrypt_key(Key, 128, &AesKey) < 0)        {            fprintf(stderr, "Unable to set encryption key in AES...\n");            exit(-1);        }        //加密        AES_cbc_encrypt((unsigned char *)InputData, (unsigned char *)EncryptData,                        SetDataLen, &AesKey, iv, AES_ENCRYPT);        //将加密后的数据转成NSData        NSData *result = [NSData dataWithBytes:EncryptData length:SetDataLen];        //释放内存        if(InputData != NULL)        {            free(InputData);            InputData = NULL;        }                if(EncryptData != NULL)        {            free(EncryptData);            EncryptData = NULL;        }                if(DecryptData != NULL)        {            free(DecryptData);            DecryptData = NULL;        }        //返回base64编码字符串 使用的GTMBase64 如果你不用这个 可以替换成泥自己的Base64编码方式        return [GTMBase64 stringByEncodingData:result];    }        }

5.AES128cbcpkcs5解密

-(NSString*)decryptAESData:(NSString*)key{    @synchronized (self) {        const char *Source;        char *InputData=NULL;        char *EncryptData=NULL;        char *DecryptData=NULL;                unsigned char Key[AES_BLOCK_SIZE+1];//建议用unsigned char        unsigned char iv[17] = <span style="font-family: Arial, Helvetica, sans-serif;">"****************"</span>;//加密的初始化向量,加密解密要一样就行        AES_KEY AesKey;        int DataLen=0,SetDataLen=0, i;        NSData *da = [GTMBase64 decodeString:self];        Source = [[GTMBase64 decodeString:self] bytes];//[self cStringUsingEncoding:NSUTF8StringEncoding];//要解密的数据        DataLen = da.length;        memset(Key, 0x00, sizeof(Key));        memcpy(Key, [key cStringUsingEncoding:NSUTF8StringEncoding], AES_BLOCK_SIZE);                // set the encryption length        SetDataLen = 0;        if ((DataLen%AES_BLOCK_SIZE) == 0)        {            SetDataLen = DataLen;        }        else        {            SetDataLen = ((DataLen/AES_BLOCK_SIZE)+1) * AES_BLOCK_SIZE;        }        if(AES_set_decrypt_key(Key, 128, &AesKey) < 0)        {//设置解密密钥            fprintf(stderr, "Unable to set encryption key in AES...\n");            exit(-1);        }        DecryptData = (char *)calloc(SetDataLen + 16, sizeof(char));        //解密        AES_cbc_encrypt((unsigned char *)Source, (unsigned char *)DecryptData,                        SetDataLen, &AesKey, iv, AES_DECRYPT);                NSData *result = [NSData dataWithBytes:DecryptData length:SetDataLen];                if(InputData != NULL)        {            free(InputData);            InputData = NULL;        }                if(EncryptData != NULL)        {            free(EncryptData);            EncryptData = NULL;        }                if(DecryptData != NULL)        {            free(DecryptData);            DecryptData = NULL;        }        NSString *backStr = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];//        NSLog(@"%@",backStr);        //因为加密的时候进行了填充,所以在这个地方需要去除填充        int c = (int)[backStr characterAtIndex:backStr.length - 1];        NSString *sss = [backStr substringToIndex:backStr.length - c];        NSLog(@"%@",sss);        return sss;    }    }
好了 差不多 AES128cbcpkcs5 加密解密都在上面了


0 0
原创粉丝点击