iOS開發(fā)加解密算法-基礎(chǔ)篇(3)<大文件加解密>

一饺鹃、 需求驅(qū)動(dòng)功能開發(fā),項(xiàng)目的需求是文件先經(jīng)過(guò)服務(wù)端加密,客戶端下載完成后再進(jìn)行解密后使用,最終確認(rèn)的方案是對(duì)文件分段加密,加密后再拼接成新的文件报嵌,最后在實(shí)現(xiàn)的時(shí)候遇到過(guò)一些坑<內(nèi)存問(wèn)題>凶伙。該篇只是介紹我們項(xiàng)目中使用的文件加密方案,并不代表移動(dòng)端開發(fā)主流文件加密的方案

</br>

二、實(shí)現(xiàn):對(duì)大文件進(jìn)行分段切割

首先想到的就是OC自帶的文件處理類NSFileHandle修档,不過(guò)在使用的時(shí)候遇到了一個(gè)運(yùn)存無(wú)法消除的問(wèn)題,雖然可以用NSFilehandlereadDataOfLengthseekToFileOffset的兩個(gè)方法達(dá)到分段讀取文件的功能,但是每次調(diào)用的時(shí)候程序的內(nèi)存是疊加的,文件多大需要消耗的內(nèi)存就有多大,當(dāng)需要的內(nèi)存大于程序的上限的時(shí)候赌髓,就會(huì)造成程序的閃退。


OC的方法雖然能實(shí)現(xiàn)功能,但是性能有不滿足要求冷冗,因?yàn)镃語(yǔ)言自帶標(biāo)準(zhǔn)I/O庫(kù),就試著用C語(yǔ)言寫了個(gè)文件分段讀取的方法,并實(shí)現(xiàn)了內(nèi)存的即時(shí)的釋放,保證了App的性能需求守屉。調(diào)用的方法解釋可以參考:C語(yǔ)言文件操作函數(shù)|c語(yǔ)言文件讀寫函數(shù)fopen方法參數(shù)說(shuō)明參見百科,具體方法實(shí)現(xiàn)如下:

/**
 *  解密視文件,主要思路是先找到待解密的文件,將解密的文件存放與臨時(shí)文件下,
 *  解密完成將加密的文件刪除再將解密完成的文件替換成原文件的名字
 *
 *  @param mediaPath 文件路徑
 *  @param index     文件路徑下標(biāo)
 *
 *  @return 是否解密成功
 */
- (BOOL)addDecryptFileWithMediaPath:(NSString *)mediaPath index:(NSInteger)index  header:(NSInteger)header key:(NSInteger)key{
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *subPath = mediaPath;
    // 文件類型
    NSString *pathExtension = [subPath pathExtension];
    // 文件路徑的前路徑
    NSString *prePath = [subPath stringByDeletingLastPathComponent];
    // 當(dāng)前文件名 主要采用的是創(chuàng)建一個(gè)
    NSString *tempfilePath = [NSString stringWithFormat:@"%@/ios_temp_%ld.%@",prePath,index,pathExtension];
    [manager removeItemAtPath:tempfilePath error:nil];
    [manager createFileAtPath:tempfilePath contents:nil attributes:nil];
    // 創(chuàng)建讀寫FILE
    FILE *readFile;
    FILE *writeFile;
    //打開發(fā)文件
    readFile = fopen([subPath cStringUsingEncoding:NSUTF8StringEncoding], "rb+");
    writeFile = fopen([tempfilePath cStringUsingEncoding:NSUTF8StringEncoding], "a+");
   //獲取文件屬性信息
    NSDictionary *attributes = [manager attributesOfItemAtPath:subPath error:nil];
    //獲取文件字節(jié)總長(zhǎng)度
    self.fileLength = ((NSNumber *)[attributes objectForKey:@"NSFileSize"]).integerValue;
    int decodeKey = (int)key;
    //根據(jù)我們的加密頭和加密參數(shù)判斷是否需要解密
    if (self.fileLength > header) {
        //如果符合解密條件將當(dāng)前初始解密文件長(zhǎng)度設(shè)置成頭的長(zhǎng)度<header是加密的時(shí)候添加上的在解密的時(shí)候需要
先將header的長(zhǎng)度去除再進(jìn)行解密>
        self.currnentLength = header;
        //調(diào)用解密方法
        BOOL isSuc =  decodeFile(readFile, self.fileLength, self.currnentLength, writeFile,decodeKey);
        if (isSuc) {
            if([manager removeItemAtPath:mediaPath error:nil]){
                isSuc =  [manager moveItemAtPath:tempfilePath toPath:mediaPath error:nil];
            }else{
                isSuc = NO;
            }
        }
        return isSuc;
    }else{
        return NO;
    }
}

=============================我是分割線============================

/**
 *  C函數(shù)解密文件的方法
 *
 *  @param file         待解密的文件File
 *  @param fileLength   文件長(zhǎng)度
 *  @param currentLegth 當(dāng)前解密的文件長(zhǎng)度
 *  @param direcFile    目標(biāo)存儲(chǔ)目錄
 */
