Golang解析android 備份檔案

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

我參考了一個stackoverflow上的一個項目,java解android備份檔案。然後譯成了golang代碼。
總結:
java語言本身雖然很老,但是人家庫多啊,但是人家的流還真是好用
想念java的第x天。

整體的備份檔案:xx.ab 分為兩部分

  • 不加密部分
  • 加密部分

分析

加密部分

我所解析的一個檔案資訊

    magic            string      version          int    compress         int    encryptionAlg    string    userSaltHex      string    ckSaltHex        string    round            int    userIvHex        string    masterKeyBlobHex string

一些debug資訊,方便瞭解上述具體內容
···
agic: ANDROID BACKUP
Version: 3
Compressed: 1
Algorithm: AES-256
IV: 1539D61DC22C13259102B5F20B7E9C3D
MK: EC78A761EDAE9E578A1CAE125331BF0C1D9178781C1D997711867EE7717EC30B
MK checksum: 944120ED555A34C6559D1793A322B5B59CED1AB8B19275DB7A482984B06ED4A7
key bytes: EC78A761EDAE9E578A1CAE125331BF0C1D9178781C1D997711867EE7717EC30B
salt bytes: D12A67D559DE5B025E7D0C5D41E27A49C9E7E9502F755E23B3E964969E0AA83DD70235E41C5A72BFD2EA0E2112E36E4827AB54F20FDEFC62F353CD557983378B
Calculated MK checksum (use UTF-8: true): 944120ED555A34C6559D1793A322B5B59CED1AB8B19275DB7A482984B06ED4A7
···

按行來說明

  1. magic 有標題的作用
  2. 版本 只支援1-4 v2版本以上要用
  3. 是否壓縮
  4. 採用的密碼編譯演算法
  5. 鹽1 userSalt
  6. 鹽2 ckSalt
  7. rounds
  8. userIvHex
  9. masterkeyBlob 這就是用來加密的密鑰了

2 的一點說明

  • 在版本號碼>2的情況下,用UTF-8儲存資訊

3 的一點說明

  • 如果是壓縮過的,那麼只能用壓縮流進行解

9 的一點說明

  • 這一段由IV+密鑰共同組成

    數組的第一個元素代表了IV的長度

加密部分

之後的內容,全都是採用加密並壓縮過的密鑰流來處理,但是這裡有一個蛋疼的問題,我讀*.ab檔案,讀了前9行後,把之後的內容解密,遇到瞭解密的bug,前面的內容正常,後面就GG了。然後,我的辦法是,把這部份內容寫入一個單獨的檔案中。再進行解密。

處理成Go的痛點

  • go中是否有加密流
  • go中是否有壓縮流
  • go中密鑰產生(填充,是否是java BC專有庫)與java是否一致

最後分析的結果(也許go的流我還不熟)

  • go中無aes cbc加密流
  • go中無壓縮流(java.util.zip.InflaterInputStream 對應go裡的啥?)
  • 手寫pkcs#5 padding
  • 密鑰產生,go沒有jce怎麼搞?

解決方案

go無aes cbc加密流的搞法

先說一下go中cipher 的特點,cbc模式下,這貨會保留上一次加密的狀態,也就是說,

var 加密機加密.文本1加密.文本2//與下面的操作等價var 加密機加密.(文本1+檔案2)

之前我也有一個誤區,就是流加密不等於塊加密。我錯了,其實流加密,就是每次讀一定的位元組數罷了,然後再讀一定的位元組數,與上一次的結果進行相應模式下的操作,如,cbc異或啦。
而塊加密,則是直接把要加密的所有內容一次性讀入記憶體中。
那麼,我用go,可每次唯讀16B的內容加密,好省記憶體呀!還方便最後一次去填充!

func (tool *Filetool) temp2() {    println("cbc方式讀")    fi, _ := os.Open(tool.temp1file)    defer fi.Close()    aesBlockEncrypter, _ := aes.NewCipher(tool.realkey)    aesEncrypter := cipher.NewCBCDecrypter(aesBlockEncrypter, tool.realIV)    fo, _ := os.Create(tool.temp2file)    defer fo.Close()    //tmp := make([]byte, 16)    read := make([]byte, 16)    write := make([]byte, 16)    frist:=true    var n int    for {        n, _ = fi.Read(read)        if n == 0 {            fo.Write(PKCS5UnPadding(write))            break        } else if !frist {            fo.Write(write)        } else {            frist=false        }        aesEncrypter.CryptBlocks(write, read)        //copy(tmp, write)    }}

go中無壓縮流

這個真的很蛋疼,只能把解密之後的內容寫入一個檔案,然後再解密。

func (tool *Filetool) final() {    inputFile, _ := os.Open(tool.temp2file) //變數指向os.Open開啟的檔案時產生的檔案控制代碼    zf, err := zlib.NewReader(inputFile)    if err != nil {        return    }    defer zf.Close()    //tarFilePath = filepath.Join(t.parseBackupTask.backupPath, fmt.Sprintf("backup_%d.tar", api.GetEvidenceID()))    //os.MkdirAll(filepath.Dir(path), os.ModePerm)    tarFile:=tool.outfileh    if err != nil {        return    }    defer tarFile.Close()    io.Copy(tarFile, zf)}

完整代碼等我有空再傳吧

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.