用随机字节填充内存 - C/Objective-C

5

我正在使用CommonCrypto对Objective-C中的加密进行AES256位加密,我想为更安全的加密提供一个IV(初始化向量)。目前我的做法如下:

const void* iv = malloc(kCCBlockSizeAES128);
// EDIT:
//if (!iv) {
//    iv = NULL;
//}

然后我创建了加密器对象:

CCCryptorRef cryptor;
CCCryptorStatus cryptStatus = CCCryptorCreate(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                                  keyPtr, kCCKeySizeAES256,
                                                  iv,
                                                  &cryptor);

问题在于这种加密方式似乎失败了(伤心脸...)。我的意思是:它加密时没有明显的问题,但解密后的数据与原始数据不同。我认为这应该是可行的,因为当你使用malloc()分配内存时,它并不会全部写入零,而是随机的。我还尝试自己编写随机值,但我的C语言知识有限。如果有一个类似于bzero的函数可以写入随机字节,请告诉我。

我还尝试了类似以下的操作:

char* iv = malloc(kCCBlockSizeAES128);
int i;
srand((unsigned int)time(NULL));
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = (char)rand()%256;
}

哦,顺便说一下,我意识到这可能是一个非常新手的问题 :)

最后我想要的东西就像 const void* iv = malloc(kCCBlockSizeAES128) 一样,在经过一些操作后我确定它的数据是完全随机的。有什么想法吗?

PS:我只提供加密/解密和Objective-C的背景信息,所以您知道我需要这个用途。我认为这不会影响任何事情。kCCBlockSizeAES128 = 16(90%确定 :)。

编辑:

好吧!经过一些调试,我很高兴地宣布,我遇到的加密和解密问题是由于程序中另一部分中存在错误造成的,现在我已经解决了。现在我需要弄清楚的是如何填充iv随机字节。一些选项:

  • 使用malloc(),它返回垃圾而不是随机字节-> 可能不安全(?)
  • 使用arc4random_buf(),正是我想要的,但它仅适用于10.7+,我的Mac是10.6.6(而且我想支持10.6)
  • 我没有考虑到的其他事情...? <-- 在这里帮助!

编辑2:

好吧!在用一些测试数据(全零,全一等)填充iv并更多的调试后,我不再高兴地宣布ccrypto似乎在某些条件下不起作用。我将解释如何进行:

每当我向加密提供一个为零的iv或NULL时(加密同理),它都有效。例如,在加密和解密时,这很好用:

uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = 0x0; // I know this is the same as doing: memset((void *)iv, 0x0, (size_t)sizeof(iv));
}

CCCryptorRef cryptor;
CCCryptorStatus cryptStatus = CCCryptorCreate(operation, kCCAlgorithmAES128,
                                              kCCOptionPKCS7Padding,
                                              (const void *)keyPtr, kCCKeySizeAES256,
                                              iv,
                                              &cryptor);

但是,当我向他输入一个至少有一个字节不为零的 IV 时,加密/解密并没有出现错误,但解密后的数据并不是原始数据。例如,下面这个...

uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = 0x1;
}

或者用于完全随机数据...
uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = arc4random() % 256;
}

无法工作。 我完全不理解这个逻辑...有什么想法吗?

6
评论:if (!iv) { iv = NULL; } 没有意义。 翻译:上述代码“如果iv为假值,则将其赋值为NULL”是没有实际作用的语句。 - Mat
@Mat,我这样做是因为如果你提供了空的加密参数,它会自己创建一个全0 IV。当我不能创建IV时,我让加密创建一个全0的IV。否则,我想要一个随机的IV。 - Alex
1
你的帖子非常模糊:“似乎失败了”?确保它正在失败。此外,加密函数应该在IV的内容不同的情况下也能正常工作 - 可能不安全,但是会起作用。因此,你的问题可能出在其他地方。请更详细地描述什么没有工作以及它如何失败。(if块内的语句只有在!iv为真时才会运行,这只会在iv == null时发生...) - Mat
@Mat,我已经更新了我的问题,请您再次检查一下? - Alex
不,我没有。我已经尝试使用上述方法将加密的NULL(清零IV)和随机IV用于解密,但都没有成功。我应该这样做吗?如果是这样,怎么做?我需要将其与文件一起保存吗? - Alex
显示剩余4条评论
1个回答

11

您可以使用arc4random_buf来填充缓冲区以获取随机数据:

#include <stdlib.h>
#include <stdint.h>

uint8_t iv[kCCBlockSizeAES128];
arc4random_buf(&iv, kCCBlockSizeAES128);
此外,malloc 返回的内存块(与任何未初始化的内存一样)都是填充有“垃圾数据”的。你不应该假设它会被填充上什么东西,尤其不是加密强度的随机数。

请确保您正在使用 Mac OS X 10.7 或 iOS 4.3(或更高版本)的 SDK 进行编译。 - 一二三
好的,我正在使用Mac OS 10.6进行编译...但是arc4random_addrandom()可以吗? - Alex
1
这可能是一个愚蠢的问题,为什么要将&iv传递给arc4random_buf,而不只是iv呢?我认为iv已经是一个指针,我们只需要将随机数据放在iv指向的位置即可... - Erben Mo
在这种情况下,iv&iv是等价的。&iv是数组的地址,而当传递给函数时(它们都是相同的),iv会衰减为指向数组第一个元素的指针。The C Book对此有更详细的解释。 - 一二三
1
&iv 不是指针所包含的地址吗?我认为你应该传递 iv 而不是 &iv。 - David 天宇 Wong
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接