Objective C - 使用AESCrypt加密解密文件(www.aescrypt.com)

时间:2013-11-14 09:44:56

标签: java objective-c encryption methods

我需要重写一个解密加密文件的Java方法,该文件使用AESCrypt(http://www.aescrypt.com)加密。此程序使用自定义文件格式(.aes),需要以自定义方式处理。已经有像我说的Java方法了。到目前为止,我完成了重写方法的一部分,到目前为止它的工作原理。但我在某些方面陷入困境。我找不到相应的IvParameterSpecSecretKeySpec

请参阅Java方法和我已完成的部分。如果你们能给我一个如何继续使用该方法的指针,那将是很棒的。

PS。不要担心参数,因为Java使用InputStream和OutputStream,我使用NSFileHandle和NSOutputStream。

感谢。

public void decrypt(long inSize, InputStream in, OutputStream out)
throws IOException, GeneralSecurityException {
    try {
        byte[] text = null, backup = null;
        long total = 3 + 1 + 1 + BLOCK_SIZE + BLOCK_SIZE + KEY_SIZE + SHA_SIZE + 1 + SHA_SIZE;
        int version;

        text = new byte[3];
        readBytes(in, text);    // Heading.
        if (!new String(text, "UTF-8").equals("AES")) {
            throw new IOException("Invalid file header");
        }

        version = in.read();    // Version.
        if (version < 1 || version > 2) {
            throw new IOException("Unsupported version number: " + version);
        }
        debug("Version: " + version);

        in.read();  // Reserved.

        if (version == 2) { // Extensions.
            text = new byte[2];
            int len;
            do {
                readBytes(in, text);
                len = ((0xff & (int) text[0]) << 8) | (0xff & (int) text[1]);
                if (in.skip(len) != len) {
                    throw new IOException("Unexpected end of extension");
                }
                total += 2 + len;
                debug("Skipped extension sized: " + len);
            } while (len != 0);
        }

        text = new byte[BLOCK_SIZE];
        readBytes(in, text);    // Initialization Vector.
        ivSpec1 = new IvParameterSpec(text);
        aesKey1 = new SecretKeySpec(generateAESKey1(ivSpec1.getIV(), password), CRYPT_ALG);
        debug("IV1: ", ivSpec1.getIV());
        debug("AES1: ", aesKey1.getEncoded());

        cipher.init(Cipher.DECRYPT_MODE, aesKey1, ivSpec1);
        backup = new byte[BLOCK_SIZE + KEY_SIZE];
        readBytes(in, backup);  // IV and key to decrypt file contents.
        debug("IV2 + AES2 ciphertext: ", backup);
        text = cipher.doFinal(backup);
        ivSpec2 = new IvParameterSpec(text, 0, BLOCK_SIZE);
        aesKey2 = new SecretKeySpec(text, BLOCK_SIZE, KEY_SIZE, CRYPT_ALG);
        debug("IV2: ", ivSpec2.getIV());
        debug("AES2: ", aesKey2.getEncoded());

        hmac.init(new SecretKeySpec(aesKey1.getEncoded(), HMAC_ALG));
        backup = hmac.doFinal(backup);
        text = new byte[SHA_SIZE];
        readBytes(in, text);    // HMAC and authenticity test.
        if (!Arrays.equals(backup, text)) {
            throw new IOException("Message has been altered or password incorrect");
        }
        debug("HMAC1: ", text);

        total = inSize - total; // Payload size.
        if (total % BLOCK_SIZE != 0) {
            throw new IOException("Input file is corrupt");
        }
        if (total == 0) {   // Hack: empty files won't enter block-processing for-loop below. 
            in.read();  // Skip last block size mod 16.
        }
        debug("Payload size: " + total);

        cipher.init(Cipher.DECRYPT_MODE, aesKey2, ivSpec2);
        hmac.init(new SecretKeySpec(aesKey2.getEncoded(), HMAC_ALG));
        backup = new byte[BLOCK_SIZE];
        text = new byte[BLOCK_SIZE];
        for (int block = (int) (total / BLOCK_SIZE); block > 0; block--) {
            int len = BLOCK_SIZE;
            if (in.read(backup, 0, len) != len) {   // Cyphertext block.
                throw new IOException("Unexpected end of file contents");
            }
            cipher.update(backup, 0, len, text);
            hmac.update(backup, 0, len);
            if (block == 1) {
                int last = in.read();   // Last block size mod 16.
                debug("Last block size mod 16: " + last);
                len = (last > 0 ? last : BLOCK_SIZE);
            }
            out.write(text, 0, len);
        }
        out.write(cipher.doFinal());

        backup = hmac.doFinal();
        text = new byte[SHA_SIZE];
        readBytes(in, text);    // HMAC and authenticity test.
        if (!Arrays.equals(backup, text)) {
            throw new IOException("Message has been altered or password incorrect");
        }
        debug("HMAC2: ", text);
    } catch (InvalidKeyException e) {
        throw new GeneralSecurityException(JCE_EXCEPTION_MESSAGE, e);
    }
}

到目前为止的ObjC方法:

- (void)decrypt:(unsigned long long)filesize in:(NSFileHandle *)in out:(NSOutputStream *)out {
long total = 3 + 1 + 1 + BLOCK_SIZE + BLOCK_SIZE + KEY_SIZE + SHA_SIZE + 1 + SHA_SIZE;
int version;

int byteCounter = 0;

NSData *buffer = nil;
buffer = [in readDataOfLength:total];

NSData *headerData = [self getSubDataFrom:byteCounter To:3 withData:buffer];
byteCounter += 3;

NSString *text  = [[NSString alloc] initWithData:headerData encoding:NSUTF8StringEncoding];
NSLog(@"header: %@", text);

if(![text isEqualToString:@"AES"]) {
    NSLog(@"Invalid file header!");
    return;
}

NSData *verData = [self getSubDataFrom:byteCounter To:1 withData:buffer];
version = [[self returnHexRepForData:verData] intValue];
byteCounter += 1;
NSLog(@"version: %d", version);

if(version < 1 || version > 2) {
    NSLog(@"Unsupported version number: %d", version);
    return;
}

if(version == 2) {
    int len = 0;

    do {
        NSData *ext1 = [self getSubDataFrom:byteCounter To:1 withData:buffer];
        int ext1byte = [[self returnHexRepForData:ext1] intValue];
        byteCounter++;

        NSData *ext2 = [self getSubDataFrom:byteCounter To:1 withData:buffer];
        int ext2byte = [[self returnHexRepForData:ext2] intValue];
        byteCounter++;

        len = ((0xff & (int) ext1byte) << 8) | (0xff & (int) ext2byte);

        total += 2 + len;

        NSLog(@"Skipped extension sized: %d",len);

    } while (len != 0);
}

uint8_t iv[BLOCK_SIZE];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
}

2 个答案:

答案 0 :(得分:0)

在部分攻击问题时,java方法在一个函数中做了几件事。

  1. 阅读文件。获取加密密钥和iv。
  2. 确定填充(如果有)。
  3. 与CCCrypt解密。
  4. 使用调用它们的整体方法,在单独的方法中执行所有这些操作。如果提供所有相同的输入,CCCrypt的结果将与Java实现匹配。

答案 1 :(得分:0)

我通过将C(Linux)源代码移植到iOS中来实现目标......