2012-06-05 84 views
3

我一直在寻找并查看几个小时。我拼命地试图让iOS使用AES-256加密来加密短文本,然后可以使用openssl进行解密。iOS上的AES-256加密不会产生与openssl相同的结果

直向前?不。

我找到的iOS代码与openssl的键和IV不兼容,所以我不得不适应它,但它显然不工作。

因此,这里的代码,我使用的加密...传递一个字符串加密(dataString)的字符串键(键)和一个字符串初始化向量(IV)...

- (NSData *)AES256Encrypt:(NSString *)dataString WithKey:(NSString *)key iv:(NSString *)iv { 

    // '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]; 

    //NSLog(@"keyPtr: '%s'", keyPtr); 

    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 
    NSLog(@"keyPtr: '%s'", keyData.bytes); 
    NSData *dataToEncrypt = [dataString dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [dataToEncrypt 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, 
              keyData.bytes, kCCKeySizeAES256, 
              ivData.bytes, // initialisation vector 
              dataToEncrypt.bytes, 
              dataToEncrypt.length, /* 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; 
} 

对于相同的字符串进行编码,这不会产生与使用openssl相同的密钥和iv ...相同的值此命令行:

openssl enc -aes-256-cbc -e -in secrets.txt -a -iv 0000 -K 0000 -p 

secrets.txt只是要加密包含字符串的文本文件

此输出是这样的:

salt=3C66000000000000 
key=0000000000000000000000000000000000000000000000000000000000000000 
iv =00000000000000000000000000000000 
qTMfgtAxbF8Yyh27ZDrcIQ== 

并且解密,执行相反的操作(假设上面加密的最后一行数据在test.secrets.out中)

openssl enc -aes-256-cbc -d -in test.secrets.out -a -iv 0000 -K 0000 -p 
salt=3C66000000000000 
key=0000000000000000000000000000000000000000000000000000000000000000 
iv =00000000000000000000000000000000 
< text of the secrets.txt file > 

现在,如果我使用4个字符的键和iv,则这不会在iOS中正确编码。如果我使用全长键和四,这也不正确编码。

基本上,这是一个检查,看看如果我发送一块加密数据它是正确的一块数据。

我错过了什么?

一些代码,我已经看了通过,试图找到答案......

http://robnapier.net/blog/aes-commoncrypto-564

https://github.com/rnapier/RNCryptor

http://pastie.org/426530

对这里广泛搜索过,并不能找到答案。

任何帮助表示赞赏。

+0

看看你是否可以让IOS解密它加密的东西。 –

+0

同意热舔,但是如果他试图加密本地使用iOS加速例程通过SSL连接到其他东西,然后.....我注意到SSL使用AES的CBC模式。你确定你已经在CBC模式下设置iOS吗? AES以128位块处理块,可能值得研究iOS是否在小端或大端解释输入数据。这也适用于关键和IV。 – trumpetlicks

+0

只是另一个说明,你可能还需要看看数据是如何填充最后的128位块(如果数据未在128位边界上对齐)。 – trumpetlicks

回答

2

OpenSSL有一个独特的(读“不接近任何标准,也不是特别安全”)方法将密码转换为IV和密钥。如果你看一下RNOpenSSLCryptor,你会看到所使用的算法:

// For aes-128: 
// 
// key = MD5(password + salt) 
// IV = MD5(Key + password + salt) 

// 
// For aes-256: 
// 
// Hash0 = '' 
// Hash1 = MD5(Hash0 + Password + Salt) 
// Hash2 = MD5(Hash1 + Password + Salt) 
// Hash3 = MD5(Hash2 + Password + Salt) 
// Hash4 = MD5(Hash3 + Password + Salt) 
// 
// Key = Hash1 + Hash2 
// IV = Hash3 + Hash4 
// 

// File Format: 
// 
// |Salted___|<salt>|<ciphertext>| 
// 

使用RNOpenSSLCryptor允许OpenSSL的格式RNCryptor支持。我目前正在修改async分支上的代码以支持异步操作,并且该分支尚不支持OpenSSL,但我打算很快(2012年7月中旬)重新进行修改。

如果您想要自行使用的代码,请参阅keyForPassword:salt:IVForKey:password:salt:

请注意,OpenSSL文件格式有几个安全问题,如果您可以避免它,我不推荐它。它没有使用非常好的KDF来生成密钥,也没有像应该那样随意使用IV,并且不提供用于验证的HMAC。这些安全问题是我设计different file format的原因,正如我讨厌制造“又一个不兼容的容器”一样。

相关问题