[英]Objective C - Decrypt File Encrypted With AESCrypt (www.aescrypt.com)
我需要重寫一個對加密文件進行解密的Java方法,該文件是使用AESCrypt( http://www.aescrypt.com )加密的。 該程序使用自定義文件格式(.aes),需要以自定義方式進行處理。 像我說的已經有一個Java方法。 到目前為止,我已經完成了部分方法的重寫,並且到目前為止,它仍然有效。 但是我被困在某個時候。 我找不到等效的IvParameterSpec
和SecretKeySpec
。
請參閱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));
}
局部攻擊問題,java方法在一個函數中做了幾件事。
在單獨的方法中執行所有這些操作,並在整體方法上調用它們。 如果您提供所有相同的輸入,則CCCrypt的結果將與Java實現匹配。
我通過將C(Linux)源代碼移植到iOS中實現了目標...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.