我不确定我的解决方案有多安全。
Rob Napier有一个非凡的框架(RNCryptor)可以在iOS和其他系统中进行加密和解密。
据我所知,他正在使用AES-CBC,这实际上是CommonCryptor.h的标准
但是,我的要求迫使我使用AES-CTR。两者都非常相似,所以理论上它必须是简单的。但事实并非如此。
CommonCryptor.h缺乏信息。这是有史以来解释最糟糕的框架之一。
使用 CBC ,您只需致电CCCrypt()
即可。但是,要使用点击率 you should call:CCCrytorCreate()
,CCCryptorUpdate()
,CCCryptorFinal(
)和CCCryptorRelease()
尝试加密我的数据,我每次都收到不同的数据,当然解密它的结果不正确。
我的第一种方法遇到了两个大问题:密钥的长度和写入dataOut的字节数。
我用以下问题对问题进行了分类:
1.-一个32个字符的NSString密钥
NSString *key = @"1234567890ABCDEFGHIJKLMNOPQRSTUV";
2.-以需要的长度剪切dataOut
最后这是我加密和解密的代码:
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>
#import <Security/Security.h>
+ (NSMutableData*) encryptString: (NSString*) stringToEncrypt withKey: (NSString*) keyString
{
//Key to Data
NSData *key = [keyString dataUsingEncoding:NSUTF8StringEncoding];
//String to encrypt to Data
NSData *data = [stringToEncrypt dataUsingEncoding:NSUTF8StringEncoding];
// Init cryptor
CCCryptorRef cryptor = NULL;
// Alloc Data Out
NSMutableData *cipherData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
//Empty IV: initialization vector
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
//Create Cryptor
CCCryptorStatus create = CCCryptorCreateWithMode(kCCEncrypt,
kCCModeCTR,
kCCAlgorithmAES,
ccPKCS7Padding,
iv.bytes, // can be NULL, because null is full of zeros
key.bytes,
key.length,
NULL,
0,
0,
kCCModeOptionCTR_BE,
&cryptor);
if (create == kCCSuccess)
{
//alloc number of bytes written to data Out
size_t outLength;
//Update Cryptor
CCCryptorStatus update = CCCryptorUpdate(cryptor,
data.bytes,
data.length,
cipherData.mutableBytes,
cipherData.length,
&outLength);
if (update == kCCSuccess)
{
//Cut Data Out with nedded length
cipherData.length = outLength;
//Final Cryptor
CCCryptorStatus final = CCCryptorFinal(cryptor, //CCCryptorRef cryptorRef,
cipherData.mutableBytes, //void *dataOut,
cipherData.length, // size_t dataOutAvailable,
&outLength); // size_t *dataOutMoved)
if (final == kCCSuccess)
{
//Release Cryptor
//CCCryptorStatus release =
CCCryptorRelease(cryptor ); //CCCryptorRef cryptorRef
}
return cipherData;
}
}
else
{
//error
}
return nil;
}
+ (NSString*) decryptData: (NSData*) data withKey: (NSString*) keyString
{
//Key to Data
NSData *key = [keyString dataUsingEncoding:NSUTF8StringEncoding];
// Init cryptor
CCCryptorRef cryptor = NULL;
//Empty IV: initialization vector
NSMutableData *iv = [NSMutableData dataWithLength:kCCBlockSizeAES128];
// Create Cryptor
CCCryptorStatus createDecrypt = CCCryptorCreateWithMode(kCCDecrypt, // operation
kCCModeCTR, // mode CTR
kCCAlgorithmAES, // Algorithm
ccPKCS7Padding, // padding
iv.bytes, // can be NULL, because null is full of zeros
key.bytes, // key
key.length, // keylength
NULL, //const void *tweak
0, //size_t tweakLength,
0, //int numRounds,
kCCModeOptionCTR_BE, //CCModeOptions options,
&cryptor); //CCCryptorRef *cryptorRef
if (createDecrypt == kCCSuccess)
{
// Alloc Data Out
NSMutableData *cipherDataDecrypt = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
//alloc number of bytes written to data Out
size_t outLengthDecrypt;
//Update Cryptor
CCCryptorStatus updateDecrypt = CCCryptorUpdate(cryptor,
data.bytes, //const void *dataIn,
data.length, //size_t dataInLength,
cipherDataDecrypt.mutableBytes, //void *dataOut,
cipherDataDecrypt.length, // size_t dataOutAvailable,
&outLengthDecrypt); // size_t *dataOutMoved)
if (updateDecrypt == kCCSuccess)
{
//Cut Data Out with nedded length
cipherDataDecrypt.length = outLengthDecrypt;
// Data to String
NSString* cipherFinalDecrypt = [[NSString alloc] initWithData:cipherDataDecrypt encoding:NSUTF8StringEncoding];
//Final Cryptor
CCCryptorStatus final = CCCryptorFinal(cryptor, //CCCryptorRef cryptorRef,
cipherDataDecrypt.mutableBytes, //void *dataOut,
cipherDataDecrypt.length, // size_t dataOutAvailable,
&outLengthDecrypt); // size_t *dataOutMoved)
if (final == kCCSuccess)
{
//Release Cryptor
//CCCryptorStatus release =
CCCryptorRelease(cryptor); //CCCryptorRef cryptorRef
}
return cipherFinalDecrypt;
}
}
else
{
//error
}
return nil;
}
要打电话:
NSString *key = @"1234567890ABCDEFGHIJKLMNOPQRSTUV";
NSString *stringToEncrypt = @"Gabriel.Massana";
NSData* encrypted = [GM_AES128_CTR encryptString:stringToEncrypt withKey:key];
NSString *decrypted = [GM_AES128_CTR decryptData:encrypted withKey:key];
我发布了我的解决方案,因为Stackoverflow中的AES CTR没有太多问题。同样,如果有人想检查它并告诉我是否有问题将非常感激。
这个解决方案有多安全?破解系统很容易吗?我有什么可能为AES-CTR添加更多安全性?
答案 0 :(得分:2)
我将此列为单独答案,但我只是放大了Zaph已经说过的内容:
这是完全破解的加密。
发生在你身上并不奇怪。当您尝试构建自己的方案时,这是一个非常常见的问题。有很多地方你可以搞砸。但我不想低估这个计划的不安全性。它确实非常破碎。
CTR无法永远重复相同的nonce +键,并且每次都重复使用nonce。这与CBC截然不同。在CBC中,如果您重用IV,那么您可以让攻击者更容易破解加密。在CTR中,如果您重复使用nonce +键,一旦您有几个密文,就很容易解密该消息。可以在RFC3686中找到一些好的讨论。
如果使用正确,AES-CTR提供高水平的 保密。不幸的是,AES-CTR很容易错误使用。 作为流密码,任何重用的每个数据包的值,称为 四,具有相同的随机数和关键是灾难性的。 IV碰撞 立即泄漏两个数据包中有关明文的信息。 因此,使用这种操作模式是不合适的 用静态键。需要采取特别措施来防止这种情况发生 在电力循环中使用静态密钥重用IV值。成为 安全,实现必须使用带有AES-CTR的新密钥。互联网 密钥交换(IKE)[IKE]协议可用于建立新鲜 键。 IKE还可以提供nonce值。
请注意RNCryptor originally used CTR。在与他们讨论了如何轻松搞砸点击率之后,我根据Apple的推荐回到了CBC。如果你可以避免点击率,你绝对应该。它对某些问题非常有用,但对于一般的文件加密,它很少适用。
那就是说,我知道你的芯片有问题。你的芯片如何得到它的钥匙?用这种方式对芯片进行对称加密似乎很奇怪。无论如何,RNCryptor v1可能会满足您的需求。您可能需要使用encryptFromStream:toStream:encryptionKey:HMACKey:error:
,因为我认为芯片无法处理PBKDF2。
尝试加密我的数据,我每次都收到不同的数据,当然解密它的结果不正确。
任何好的加密系统都会拥有此属性。这就是为什么你需要发送你的随机数/ IV(如果你使用密码,盐)和密文。
NSString * key = @“1234567890ABCDEFGHIJKLMNOPQRSTUV”;
这不是关键。这是一个密码,可以显着减少您的可用密钥空间。密钥通常为NSData
,因为需要选择所有可能的值,而不仅仅是ASCII。