2010-03-27 52 views
1

我是密码学的新手,我正在构建一些测试应用程序来尝试理解它的基本知识。我并不是试图从头开始构建算法,但我试图让两种不同的AES-256实现相互交谈。两个AES算法之间的互操作性

我有一个数据库,存储在Base64中的this Javascript implementation。现在,我试图获得一个Objective-C方法来解密它的内容,但是我在实现中的差异在哪里有点失落。我可以在Javascript中进行加密/解密,并且我可以在Cocoa中加密/解密,但是不能在JavaScript中使用JavaScript解密JavaScript中的字符串,反之亦然。

我猜测它与初始化向量,随机数,计数器操作模式或所有这些有关,坦率地说,它现在不会对我说话。

下面是我使用的Objective-C是什么,改编主要是从thisthis

@implementation NSString (Crypto) 

- (NSString *)encryptAES256:(NSString *)key { 
    NSData *input = [self dataUsingEncoding: NSUTF8StringEncoding]; 
    NSData *output = [NSString cryptoAES256:input key:key doEncrypt:TRUE]; 
    return [Base64 encode:output]; 
} 

- (NSString *)decryptAES256:(NSString *)key { 
    NSData *input = [Base64 decode:self]; 
    NSData *output = [NSString cryptoAES256:input key:key doEncrypt:FALSE]; 
    return [[[NSString alloc] initWithData:output encoding:NSUTF8StringEncoding] autorelease]; 
} 

+ (NSData *)cryptoAES256:(NSData *)input key:(NSString *)key doEncrypt:(BOOL)doEncrypt { 
    // '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 = [input 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 numBytesCrypted = 0; 
    CCCryptorStatus cryptStatus = 
     CCCrypt(doEncrypt ? kCCEncrypt : kCCDecrypt, 
      kCCAlgorithmAES128, 
      kCCOptionECBMode | kCCOptionPKCS7Padding, 
      keyPtr, kCCKeySizeAES256, 
      nil, // initialization vector (optional) 
      [input bytes], dataLength, // input 
      buffer, bufferSize, // output 
      &numBytesCrypted 
     ); 
    if (cryptStatus == kCCSuccess) { 
     // the returned NSData takes ownership of the buffer and will free it on deallocation 
     return [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted]; 
    } 
    free(buffer); // free the buffer; 
    return nil; 
} 

@end 

当然,输入为Base64编码解码事前。

我看到,每个使用相同的密钥和JavaScript中的相同内容的加密提供了一个不同的加密字符串,这与Objective-C实现不一样,总是给出相同的加密字符串。我已阅读this post的答案,它使我相信我对沿矢量初始化的某些事情是正确的,但我需要你的帮助来精确地确定发生了什么。

谢谢!

+0

你有没有找到一种方法让两个人说话?我面对完全相同的问题,但我无法找出一种方法来使这项工作..任何帮助表示赞赏。谢谢。 – 2012-10-21 09:07:21

+0

@Ifafavreau,我面临着和你一样的问题。你解决了吗?谢谢! – AlexR 2013-11-21 07:08:37

+1

@AlexR,不,我没有解决它。 Accipitridae说的是真实的:两种实现方式有所不同,并没有采用这种方式。 – lpfavreau 2013-11-21 22:37:28

回答

3

是的,这两个实现之间存在许多差异。

  • JavaScript实现使用CTR模式而Objective-C的实施方式使用ECB模式(ECB弱并且不应当被使用。)

  • JavaScript的实行使用密钥扩展。即它在将密钥传递给AES代码之前转换密钥。不确定Objective-C的实现。无论如何,你几乎可以确定这两个实现不使用相同的密钥进行加密。

  • Javascript实现使用当前时间来生成一个8字节的IV,它被加密到密文中。此IV用于初始化CTR模式的计数器。 由于IV变化,加密相同的明文两次将导致不同的密文。只要不在相同的时钟周期()内加密两个密文,使用当前时间生成CTR模式的IV也是可以的。 Objective-C实现不使用IV(因为它使用ECB模式)。

  • Objective-C代码使用PKCS#7填充,Javascript代码使用none。这是使用不同加密模式的结果。

  • 此外,您还必须检查密文是如何编码的。 Javascript代码使用Base64编码。 Objective-C代码分布在多个帖子上太多,我没有找到相关的代码。

+0

我还注意到你的Objective-C代码说'kCCAlgorithmAES128',但是你的文本说你想要实现AES-256。你不小心使用了较小的块大小? – 2010-03-27 18:32:18

+0

谢谢你这个很好的答案。关于块大小,我在Objective-C中看到的所有AES256实现(使用默认的CCCrypt)使用kCCAlgorithmAES128作为块大小,但没有我知道的kCCAlgorithmAES256。不知道密码学方面的问题,我不能说这是否会产生影响,还是标准做法。关于编码,两者都使用Base64作为生成的加密文本。 – lpfavreau 2010-03-27 18:49:08

+1

AES的块大小始终为128位。但是,密钥大小可能会有所不同。即密钥大小可以是128,192或256位。因此,以上块和密钥大小的规格看起来不错。 – Accipitridae 2010-03-27 20:14:42

0

要进行测试,您应该考虑使用NIST website for AESFIPS 197中的测试值。

+0

我如何解释结果?如果我已经知道这两个实现产生的加密字符串是不同的,那么我将如何使用这些值来学习? – lpfavreau 2010-03-27 17:52:30