我遇到了密码加密问题。我正在使用AES128来加密数据。以下是代码:
LoginController.m
#import <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonKeyDerivation.h>
#import "NSData+AES.h"
- (IBAction)loginButtonClick:(id)sender
{
NSData *toencrypt = [password.text dataUsingEncoding:NSUTF8StringEncoding];
NSString *credentials = [self md5:[NSString stringWithFormat:@"63jhdf83hf73haf3983f"]]; //returns 679fb1ddf7d81bee0aff2ef251fe6bf5
NSString *iv = @"kdf67398DF7383fd";
NSData *data = [toencrypt AES128EncryptWithKey:credentials iv:iv];
NSString *postdata = [data base64Encoding]; //base64Encoding is implemented in NSData+AES.m
NSLog(@"Original Password: %@",password);
NSLog(@"Encrypted Password: %@",postdata);
}
** N.B:md5转换和base64Encoding工作正常。
的NSData + AES.m
static char encodingTable[64] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
@implementation NSData (AES)
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
char keyPtr[kCCKeySizeAES128+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCKeySizeAES128+1];
bzero(ivPtr, sizeof(ivPtr));
[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
int newSize = 0;
if(diff > 0){
newSize = (int)dataLength + diff;
}
char dataPtr[newSize];
memcpy(dataPtr, [self bytes], [self length]);
for(int i = 0; i < diff; i++){
dataPtr[i + dataLength] = 0x00;
}
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
0x00, //No padding
keyPtr,
kCCKeySizeAES128,
ivPtr,
dataPtr,
sizeof(dataPtr),
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
return nil;
}
现在如果发送“brad”,它应该返回“ur / bq4Rz”。但不幸的是它返回“83 + eQZW3eI4UWGdNk4nnUw ==”。有什么问题?请帮帮我。提前谢谢。
答案 0 :(得分:1)
请注意,此代码非常不安全。它为每条消息重复使用相同的Key + IV,这极大地简化了为攻击者解密消息的工作(特别是短消息)。它还有其他安全问题(键空间差,填充方案不好)
也就是说,特别破坏的部分是你通过一个32字节(256位)&#34;键&#34;但是你只使用了128位。您可能打算使用kCCKeySizeAES256
作为密钥长度。这与kCCAlgorithmAES128
无关,diff
指的是块大小,而不是密钥长度。在kCCBlockSizeAES128
代码中,您打算使用kCCKeySizeAES128
而不是{{1}},但它们都是16,因此不会对结果产生影响。
正如@Codo所说,标准CBC模式无法输出长度不是16字节倍数的密文。为什么你相信&#34; ur / bq4Rz&#34;是正确的加密?有一个CBC的修改可以做到这一点(它增加了所谓的&#34;密文窃取&#34;或CTS),但iOS不支持。
您的代码正在执行零填充,这是一种非常糟糕的方法(您只需添加零,直到达到16字节边界)。标准(更安全)的解决方案是PKCS#7填充,您将关闭它。
如果我不得不猜测,你要复制零填充数据的代码,然后将密文截断为长度。然后解密可能用零填充密文,然后在最后截断垃圾(可能基于事先知道长度)。我知道这是如何工作的,但这不是正常的做法。
如果您想了解如何执行此操作的示例,请参阅Properly Encrypting With AES and CommonCrypto。如果您想要一种更安全的方法来完成所有这些操作,请参阅RNCryptor。但是,这些都不会生成与明文长度相同的密文。
答案 1 :(得分:0)
我发现了一些问题,例如您没有检查getCString:maxLength:endocind
是否失败。这是不推荐使用的函数,它可能在这里失败,因此加密方法可能使用完全不同的密钥和IV
这是我的这个方法的版本。这应该做正确的工作:
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
int diff = kCCKeySizeAES128 - (self.length % kCCKeySizeAES128);
NSMutableData *adjustedData = [NSMutableData dataWithData:self];
[adjustedData appendData:[[NSMutableData alloc] initWithLength:diff]];
size_t bufferSize = adjustedData.length + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
0x00, //No padding
[key UTF8String], kCCKeySizeAES128,
[iv UTF8String],
adjustedData.bytes,
adjustedData.length,
buffer,
bufferSize,
&numBytesEncrypted);
if(cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
return nil;
}