【问题标题】:AES256 more than 32BytesAES256 超过 32Bytes
【发布时间】:2015-07-12 13:41:48
【问题描述】:

我有这个将 NSData 转换为 AES256 的 Objective-c 代码,最近我发现密码的最大数量是 32 个字节:

- (NSData *)AES256EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

我想知道是否有可能找到一些方法来增加这些字节?导致密码大于32位,有可能吗?

【问题讨论】:

    标签: ios objective-c aes nsdata


    【解决方案1】:
    1. 字节不是数字。

    2. 256 位密钥远远超出暴力破解。

    3. 不要为加密密钥使用密码。如果您需要使用密码,请使用密码密钥派生函数(例如 PBKDF2)从密码创建安全加密密钥。密码可以是任意长度,并且 PBKDF2 函数将生成正确长度的安全加密密钥。指定 > 10K 的迭代计数。

    4. 让 CCCrypt 工作是创建安全加密方案的微不足道的部分。

    5. 考虑使用 RNcryptor,它将处理这些细节等等。

    6. 您需要处理密码/密钥的安全性,这并不容易。

    【讨论】:

      【解决方案2】:

      AES 不使用密码,而是使用密钥。例如,AES-256 仅针对 256 位密钥(32 字节)定义。您当然可以使用基于密码的派生函数从密码中派生密钥。

      流行的选择是PBKDF2、bcrypt 和 scrypt(速度越来越慢 - 越慢越好)。它们本质上是哈希函数,接受任意二进制字符串并给出(可变)固定输出。

      PBKDF2 的一个好的值是 86,000 次迭代。另外,使用随机盐。然后,您可以为密钥和 IV 生成足够的输出。

      CBC 模式(这是 CCCrypt 的默认设置)如果与静态 IV(例如代码中的全零 IV)一起使用,则在语义上是不安全的。至少使用带有随机 IV 的 CBC 模式,甚至更好的是使用 GCM 或 EAX 等经过身份验证的模式。如果验证模式不可用,您需要将消息验证码应用于您的密文(encrypt-then-MAC),以防您的系统容易受到随机预言机攻击。

      【讨论】:

      • 这取决于你的密码和它有多少熵。如果它的熵很低,意味着它出现在字典中或者是一个通用密码,那么这根本不安全。它很容易被暴力破解。
      • 正如我所说,这取决于密码以及它的易猜性。
      • 看这个->github.com/RNCryptor/RNCryptor,简单,用CBC,随机IV,我用这个
      • RNCryptor 很好,目前正在维护。您将如何维护和传输加密密钥?
      • 我不同意你的回答,一切都很好。这一切也很复杂。我同意知识是有益的,如果没有其他原因让开发人员明白它不像密码和 AES 那么容易。更好的链接是github.com/RNCryptor,它提供了 10 多种语言/平台组合的可用性信息。我不断地看到跨平台/语言问题,这有助于缓解互操作性问题。我从未使用过 RNCryptor,但如果我需要实现它支持的功能,经过良好测试的代码可能会胜过我的新代码。
      猜你喜欢
      • 2018-08-19
      • 2016-02-08
      • 2019-06-23
      • 2014-08-01
      • 2015-05-19
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多