iOS开发之Objective-c的AES256加密和解密算法的实现

原文:http://www.lidaren.com/archives/1470
高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法。 以下实现代码中分别为NSData和NSString增加了一个Category。使用时直接调用即可。
需要注意的是,AES并不能作为HASH算法,加密并解密后的结果,并不一定与原文相同,使用时请注意进行结果验算。例如解密原文的长度,格式规则等。 NG实例

原文:170987350
密码:170
Objective-c的AES加密和解密算法的具体实现代码如下: 1.拓展NSData,增加AES256加密方法

 

  1 //
  2 //NSData+AES256.h
  3 //
  4  
  5 #import <Foundation/Foundation.h>
  6 #import <CommonCrypto/CommonDigest.h>
  7 #import <CommonCrypto/CommonCryptor.h>
  8  
  9 @interface NSData(AES256)
 10 -(NSData *) aes256_encrypt:(NSString *)key;
 11 -(NSData *) aes256_decrypt:(NSString *)key;
 12 @end
 13  
 14  
 15 //
 16 //NSData+AES256.m
 17 //
 18 #import "NSData+AES256.h"
 19  
 20 @implementation NSData(AES256)
 21  
 22 - (NSData *)aes256_encrypt:(NSString *)key   //加密
 23 {
 24   char keyPtr[kCCKeySizeAES256+1];
 25   bzero(keyPtr, sizeof(keyPtr));
 26   [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
 27   NSUInteger dataLength = [self length];
 28   size_t bufferSize = dataLength + kCCBlockSizeAES128;
 29   void *buffer = malloc(bufferSize);
 30   size_t numBytesEncrypted = 0;
 31   CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
 32                       kCCOptionPKCS7Padding | kCCOptionECBMode,
 33                       keyPtr, kCCBlockSizeAES128,
 34                       NULL,
 35                       [self bytes], dataLength,
 36                       buffer, bufferSize,
 37                       &numBytesEncrypted);
 38   if (cryptStatus == kCCSuccess) {
 39     return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
 40   }
 41   free(buffer);
 42   return nil;
 43 }
 44  
 45  
 46 - (NSData *)aes256_decrypt:(NSString *)key   //解密
 47 {
 48   char keyPtr[kCCKeySizeAES256+1];
 49   bzero(keyPtr, sizeof(keyPtr));
 50   [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
 51   NSUInteger dataLength = [self length];
 52   size_t bufferSize = dataLength + kCCBlockSizeAES128;
 53   void *buffer = malloc(bufferSize);
 54   size_t numBytesDecrypted = 0;
 55   CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
 56                       kCCOptionPKCS7Padding | kCCOptionECBMode,
 57                       keyPtr, kCCBlockSizeAES128,
 58                       NULL,
 59                       [self bytes], dataLength,
 60                       buffer, bufferSize,
 61                       &numBytesDecrypted);
 62   if (cryptStatus == kCCSuccess) {
 63     return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
 64  
 65   }
 66   free(buffer);
 67   return nil;
 68 }
 69 @end
 70 2.拓展NSString,增加AES256加密方法,需要导入NSData+AES256.h
 71 
 72  
 73 //
 74 //NSString +AES256.h
 75 //
 76  
 77 #import <Foundation/Foundation.h>
 78 #import <CommonCrypto/CommonDigest.h>
 79 #import <CommonCrypto/CommonCryptor.h>
 80  
 81 #import "NSData+AES256.h"
 82  
 83 @interface NSString(AES256)
 84  
 85 -(NSString *) aes256_encrypt:(NSString *)key;
 86 -(NSString *) aes256_decrypt:(NSString *)key;
 87  
 88 @end
 89  
 90  
 91 //
 92 //NSString +AES256.h
 93 //
 94  
 95 @implementation NSString(AES256)
 96  
 97 -(NSString *) aes256_encrypt:(NSString *)key
 98 {
 99   const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
100   NSData *data = [NSData dataWithBytes:cstr length:self.length];
101   //对数据进行加密
102   NSData *result = [data aes256_encrypt:key];
103  
104   //转换为2进制字符串
105   if (result && result.length > 0) {
106  
107     Byte *datas = (Byte*)[result bytes];
108     NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
109     for(int i = 0; i < result.length; i++){
110       [output appendFormat:@"%02x", datas[i]];
111     }
112     return output;
113   }
114   return nil;
115 }
116  
117 -(NSString *) aes256_decrypt:(NSString *)key
118 {   
119   //转换为2进制Data
120   NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
121   unsigned char whole_byte;
122   char byte_chars[3] = {'\0','\0','\0'};
123   int i;
124   for (i=0; i < [self length] / 2; i++) {
125     byte_chars[0] = [self characterAtIndex:i*2];
126     byte_chars[1] = [self characterAtIndex:i*2+1];
127     whole_byte = strtol(byte_chars, NULL, 16);
128     [data appendBytes:&whole_byte length:1];
129   }
130  
131   //对数据进行解密
132   NSData* result = [data aes256_decrypt:key];
133   if (result && result.length > 0) {
134     return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
135   }
136   return nil;
137 }
138 @end

 

转载于:https://www.cnblogs.com/qq744890760/p/5072220.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来解答你的问题。 首先,需要在项目中添加`OpenSSL`库,可以通过`CocoaPods`进行添加,也可以手动添加。 然后,分别实现`AES-GCM`和`AES-ECB`的加密解密操作: ### AES-GCM加密解密 ```objective-c #import <CommonCrypto/CommonCrypto.h> #include <openssl/aes.h> #include <openssl/evp.h> #include <openssl/rand.h> #define kGCMNonceSize 12 // 96 bits #define kGCMTagSize 16 // 128 bits NSData *AESGCMEncrypt(NSData *key, NSData *nonce, NSData *aad, NSData *plainText, NSError **error) { if (nonce.length != kGCMNonceSize) { if (error != NULL) { *error = [NSError errorWithDomain:@"com.example.AESGCMEncrypt" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Invalid nonce size"}]; } return nil; } unsigned char *keyBytes = (unsigned char *)[key bytes]; unsigned char *nonceBytes = (unsigned char *)[nonce bytes]; unsigned char *aadBytes = (unsigned char *)[aad bytes]; unsigned char *plainTextBytes = (unsigned char *)[plainText bytes]; unsigned char tag[kGCMTagSize]; memset(tag, 0, kGCMTagSize); size_t cipherTextLength = plainText.length + kGCMTagSize; unsigned char *cipherTextBytes = malloc(cipherTextLength); memset(cipherTextBytes, 0, cipherTextLength); unsigned char *cipherTextPtr = cipherTextBytes; size_t cipherTextLen = 0; EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)nonce.length, NULL); EVP_EncryptInit_ex(ctx, NULL, NULL, keyBytes, nonceBytes); EVP_EncryptUpdate(ctx, NULL, (int *)&cipherTextLen, aadBytes, (int)aad.length); EVP_EncryptUpdate(ctx, cipherTextPtr, (int *)&cipherTextLen, plainTextBytes, (int)plainText.length); EVP_EncryptFinal_ex(ctx, cipherTextPtr+cipherTextLen, (int *)&cipherTextLen); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, kGCMTagSize, tag); EVP_CIPHER_CTX_free(ctx); NSMutableData *cipherText = [[NSMutableData alloc] initWithBytes:cipherTextBytes length:cipherTextLen+kGCMTagSize]; [cipherText appendBytes:tag length:kGCMTagSize]; free(cipherTextBytes); return cipherText; } NSData *AESGCMDecrypt(NSData *key, NSData *nonce, NSData *aad, NSData *cipherText, NSError **error) { if (nonce.length != kGCMNonceSize) { if (error != NULL) { *error = [NSError errorWithDomain:@"com.example.AESGCMDecrypt" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Invalid nonce size"}]; } return nil; } unsigned char *keyBytes = (unsigned char *)[key bytes]; unsigned char *nonceBytes = (unsigned char *)[nonce bytes]; unsigned char *aadBytes = (unsigned char *)[aad bytes]; unsigned char *cipherTextBytes = (unsigned char *)[cipherText bytes]; unsigned char tag[kGCMTagSize]; memcpy(tag, cipherTextBytes+cipherText.length-kGCMTagSize, kGCMTagSize); size_t plainTextLength = cipherText.length - kGCMTagSize; unsigned char *plainTextBytes = malloc(plainTextLength); memset(plainTextBytes, 0, plainTextLength); unsigned char *plainTextPtr = plainTextBytes; size_t plainTextLen = 0; EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)nonce.length, NULL); EVP_DecryptInit_ex(ctx, NULL, NULL, keyBytes, nonceBytes); EVP_DecryptUpdate(ctx, NULL, (int *)&plainTextLen, aadBytes, (int)aad.length); EVP_DecryptUpdate(ctx, plainTextPtr, (int *)&plainTextLen, cipherTextBytes, (int)plainTextLength); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, kGCMTagSize, tag); int ret = EVP_DecryptFinal_ex(ctx, plainTextPtr+plainTextLen, (int *)&plainTextLen); EVP_CIPHER_CTX_free(ctx); if (ret <= 0) { if (error != NULL) { *error = [NSError errorWithDomain:@"com.example.AESGCMDecrypt" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Decryption failed"}]; } return nil; } NSData *plainText = [[NSData alloc] initWithBytes:plainTextBytes length:plainTextLen]; free(plainTextBytes); return plainText; } ``` 使用示例: ```objective-c NSData *key = [NSData dataWithBytes:"01234567890123456789012345678901" length:32]; NSData *nonce = [NSData dataWithBytes:"012345678901" length:12]; NSData *aad = [@"additional authenticated data" dataUsingEncoding:NSUTF8StringEncoding]; NSData *plainText = [@"plain text" dataUsingEncoding:NSUTF8StringEncoding]; NSError *error = nil; NSData *cipherText = AESGCMEncrypt(key, nonce, aad, plainText, &error); if (cipherText != nil) { NSData *decryptedPlainText = AESGCMDecrypt(key, nonce, aad, cipherText, &error); NSLog(@"Decrypted plain text: %@", [[NSString alloc] initWithData:decryptedPlainText encoding:NSUTF8StringEncoding]); } else { NSLog(@"Encryption failed: %@", error.localizedDescription); } ``` ### AES-ECB加密解密 ```objective-c NSData *AESECBEncrypt(NSData *key, NSData *plainText) { unsigned char *keyBytes = (unsigned char *)[key bytes]; unsigned char *plainTextBytes = (unsigned char *)[plainText bytes]; size_t cipherTextLength = plainText.length + AES_BLOCK_SIZE; unsigned char *cipherTextBytes = malloc(cipherTextLength); memset(cipherTextBytes, 0, cipherTextLength); unsigned char *cipherTextPtr = cipherTextBytes; size_t cipherTextLen = 0; AES_KEY aesKey; AES_set_encrypt_key(keyBytes, (int)(key.length*8), &aesKey); AES_encrypt(plainTextBytes, cipherTextPtr, &aesKey); NSData *cipherText = [[NSData alloc] initWithBytes:cipherTextBytes length:cipherTextLen+AES_BLOCK_SIZE]; free(cipherTextBytes); return cipherText; } NSData *AESECBDecrypt(NSData *key, NSData *cipherText) { unsigned char *keyBytes = (unsigned char *)[key bytes]; unsigned char *cipherTextBytes = (unsigned char *)[cipherText bytes]; size_t plainTextLength = cipherText.length; unsigned char *plainTextBytes = malloc(plainTextLength); memset(plainTextBytes, 0, plainTextLength); unsigned char *plainTextPtr = plainTextBytes; size_t plainTextLen = 0; AES_KEY aesKey; AES_set_decrypt_key(keyBytes, (int)(key.length*8), &aesKey); AES_decrypt(cipherTextBytes, plainTextPtr, &aesKey); NSData *plainText = [[NSData alloc] initWithBytes:plainTextBytes length:plainTextLen]; free(plainTextBytes); return plainText; } ``` 使用示例: ```objective-c NSData *key = [NSData dataWithBytes:"01234567890123456789012345678901" length:32]; NSData *plainText = [@"plain text" dataUsingEncoding:NSUTF8StringEncoding]; NSData *cipherText = AESECBEncrypt(key, plainText); NSData *decryptedPlainText = AESECBDecrypt(key, cipherText); NSLog(@"Decrypted plain text: %@", [[NSString alloc] initWithData:decryptedPlainText encoding:NSUTF8StringEncoding]); ``` 注意:`AES-ECB`加密模式不安全,不建议使用。建议使用`AES-GCM`等更加安全的加密模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值