BOOL decodeFile(FILE *file,long fileLength,long currentLegth,FILE *direcFile,int key){
    BOOL isSucessed;
//分段最大讀取長(zhǎng)度 1MB
    NSInteger readLength = 1024 * 1024 * 1;
    // 如果文件長(zhǎng)度減去當(dāng)前解密到的文件長(zhǎng)度還大于分段最大讀取長(zhǎng)度則采用遞歸調(diào)用解密
    if (fileLength - currentLegth > readLength) {
        // 指針指向首字節(jié)
        //讀取文件
        // 成功蒿辙,返回0拇泛,失敗返回-1
        int set = fseek(file, currentLegth, SEEK_SET);
        if (set == 0) {
            //設(shè)置buffer保存分段讀取文件的Data值
            Byte *buffer = malloc(sizeof(Byte) * readLength);
            fread(buffer, readLength, sizeof(Byte), file);
           //讀取成功后設(shè)置當(dāng)前解密長(zhǎng)度
            currentLegth += readLength;
            //設(shè)置讀取位置
            // 解密方法  可以在此基礎(chǔ)上采用其他的加解密<RSA/AES>
            for (int i = 0 ; i < readLength; i++) {
                *(buffer + i ) -= key;
            }
            // 將解密后的文件流寫入解密目標(biāo)文件
            size_t writedData =  fwrite(buffer, sizeof(Byte), readLength, direcFile);
            if (writedData == readLength) {
                isSucessed = YES;
            }else{
                isSucessed = NO;
            }
          // 釋放內(nèi)存  
            free(buffer);
            if (isSucessed) {
                // 遞歸調(diào)用
                return  decodeFile(file, fileLength, currentLegth,direcFile,key);
            }else{
                return isSucessed;
            }}}else{//如果文件長(zhǎng)度減去當(dāng)前長(zhǎng)度小于最小分段讀取長(zhǎng)度 則跳出遞歸完成解密
                // 大于0的話繼續(xù)解密
              if(fileLength - currentLegth  > 0){
            long length = fileLength - currentLegth;
            int set = fseek(file, currentLegth, SEEK_SET);
            if (set == 0) {
                Byte *buffer = malloc(sizeof(Byte) * length);
                fread(buffer, length, sizeof(Byte), file);
                currentLegth += length;
                //設(shè)置讀取位置
                for (int i = 0 ; i < length; i++) {
                    *(buffer + i ) -= key;
                }
                size_t writedData = fwrite(buffer, sizeof(Byte), length, direcFile);
                printf("最終-fseek--%d",set);
                if (writedData == length) {
                    isSucessed = YES;
                }else{
                    isSucessed = NO;
                }
                // 釋放內(nèi)存
                free(buffer);
                // 關(guān)閉文件
                fclose(file);
                fclose(direcFile);
            }
        }
    }
    return isSucessed;
}

Demo地址

如有不當(dāng)之處歡迎指正。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末思灌,一起剝皮案震驚了整個(gè)濱河市俺叭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泰偿,老刑警劉巖熄守,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異耗跛,居然都是意外死亡裕照,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門课兄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)牍氛,“玉大人,你說(shuō)我怎么就攤上這事烟阐“峥。” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蜒茄,是天一觀的道長(zhǎng)唉擂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)檀葛,這世上最難降的妖魔是什么玩祟? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮屿聋,結(jié)果婚禮上空扎,老公的妹妹穿的比我還像新娘藏鹊。我一直安慰自己,他們只是感情好转锈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布盘寡。 她就那樣靜靜地躺著,像睡著了一般撮慨。 火紅的嫁衣襯著肌膚如雪竿痰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天砌溺,我揣著相機(jī)與錄音影涉,去河邊找鬼。 笑死规伐,一個(gè)胖子當(dāng)著我的面吹牛蟹倾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播楷力,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼喊式,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了萧朝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤夏哭,失蹤者是張志新(化名)和其女友劉穎检柬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竖配,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡何址,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了进胯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片用爪。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖胁镐,靈堂內(nèi)的尸體忽然破棺而出偎血,到底是詐尸還是另有隱情,我是刑警寧澤盯漂,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布颇玷,位于F島的核電站,受9級(jí)特大地震影響就缆,放射性物質(zhì)發(fā)生泄漏帖渠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一竭宰、第九天 我趴在偏房一處隱蔽的房頂上張望空郊。 院中可真熱鬧份招,春花似錦、人聲如沸狞甚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)入愧。三九已至鄙漏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棺蛛,已是汗流浹背怔蚌。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旁赊,地道東北人桦踊。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像终畅,于是被迫代替她去往敵國(guó)和親籍胯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 項(xiàng)目也快兩年了,項(xiàng)目這么長(zhǎng)時(shí)間下來(lái)經(jīng)歷了各種加解密算法,坑也踩過(guò)不少.現(xiàn)在把項(xiàng)目中使用過(guò)一些常用的加解密算法總結(jié)一...
    踏遍青山閱讀 2,060評(píng)論 1 12
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蝶涩,服務(wù)發(fā)現(xiàn),斷路器絮识,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 首先羅列一些知識(shí)點(diǎn): 1.加密算法通常分為對(duì)稱性加密算法和非對(duì)稱性加密算法:對(duì)于對(duì)稱性加密算法绿聘,信息接收雙方都需事...
    JonesCxy閱讀 1,386評(píng)論 2 4
  • 嘟噥嘟噥:最近接到一個(gè)任務(wù):在客戶端動(dòng)態(tài)生成RSA密鑰對(duì),然后向服務(wù)器發(fā)送這個(gè)密鑰對(duì)中的公鑰字符串次舌,由服務(wù)器進(jìn)行公...
    TimmyR閱讀 8,029評(píng)論 19 21
  • 忘掉今天犯的錯(cuò)誤熄攘,其實(shí)是對(duì)自己的一種寬恕。是人就會(huì)犯錯(cuò)誤彼念,有時(shí)候就是當(dāng)時(shí)心念一轉(zhuǎn)的瞬間挪圾,于是犯下一些自己銘記的錯(cuò)誤...
    夏煙閱讀 179評(píng)論 0 0