适用于ios密码的AES128加密方法

时间:2015-01-13 13:06:43

标签: ios objective-c encryption

我遇到了密码加密问题。我正在使用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 ==”。有什么问题?请帮帮我。提前谢谢。

2 个答案:

答案 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;
}