Forked from eliburke/gist:24f06a1590d572e86a01504e1b38b27f
Created
February 4, 2022 05:11
-
-
Save winterrdog/d49be3bac401cf3aaf08dcb796735e4e to your computer and use it in GitHub Desktop.
Encrypt/Decrypt functions for AES 256 GCM using OpenSSL for iPhone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is 4 year old code, and I have long since switched to PolarSSL | |
// But I have no reason to believe it is not still valid and functional | |
#include <openssl/rand.h> | |
#include <openssl/ecdsa.h> | |
#include <openssl/obj_mac.h> | |
#include <openssl/err.h> | |
#include <openssl/pem.h> | |
#include <openssl/evp.h> | |
#define AES_256_KEY_LENGTH 32 | |
#define AES_256_KEY_LENGTH_BITS 256 | |
#define AES_256_IVEC_LENGTH 12 | |
#define AES_256_GCM_TAG_LENGTH 16 | |
// encrypt plaintext. | |
// key, ivec and tag buffers are required, aad is optional | |
// depending on your use, you may want to convert key, ivec, and tag to NSData/NSMutableData | |
+ (BOOL) aes256gcmEncrypt:(NSData*)plaintext | |
ciphertext:(NSMutableData**)ciphertext | |
aad:(NSData*)aad | |
key:(const unsigned char*)key | |
ivec:(const unsigned char*)ivec | |
tag:(unsigned char*)tag { | |
int status = 0; | |
*ciphertext = [NSMutableData dataWithLength:[plaintext length]]; | |
if (! *ciphertext) | |
return NO; | |
// set up to Encrypt AES 256 GCM | |
int numberOfBytes = 0; | |
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); | |
EVP_EncryptInit_ex (ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); | |
// set the key and ivec | |
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_IVEC_LENGTH, NULL); | |
EVP_EncryptInit_ex (ctx, NULL, NULL, key, ivec); | |
// add optional AAD (Additional Auth Data) | |
if (aad) | |
status = EVP_EncryptUpdate( ctx, NULL, &numberOfBytes, [aad bytes], [aad length]); | |
unsigned char * ctBytes = [*ciphertext mutableBytes]; | |
EVP_EncryptUpdate (ctx, ctBytes, &numberOfBytes, [plaintext bytes], (int)[plaintext length]); | |
status = EVP_EncryptFinal_ex (ctx, ctBytes+numberOfBytes, &numberOfBytes); | |
if (status && tag) { | |
status = EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, AES_256_GCM_TAG_LENGTH, tag); | |
} | |
EVP_CIPHER_CTX_free(ctx); | |
return (status != 0); // OpenSSL uses 1 for success | |
} | |
// decrypt ciphertext. | |
// key, ivec and tag buffers are required, aad is optional | |
// depending on your use, you may want to convert key, ivec, and tag to NSData/NSMutableData | |
+ (BOOL) aes256gcmDecrypt:(NSData*)ciphertext | |
plaintext:(NSMutableData**)plaintext | |
aad:(NSData*)aad | |
key:(const unsigned char *)key | |
ivec:(const unsigned char *)ivec | |
tag:(unsigned char *)tag { | |
int status = 0; | |
if (! ciphertext || !plaintext || !key || !ivec) | |
return NO; | |
*plaintext = [NSMutableData dataWithLength:[ciphertext length]]; | |
if (! *plaintext) | |
return NO; | |
// set up to Decrypt AES 256 GCM | |
int numberOfBytes = 0; | |
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); | |
EVP_DecryptInit_ex (ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); | |
// set the key and ivec | |
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_IVEC_LENGTH, NULL); | |
status = EVP_DecryptInit_ex (ctx, NULL, NULL, key, ivec); | |
// Set expected tag value. A restriction in OpenSSL 1.0.1c and earlier requires the tag before any AAD or ciphertext | |
if (status && tag) | |
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_256_GCM_TAG_LENGTH, tag); | |
// add optional AAD (Additional Auth Data) | |
if (aad) | |
EVP_DecryptUpdate(ctx, NULL, &numberOfBytes, [aad bytes], [aad length]); | |
status = EVP_DecryptUpdate (ctx, [*plaintext mutableBytes], &numberOfBytes, [ciphertext bytes], (int)[ciphertext length]); | |
if (! status) { | |
//DDLogError(@"aes256gcmDecrypt: EVP_DecryptUpdate failed"); | |
return NO; | |
} | |
EVP_DecryptFinal_ex (ctx, NULL, &numberOfBytes); | |
EVP_CIPHER_CTX_free(ctx); | |
return (status != 0); // OpenSSL uses 1 for success | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment