如何在iOS中检查zip文件是否受密码保护?

4
我正在使用ZipArchive来在iOS应用程序中解压缩zip文件,但我想在打开文件之前知道它是否受密码保护,以便可以将密码传递给UnZipOpenFile函数。

首先尝试正常打开,如果不成功,则尝试使用密码,提示用户输入密码。 - Rahul Vyas
4个回答

4

zip文件的密码不记录在头部,而是记录在zip文件中的各个文件条目中。

因此,您需要检查zip中的所有文件。

请将此功能添加到ZipArchive中。

-(BOOL) UnzipIsEncrypted {

    int ret = unzGoToFirstFile( _unzFile );
    if (ret == UNZ_OK) {
        do {
            ret = unzOpenCurrentFile( _unzFile );
            if( ret!=UNZ_OK ) {
                return NO;
            }
            unz_file_info   fileInfo ={0};
            ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
            if (ret!= UNZ_OK) {
                return NO;
            }
            else if((fileInfo.flag & 1) == 1) {
                return YES;
            }

            unzCloseCurrentFile( _unzFile );
            ret = unzGoToNextFile( _unzFile );
        } while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );

    }

    return NO;
}

这个功能甚至对于已锁定的压缩文件也无法正常工作。对于已锁定的文件,如果返回值不等于UNZ_OK,则会在此处返回。有什么想法吗? - undefined

3
实际上,我在zipArchive中找不到检测文件是否加密的功能,所以我检查文件头以确定它是否受到密码保护,如下链接所述: http://secureartisan.wordpress.com/2008/11/04/analysis-of-encrypted-zip-files/
-(BOOL) IsEncrypted:(NSString*)path
{
    NSData* fileData = [NSData dataWithContentsOfFile:path];
    NSData* generalBitFlag = [fileData subdataWithRange:NSMakeRange(6, 2)];
    NSString* genralBitFlgStr = [generalBitFlag description];

    if ([genralBitFlgStr characterAtIndex:2]!='0')
    {
        return true;
    }
    else
    {
        return false;
    }
}

感谢您的支持。

只有一个问题,如果密码是空字符串,这将无法工作。有没有办法检测密码是否为空? - LiangWang
不幸的是,我没有尝试过这种情况。此外,我尝试了我的方法,在某些情况下失败了,因为通用位标志不等于零,尽管它没有受到密码保护。这就是为什么我使用了被标记为已回答并且有效的IPaPa解决方案。 - Eman.H
如果压缩文件中的所有文件都在根文件夹内,这种方法将失败。虽然对于单个文件的压缩文件很好用。 - bikram990

2
我本人没有使用过ZipArchive,但通过查看代码,似乎可以先使用没有密码参数的UnzipOpenFile变量,尝试调用UnzipFileTo。如果失败了,您可以重新打开一个带有密码的压缩文件,并再次调用UnzipFileTo。这样做的问题是您将无法区分无效的ZIP文件和使用无效密码之间的区别。
如果您确实需要知道该文件是否已加密,则可能需要自己添加这个功能(未经测试的代码):
请将此添加到minizip中的unzip.c中:
extern int ZEXPORT unzIsEncrypted (file)
    unzFile file;
{
   return ((unz_s*)file)->encrypted;
}

这是关于unzip.h的内容:
extern int ZEXPORT unzIsEncrypted OF((unzFile file));

这是关于ZipArchive.mm的内容:
- (BOOL)ZipIsEncrypted {
    return unzIsEncrypted(_unzFile);
}

这是关于ZipArchive.h的内容:
- (BOOL)ZipIsEncrypted;

在调用UnzipFileTo之后使用它。


我也在想ZipArchive的问题,然后我找到了这个!!!太神奇了!!! - virindh
unz_s未定义,你是如何使其工作的? - undefined
抱歉,不知道,unz_s结构体已经改名了吗?还是你把它添加到了错误的源文件中? - undefined

1

我正在解压一个超过50MB的加密文件,所以将整个文件加载到NSData中是一个问题。因此,我做了修改并使用了以下代码:

-(BOOL) IsEncrypted:(NSString*)path

{

    NSInteger chunkSize = 1024     //Read 1KB chunks.
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSData *fileData = [handle readDataOfLength:chunkSize];
    NSData* generalBitFlag = [fileData subdataWithRange:NSMakeRange(6, 2)];
    NSString* genralBitFlgStr = [generalBitFlag description];


    if ([genralBitFlgStr characterAtIndex:2]!='0')
    {
        return true;
    }
    else
    {
        return false;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接