【问题标题】:Objective-c AES128 encrypt [closed]Objective-c AES128加密[关闭]
【发布时间】:2017-03-15 18:51:03
【问题描述】:

我尝试用这个类加密NSString

#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES)

- (NSData *)AES128EncryptedDataWithKey:(NSString *)key
{
    return [self AES128EncryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128DecryptedDataWithKey:(NSString *)key
{
    return [self AES128DecryptedDataWithKey:key iv:nil];
}

- (NSData *)AES128EncryptedDataWithKey:(NSString *)key iv:(NSString *)iv
{
    return [self AES128Operation:kCCEncrypt key:key iv:iv];
}

- (NSData *)AES128DecryptedDataWithKey:(NSString *)key iv:(NSString *)iv
{
    return [self AES128Operation:kCCDecrypt key:key iv:iv];
}

- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
    char keyPtr[kCCKeySizeAES128 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
    if (iv) {
        [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    }

    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr,
                                          kCCBlockSizeAES128,
                                          ivPtr,
                                          [self bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}

@end

我为此使用此代码:

//This is MD5 key
NSString *key = @"7046dd94480f28dbf4b2e3cb6fa3864a";

NSData *plainDataEmail = [@"app@cfd.com" dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedDataEmail = [plainDataEmail AES128EncryptedDataWithKey:key];
NSString *encryptedStringEmail = [encryptedDataEmail base64EncodedStringWithOptions:0];

encryptedStringEmail 是:

JXf7l5dH3qaYvudxCzE98w==

现在我在this site 上检查相同的详细信息, 原因是:

gnZZGbRaVtCG8Z8Xf732Cw==

请告诉我我的 Objective-c 代码有什么问题

【问题讨论】:

  • 我的错误,我编辑了链接
  • 在这种情况下,代码是否每次都产生相同的 JXf7l5dH3qaYvudxCzE98w==?
  • 是一样的结果
  • 已编辑,现在可以了吗?

标签: ios objective-c encryption aes


【解决方案1】:

这里发生了很多事情。几乎每一步都在某种程度上看起来是错误的。我可以通过,但整个计划非常不安全。我的建议是,除非您需要专门匹配 aesencryption.net,否则请使用跨平台的安全格式,例如 RNCryptor

简短版:没有普遍接受的使用 AES 的方法。您必须准确了解双方是如何实施其格式并使其匹配的。 aesencryption.net 没有解释他们的方法(代码示例似乎彼此不匹配或网站工具不匹配)。正确使用 AES 非常困难,因此几乎任何随意选择的方法都会非常不安全。

您有一个不正确的密钥假设:使用相同密钥加密的明文应该始终生成相同的密文。在安全方案中,这应该从不为真。 (如果您使用正确使用的工具,那么您将获得匹配的输出,但那是因为它们是不安全的实现。)除非在极少数情况下您需要可重现性并故意为此牺牲安全性,否则至少应该有方案中的一个随机元素,它导致每个加密都是唯一的。在上面的代码中,该随机元素应该是 IV。您应该生成一个随机 IV 并将其传递给加密器。

虽然您期望使用 128 位加密,但您的密钥实际上是 256 位长。您可能认为密钥的第一个字节是 0x70,但这是不正确的。它是 0x37,这是“7”的 UTF-8 编码。您正在传递一个字符串,它只是被 UTF-8 编码,然后被截断(或零填充)为 16 个字节。 (这是这个 ObjC 代码如此不安全的关键原因之一。)

不清楚 aesencryption.net 对密钥做了什么;他们没有显示他们的代码,他们的代码示例也不清楚。他们的 Java 示例对密钥进行哈希处理,但我认为他们的 PHP 代码不会。该网站的行为方式,我认为它不会散列,但它的行为有点奇怪。长度为 33 个字符的密钥与 32 个字符的加密完全相同,因此很明显会被截断。但它被截断为 32 字节,而不是 16 字节,即使对于 128 位密钥也是如此。所以这一切都很奇怪。

最后,ObjC 代码使用 ECB 模式,这几乎是您可以为通用加密选择的最差模式。在一些非常特殊的情况下它很有用,但这不是其中之一。 aesencryption.net 使用的是什么并不明显,尽管他们的代码示例确实使用了 ECB。

【讨论】:

    【解决方案2】:

    您的链接无法正常工作。

    我过去也遇到过类似的问题。我怀疑AES128EncryptedDataWithKey 方法正在将您的密钥(NSString)转换为二进制文件,使用的方法或编码与您尝试链接的网站不同。

    【讨论】:

    • 抱歉我的错误,我再次编辑了问题
    猜你喜欢
    • 2020-03-29
    • 2013-03-01
    • 2014-07-07
    • 1970-01-01
    • 2014-01-27
    • 2017-07-10
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多