Android中鎖定文件的方法


androidSDK中並沒有鎖定文件相關的api.

但是android是基於linux操作系統的,linux比較底層,靈活性也更大,為了實現鎖定文件的效果,大概有以下幾種辦法:

  1. 用chmod命令修改文件讀寫權限
  2. 利用linux中的多線程獨占鎖,啟動一個長期占用文件的后台線程
  3. 使用文件IO流,對文件的前1K字節進行加密,使其不能被識別為文件,或者讀不出有意義的數據

這三種方法中最優雅的是第三種方法,下面結合金山文件鎖的源碼和技術文章等來詳解第三種方法.

 

==================================技術分割線===================================

金山文件鎖會在SD卡下生成一個.ksbox文件夾,這個文件夾下會保存加密后的文件.這個文件夾下有一個db.sqlite數據庫文件,使用SQLite Database Browser打開后可以看到被加密文件的列表.

接下來去反編譯金山的apk,最開始我使用的工具是dex2jar和java decompiler然而並沒有看到加密核心代碼.之后使用Apk IDE來反編譯.

相關的核心代碼在com/ijinshan/mPrivacy/c/j.smali文件中,里面是一些類似匯編的代碼:

method public final read([BII)I

    .locals 7

    .parameter

    .parameter

    .parameter

 

    .prologue

    const/4 v6, 0x0

 

    const/16 v5, 0x400

 

    .line 61

    iget-object v0, p0, Lcom/ijinshan/mPrivacy/c/j;->a:Ljava/io/FileInputStream;

 

    invoke-virtual {v0, p1, p2, p3}, Ljava/io/FileInputStream;->read([BII)I

 

    move-result v0

 

    .line 63

    const/4 v1, -0x1

 

    if-ne v0, v1, :cond_0

 

    .line 103

    :goto_0

    return v0

 

    .line 70

    :cond_0

    iget-wide v1, p0, Lcom/ijinshan/mPrivacy/c/j;->f:J

 

    const-wide/16 v3, 0x400

 

    cmp-long v1, v1, v3

 

    if-gtz v1, :cond_5

 

    .line 73

    iget-boolean v1, p0, Lcom/ijinshan/mPrivacy/c/j;->e:Z

 

    if-nez v1, :cond_1

 

    .line 75

    iget-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->c:Lcom/ijinshan/mPrivacy/c/g;

 

    iget-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->b:Ljava/lang/String;

 

    invoke-static {v1}, Lcom/ijinshan/mPrivacy/c/g;->b(Ljava/lang/String;)[B

 

    move-result-object v1

 

    iput-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    .line 76

    iget-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    if-eqz v1, :cond_1

 

    .line 77

    const/4 v1, 0x1

 

    iput-boolean v1, p0, Lcom/ijinshan/mPrivacy/c/j;->e:Z

 

    .line 80

    :cond_1

    if-ge v0, p3, :cond_3

 

    move v1, v0

 

    .line 82

    :goto_1

    add-int v2, p2, v1

 

    if-gt v2, v5, :cond_4

 

    .line 84

    iget-object v2, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    if-eqz v2, :cond_2

 

    .line 85

    iget-object v2, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    invoke-static {v2, p2, p1, v6, v1}, Ljava/lang/System;->arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V

 

    .line 100

    :cond_2

    :goto_2

    iget-wide v1, p0, Lcom/ijinshan/mPrivacy/c/j;->f:J

 

    int-to-long v3, v0

 

    add-long/2addr v1, v3

 

    iput-wide v1, p0, Lcom/ijinshan/mPrivacy/c/j;->f:J

 

    goto :goto_0

 

    :cond_3

    move v1, p3

 

    .line 80

    goto :goto_1

 

    .line 89

    :cond_4

    if-ge p2, v5, :cond_2

 

    .line 91

    iget-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    if-eqz v1, :cond_2

 

    .line 92

    iget-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    sub-int v2, v5, p2

 

    invoke-static {v1, p2, p1, v6, v2}, Ljava/lang/System;->arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V

 

    goto :goto_2

 

    .line 98

    :cond_5

    const/4 v1, 0x0

 

    iput-object v1, p0, Lcom/ijinshan/mPrivacy/c/j;->d:[B

 

    goto :goto_2

.end method

 

還有一些和它相關聯的函數,代碼比較長就不全貼上來了,參考着文檔對其進行分析的大概了解到金山的做法:

首先創建類繼承InputStream,使用decodeStream函數得到輸入流,重寫read()方法,在方法體中對輸入流的前1K字節進行解密,后面的字節直接從filename文件中讀取.

解密的方法就是讀取filename_e文件,每個字節異或0x6b

這樣就得到了加密前的文件.

===========================技術分割線================================

這種方法算是所有方法中最優雅的方法了,雖然也有缺點(文件被誤刪),但是加解密計算小,只計算前1K字節.文件移動代價小,只要改變一下文件指針,就可以移動文件.速度快穩定性高.是業內主流的解決方案!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM