ios ObjectC开发 openssl 实现AES-GCM和AES-ECB加密解密并举例
时间: 2024-01-06 19:07:12 浏览: 275
OpenSSL实现AES的ECB和CBC加解密,可一次性加解密任意长度的明文字符串或字节流(QT C++环境)
好的,我来解答你的问题。
首先,需要在项目中添加`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`等更加安全的加密模式。
阅读全文