iOS开发——AES加密(128 CBC/ECB NoPadding/PKCS7Padding)

  项目开发过程中,经常会使用各种加密手段来保证数据的安全性,常见的有MD5,DES,AES等等。摘取百度百科AES词条的简介:AES即高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

  以上可见AES作为一项加密技术使用是很普遍的,博主之前的一个项目跟后台交换数据时就需要使用到AES 128 ECB NoPadding加密,但是苦于网上的关于AES的博客内容大同小异,基本都是AES 128 CBC NoPadding加密,所以纠结了很久。从网上下载下来的AES 128 CBC NoPadding加密方法针对后台数据的加密解密失灵时不灵(后台是ECB模式)。后来自己鼓捣了很长时间总算是弄出来了,网上档下来的方法可以使用,不过需要修改部分代码,让我们先看看网上比较多的AES 128 CBC NoPadding的方法(方法来自博客:http://www.cnblogs.com/wanyakun/p/3403352.html)。

  首先,.h文件:

#import <Foundation/Foundation.h>

@interface AESEnrypt : NSObject

+ (NSString*) AES128Encrypt:(NSString *)plainText;

+ (NSString*) AES128Decrypt:(NSString *)encryptText;

@end

  然后是.m文件:

#import "AESEncrypt.h"
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"

#define gkey @"16位长度的字符串" //自行修改
#define gIv @"16位长度的字符串" //自行修改

@implementation AESEncrypt

+(NSString *)AES128Encrypt:(NSString *)plainText
{
    char keyPtr[kCCKeySizeAES128+1];
    memset(keyPtr, 0, sizeof(keyPtr));
    [gkey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128+1];
    memset(ivPtr, 0, sizeof(ivPtr));
    [gIv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [data length];

    int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
    int newSize = 0;

    if(diff > 0)
    {
        newSize = dataLength + diff;
    }

    char dataPtr[newSize];
    memcpy(dataPtr, [data bytes], [data length]);
    for(int i = 0; i < diff; i++)
    {
        dataPtr[i + dataLength] = 0x00;
    }

    size_t bufferSize = newSize + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    memset(buffer, 0, bufferSize);

    size_t numBytesCrypted = 0;

    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          0x0000,               //No padding
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          dataPtr,
                                          sizeof(dataPtr),
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);

    if (cryptStatus == kCCSuccess) {
        NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
        return [GTMBase64 stringByEncodingData:resultData];
    }
    free(buffer);
    return nil;
}

+(NSString *)AES128Decrypt:(NSString *)encryptText
{
    char keyPtr[kCCKeySizeAES128 + 1];
    memset(keyPtr, 0, sizeof(keyPtr));
    [gkey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128 + 1];
    memset(ivPtr, 0, sizeof(ivPtr));
    [gIv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];

    NSData *data = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];
    NSUInteger dataLength = [data length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesCrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmAES128,
                                          0x0000,
                                          keyPtr,
                                          kCCBlockSizeAES128,
                                          ivPtr,
                                          [data bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
        return [[[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding] autorelease];
    }
    free(buffer);
    return nil;
}

@end

  以上就是最基本的AES 128 CBC Nopadding的加密算法了。如果要使用ECB或者PKCS7Padding模式那么,就需要在.m文件里简单的作出点修改,修改CCCryptorStatus的初始化,如下:

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          0x0000 | kCCOptionECBMode, // 这里添加ECB模式,如果需要PKCS7Padding,那么后面再加上 | kCCOptionPKCS7Padding即可
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          dataPtr,
                                          sizeof(dataPtr),
                                          buffer,
                                          bufferSize,
                                          &numBytesCrypted);

  当然,加密解密里面都需要修改CCCryptorStatus的初始化,保持一致。

  PS:博主在使用自己修改后的AES 128 ECB Nopadding加密方法的时候,遇到一个问题,就是解密之后的字符串末尾会有一长串的‘\0‘结束符,这样导致无法正确解析JSON对象,虽然经过简单处理不影响使用,但是最好还是一步到位最合适,不知有没有大神能帮助解决下这个问题。

时间: 2024-11-10 07:46:15

iOS开发——AES加密(128 CBC/ECB NoPadding/PKCS7Padding)的相关文章

AES加密,CBC模式,0填充

java的aes加密的CBC模式只有NoPadding,PKCS5Padding,PKCS7Padding,因此0填充需要手动更改 public static byte[] encrypt(byte[] data, byte[] iv, byte[] key) { if(key.length != 16) { throw new RuntimeException("Invalid AES key length (must be 16 bytes)"); } else { try { S

ios安全性---AES加密

数据加密在解密在软件开发过程中举足轻重的作用,可能有的公司在加密的时候有自己公司内部一套设计的算法,而在这方面不想浪费太大精力就可以去考虑使用第三方提供的加密算法,如AES加密算法,本篇内容介绍开源中国iOS客户端使用ASE算法加密密码: AES   GitHub 下载地址  https://github.com/Gurpartap/AESCrypt-ObjC 对一个比较大的工程我们可能都不知道某个类库或者方法在哪被使用,但是智能的Xcode给我们提供了一个全局搜索的功能,我们可以在真个工程中来

移动开发---AES加密解密

aes加密解密 ? import android.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * Date: 2019/4/1 * autor:Wayne */ public class AESUtil { private static String key = "123456789&qu

php开发aes加密总结

封装一个类aes类: <?php class aes{ /** * 通过AES加密请求数据 * * @param array $query * @return string */ function AESEncryptRequest($encryptKey, $query){ return $this->encrypt_pass($query,$encryptKey); } // 加密 function encrypt_pass($input, $key) { $size = mcrypt_g

iOS之AES加密解密

//AES加密解密#import <CommonCrypto/CommonCrypto.h>#import <CommonCrypto/CommonDigest.h> //AES128位加密 base64编码 注:kCCKeySizeAES128点进去可以更换256位加密 -(NSString *)AES128Encrypt:(NSString *)plainText key:(NSString *)key { char keyPtr[kCCKeySizeAES128+1];//

iOS开发-MD5加密、SHA1加密

1.MD5加密 ///MD5加密 + (NSString *)md5:(NSString *)inputString{ const char *cStr = [inputString UTF8String]; unsigned char digest[CC_MD5_DIGEST_LENGTH]; CC_MD5( cStr, (int)strlen(cStr), digest ); NSMutableString *output = [NSMutableString stringWithCapac

iOS开发——MD5加密

- (NSString *)md5:(NSString *)str { const char *cStr = [str UTF8String]; unsigned char result[16]; CC_MD5(cStr, (CC_LONG)strlen(cStr), result); return [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"

C#AES加密

今天写个接口,要求如下,需要对应的AES加密(128位),例子php的 C#实现 /// <summary> /// AES 加密 输出hex格式 /// </summary> /// <param name="str">明文(待加密)</param> /// <param name="key">密文</param> /// <returns></returns> pub

IOS 与 PHP 通信加密,使用AES 128 CBC no padding

这个网上的资料真实浩如烟海,但是真正有价值的屈指可数 自己尝试了一天多,终于还是搞定了. 再次要感谢网上的前辈么. 比如下面这个关于php和java端的实现: http://my.oschina.net/Jacker/blog/86383 关于php和java端的实现. 再比如下面这个关于ios端的实现: http://www.cnblogs.com/wanyakun/p/3403352.html 为何要采用 no padding 这种形式: AES加密如果原输入数据不够16字节的整数位,就要补