我试图在objective c中加密/解密一个AES-128 GCM格式的字符串。我到处都找过了,但似乎找不到有效的解决方案。
/*
typical GCM use case: sending an authenticated packet
+--------------+-------+--------------+
| header | seq. | Data |
+--------------+-------+--------------+
| | |
| | |
Addtl auth data IV plain text
| | |
| | V
| | +--------------------+
| +---->| |
| | | GCM encryption |
+---------------->| |
| | +--------------------+
| | | |
| | cipher text Auth tag
| | | |
V V V V
+--------------+-------+----------------+---------+
| header | seq. | encrypted data | ICV |
+--------------+-------+----------------+---------+
*/
#define CCCryptorGCMprologue() CCCryptor *cryptor = getRealCryptor(cryptorRef, 0); \
CC_DEBUG_LOG("Entering\n"); \
if(!cryptor) return kCCParamError;
static inline CCCryptorStatus translate_err_code(int err)
{
if (err==0) {
return kCCSuccess;
} /*else if(err == CCMODE_INVALID_CALL_SEQUENCE){ //unti we can read error codes from corecrypto
return kCCCallSequenceError;
} */ else {
return kCCUnspecifiedError;
}
}
CCCryptorStatus
CCCryptorGCMAddIV(CCCryptorRef cryptorRef,
const void *iv,
size_t ivLen)
{
CCCryptorGCMprologue();
if(ivLen!=0 && iv==NULL) return kCCParamError;
//it is okay to call with ivLen 0 and/OR iv==NULL
//infact this needs to be done even with NULL values, otherwise ccgcm_ is going to return call sequence error.
//currently corecrypto accepts NULL
//rdar://problem/23523093
int rc = ccgcm_set_iv_legacy(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, ivLen, iv);
return translate_err_code(rc);
}
//Add additional authentication data
CCCryptorStatus
CCCryptorGCMAddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
CCCryptorGCMprologue();
if(aDataLen!=0 && aData==NULL) return kCCParamError;
//it is okay to call with aData zero
int rc = ccgcm_gmac(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, aDataLen, aData);
return translate_err_code(rc);
}
// This is for old iOS5 clients
CCCryptorStatus
CCCryptorGCMAddADD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
// This was a temp mistake in MacOSX8
CCCryptorStatus
CCCryptorGCMaddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
//we are not providing this function to users.
//The reason is that we don't want to create more liability for ourself
//and a new interface function just increases the number of APIs
//without actually helping users
//User's use the old CCCryptorGCMEncrypt() and CCCryptorGCMDecrypt()
static CCCryptorStatus gcm_update(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
CCCryptorGCMprologue();
if(dataInLength!=0 && dataIn==NULL) return kCCParamError;
//no data is okay
if(dataOut == NULL) return kCCParamError;
int rc = ccgcm_update(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef,
const void *dataIn,
size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef,
void *tagOut,
size_t *tagLength)
{
CCCryptorGCMprologue();
if(tagOut == NULL || tagLength == NULL) return kCCParamError;
int rc = ccgcm_finalize(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, *tagLength, (void *) tagOut);
if(rc == -1)
return kCCUnspecifiedError;
else
return kCCSuccess; //this includes 0 and any error message other than -1
// ccgcm_finalize() returns CCMODE_INTEGRITY_FAILURE (-3) if the expected tag is not coppied to the buffer. but that doesn't mean there is an error
}
CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef)
{
CCCryptorGCMprologue();
int rc = ccgcm_reset(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCM(CCOperation op, /* kCCEncrypt, kCCDecrypt */
CCAlgorithm alg,
const void *key, size_t keyLength, /* raw key material */
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
void *tagOut, size_t *tagLength)
{
CCCryptorRef cryptorRef;
CCCryptorStatus retval;
CC_DEBUG_LOG("Entering Op: %d Cipher: %d\n", op, alg);
retval = CCCryptorCreateWithMode(op, kCCModeGCM, alg, 0, NULL, key, keyLength,
NULL, 0, 0, 0, &cryptorRef);
if(retval) return retval;
//call even with NULL pointer and zero length IV
retval = CCCryptorGCMAddIV(cryptorRef, iv, ivLen);
if(retval) return retval;
retval = CCCryptorGCMaddAAD(cryptorRef, aData, aDataLen);
if(retval) return retval;
retval = gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
if(retval) return retval;
retval = CCCryptorGCMFinal(cryptorRef, tagOut, tagLength);
CCCryptorRelease(cryptorRef);
return retval;
}
不久前,我也遇到过类似的问题,我能找到的最好答案是这个。总而言之,iOS有一些功能可以做你想做的事,但它们是私人的。
因此,在Apple决定发布这些功能之前,我选择开发自己的库,该库目前存储在GitHub中,可在CocoaPods中使用。
您描述的案例可以这样实现:
#import <CommonCrypto/CommonCrypto.h>
#import "IAGAesGcm.h"
// For the case you describe, the key length is 128 bits (16 bytes)
u_char keyBytes[kCCKeySizeAES128] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
NSData *key = [NSData dataWithBytes:keyBytes length:sizeof(keyBytes)];
// GCM recommends a IV size of 96 bits (12 bytes), but you are free
// to use other sizes
u_char ivBytes[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
NSData *iv = [NSData dataWithBytes:ivBytes length:sizeof(ivBytes)];
NSData *aad = [@"AdditionalAuthenticatedData" dataUsingEncoding:NSUTF8StringEncoding];
// Authenticated Encryption Function
NSData *expectedPlainData = [@"PlainData" dataUsingEncoding:NSUTF8StringEncoding];
// The returned ciphered data is a simple class with 2 properties: the actual encrypted data and the authentication tag.
// The authentication tag can have multiple sizes and it is up to you to set one, in this case the size is 128 bits
// (16 bytes)
IAGCipheredData *cipheredData = [IAGAesGcm cipheredDataByAuthenticatedEncryptingPlainData:expectedPlainData
withAdditionalAuthenticatedData:aad
authenticationTagLength:IAGAuthenticationTagLength128
initializationVector:iv
key:key
error:nil];
// Authenticated Decryption Function
NSData *plainData = [IAGAesGcm plainDataByAuthenticatedDecryptingCipheredData:cipheredData
withAdditionalAuthenticatedData:aad
initializationVector:iv
key:key
error:nil];
XCTAssertEqualObjects(expectedPlainData, plainData);
希望这段代码有任何帮助。
最后(感谢zaph提到这一点),我没有对这段代码进行任何基准测试,所以假设它很慢。我打算用它来破译JWE字符串中的符号,只是偶尔,我不推荐任何比这要求更高的东西。
问候。
关于Target 在Glide中,Target 是介于请求和请求者之间的中介者的角色。Target 负责展示占位符,加载资源,并为每个请求决定合适的尺寸。被使用得最频繁的是 ImageViewTargets ,它用于在 ImageView 上展示占位符、Drawable 和 Bitmap 。用户还可以实现自己的 Target ,或者从任何可用的基类派生子类。 指定目标 into(Target) 方
youbest兄的大作《5M大小的Apache服务器》和其续篇《600K的Apache服务器》将LFS的精神发挥到了极致,令人叹为观止!然而许多实用主义者(包括我在内)也只能叹为观止而已,因为这样的服务器由于过分追求小巧而变得不太实用,基本上不能在实践中用于生产目的。 鉴于上述原因,本文打算制作一个既实用又小巧的 Linux + Apache + PHP + PostgreSQL + OpenSS
设计和架构目标 CodeIgniter 的目标是在最小化,最轻量级的开发包中得到最大的执行效率、功能和灵活性。 为了达到这个目标,我们在开发过程的每一步都致力于基准测试、重构和简化工作,拒绝加入任何对实现目标没有帮助的东西。 从技术和架构角度看,CodeIgniter 按照下列目标创建: 动态实例化。在 CodeIgniter 中,组件的导入和函数的执行只有在被要求的时候才执行,而不是在全局范围。
我们将在已有的例子中创建一个新的Activity。这个Activity将通过StackExchange API从stackoverflow检索出最活跃的10位用户。App使用这些信息来展示一个包含用户头像、姓名、名望数以及住址的列表。对每一位用户,app使用OpenWeatherMap API来检索该用户住址当地的天气预报,并显示一个小天气图标。基于从StackOverflow检索的信息,app对
了解图是什么,以及如何使用它。 使用多个内部表示来实现图抽象数据类型。 看看如何使用图来解决各种各样的问题 在本章中,我们将研究图。图是比我们在上一章中研究的树更通用的结构;实际上你可以认为树是一种特殊的图。图可以用来表示我们世界上许多有趣的事情,包括道路系统,从城市到城市的航空公司航班,互联网如何连接,甚至是完成计算机科学专业必须完成的课程顺序。我们将在本章中看到,一旦我们有一个问题的好的表示,
要理解树数据结构是什么,以及如何使用它。 查看树如何用于实现 map 数据结构。 使用列表实现树。 使用类和引用来实现树。 实现树作为递归数据结构。 使用堆实现优先级队列。
能够解释和实现顺序查找和二分查找。 能够解释和实现选择排序,冒泡排序,归并排序,快速排序,插入排序和希尔排序。 理解哈希作为搜索技术的思想。 引入映射抽象数据类型。 使用哈希实现 Map 抽象数据类型。
本章的目标如下: 要理解可能难以解决的复杂问题有一个简单的递归解决方案。 学习如何递归地写出程序。 理解和应用递归的三个定律。 将递归理解为一种迭代形式。 实现问题的递归公式化。 了解计算机系统如何实现递归。