两种AES算法之间的互操作性 [英] Interoperability between two AES algorithms

查看:137
本文介绍了两种AES算法之间的互操作性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是密码学的新手,我正在建立一些测试应用程序,尝试并了解它的基础。我不想从头开始构建算法,但我试图让两个不同的AES-256实现相互交谈。

I'm new to cryptography and I'm building some test applications to try and understand the basics of it. I'm not trying to build the algorithms from scratch but I'm trying to make two different AES-256 implementation talk to each other.

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

I've got a database that was populated with this Javascript implementation stored in Base64. Now, I'm trying to get an Objective-C method to decrypt its content but I'm a little lost as to where the differences in the implementations are. I'm able to encrypt/decrypt in Javascript and I'm able to encrypt/decrypt in Cocoa but cannot make a string encrypted in Javascript decrypted in Cocoa or vice-versa.

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

I'm guessing it's related to the initialization vector, nonce, counter mode of operation or all of these, which quite frankly, doesn't speak to me at the moment.

这里是我在Objective-C中使用,主要修改此< a>:

Here's what I'm using in Objective-C, adapted mainly from this and this:

@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已经预先解码。

Of course, the input is Base64 decoded beforehand.

我发现在Javascript中使用相同的键和相同的内容进行的每次加密都提供了不同的加密字符串,而Objective-C实现则不是这样总是给出相同的加密字符串。我已阅读此帖的答案,它让我相信我'关于沿着矢量初始化的线的东西,但我需要你的帮助,准确地指出正在发生什么。

I see that each encryption with the same key and same content in Javascript gives a different encrypted string, which is not the case with the Objective-C implementation that always give the same encrypted string. I've read the answers of this post and it makes me believe I'm right about something along the lines of vector initialization but I'd need your help to pinpoint what's going on exactly.

谢谢!

推荐答案

JavaScript实现使用CTR模式,而Objective-C实现使用ECB模式(ECB是弱的(弱的)),而不是两个实现之间的区别。

Yup, there are a number of differences between the two implementations.


  • 不应该使用。)
  • The Javascript implementation uses CTR mode while the Objective-C implementation uses ECB mode (ECB is weak and should not be used.)

Javascript实现使用键扩展。也就是说它在将密钥传递给AES代码之前对密钥进行转换。不确定Objective-C实现。无论如何,你几乎可以确定这两个实现没有使用相同的密钥进行加密。

The Javascript implemenation uses a key expansion. I.e. it transforms the key before passing it to the AES code. Not sure about the Objective-C implementation. Anyway, you can almost be sure that the two implementations are not using the same key for the encryption.

Javascript实现使用当前时间生成一个8字节IV加密到密文。此IV用于初始化CTR模式的计数器。
由于IV更改,加密相同的明文两次将导致不同的密文。还使用当前时间为CTR模式生成IV是确定,只要你不在同一时钟tick()内加密两个密文。 Objective-C实现不使用IV(因为它使用ECB模式)。

The Javascript implementation uses the current time to generate a 8 byte IV that is prepended to the ciphertext. This IV is used to initialize the counter for the CTR mode. Because of the IV changes, encrypting the same plaintext twice will result in different ciphertexts. Also using the current time for generating an IV for CTR mode is ok, as long as you don't encrypt two ciphertexts within the same clock tick(). The Objective-C implementation doesn't use an IV (since it uses ECB mode).

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

The Objective-C code uses PKCS #7 padding, the Javascript code uses none. This is a consequence of using distinct encryption modes.

此外,您还必须检查密文如何编码。 Javascript代码使用Base64编码。

Furthermore, you also have to check, how the ciphertext is encoded. The Javascript code uses Base64 encoding. The Objective-C code is too much distributed over several postings, that I didn't find the relevant code.

这篇关于两种AES算法之间的互操作性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