編輯:關於android開發
全磁盤加密是使用一個密鑰來為android設備上所有的用戶數據加密的過程。一旦設備被加密,所有的用戶創建的數據都將會在提交的磁盤之前自動加密,在讀取之前都會自動解密。
Android 5.0中添加了啥注意:升級到Android5.0並且被加密的設備可能會數據恢復出廠後返回一個未加密狀態。在首次啟動時加密的新的Android 5.0設備不能返回到未加密狀態。
Android全磁盤加密基於dm-crypy,他是一個內核特征,工作在塊設備層。出於這個原因,加密是和嵌入式多媒體卡和作為塊設備的閃存設備一起工作的。在YAFFS文件系統中,加密是不可能工作的,他是直接和NAND閃存芯片工作的。
加密算法是帶有CBC和 ESSIV:SHA256的128高級加密標准。主鍵是通過128位AES通過OpenSSL庫被加密的。你必須要使用128位或更大位數的鍵值。
注意:OEMs能夠使用128位或更高位數來加密主鍵。
在Android5.0的發行版中,有四種加密狀態:
默認PIN密碼模式在第一次啟動的時候,設備創建一個隨機生成的128位主鍵,然後使用默認密碼和存儲的salt進行哈希運算。默認密碼是”default_password”。然而,結果散列也需要通過TEE進行簽名,他使用一個簽名的散列來加密主鍵。
你可以在Android源碼文件cryptfs.c中找到默認密碼。
當用戶在設備中設置了PIN或者是密碼,僅僅128位的鍵被重新加密和存儲。(用戶PIN/密碼/模式的改變不會造成用戶數據重新加密)。注意管理的設備可能會受到PIN,模式或密碼的限制。
加密是由init和vold管理的。init調用vold,vold設置位於init中的屬性來觸發事件。系統的其他部分也會根據這些屬性來進行工作,例如報告狀態,查詢密碼,或者是發生致命錯誤的時候及時工廠重置。為了在vold中激活加密特征,系統使用命令行工具vdc’s cryptfs運行命令: checkpw, restart, enablecrypto, changepw, cryptocomplete, verifypw,setfield, getfield, mountdefaultencrypted, getpwtype, getpw, 和clearpw.
為了進行加密,解密或清除/data,/data必須要被掛載。然而,為了能夠顯示用戶接口,框架一定要運行並且框架需要/data來運行。為了解決這個難題,在/data中會掛載一個臨時的文件系統。這使得安卓能夠提示密碼,顯示進展,或在需要的時候進行數據擦除。在從臨時文件系統到真實的/data文件系統的轉換的時候強加了一些限制,系統必須要停止打開臨時文件系統中文件的每一個進程,然後在真實的/data文件系統中重啟這些進程。為了這樣做,所有的服務都必須在這三個組中的一個中:core,main和late_start。
core:在啟動後永遠不關閉main:在磁盤密碼輸入後關機在重啟late_restart:在/data被解密並且掛載之前不要開始為了激發這些行為,vold.decrypt屬性被設置為各種字符串。為了殺死並且重啟服務,init命令為:
class_reset:停止服務,並且允許使用class_start進行重啟。class_start:重啟服務class_stop:停止一個服務,並且添加一個SVC_DISABLED標志。停止的服務不向class_start做出回應。流對於一個加密的設備來說有四個流。一個設備僅僅加密一次,然後遵循一個正常的啟動流。
加密一個原先未加密的設備:使用forceencrypt加密一個新的設備:在首次啟動的時候強制性加密(在Android L開始)加密一個存在的設備:用戶初始化加密(Android K並且更早)啟動一個加密設備:啟動一個不帶密碼的加密設備:啟動一個沒有設置密碼的加密設備(相關的設備運Android 5.0或更新)開始一個帶有密碼的加密設備:啟動一個設置密碼的加密設備。除了這些流,設備加密/data就會失敗。每一個流在下面都會詳細解釋。
加密一個帶有/forceencrypt新設備這是一個Android 5.0設備正常的首次啟動。
/data沒有被加密,但是必須要進行加密。因為 /forceencrypt委托他這樣做。卸載/data
開始加密/data
vold.decrypt = "trigger_encryption" triggers init.rc, which will cause vold to encrypt /data with no password. (None is set because this should be a new device.)
掛載tmpfsvold掛載一個臨時文件系統 /data(從ro.crypto.tmpfs_options中使用tmpfs選項),並且設置屬性vold.encrypt_progress 為0.vold為啟動一個加密的系統准備tmpfs /data,並且設置屬性vold.decrypt為trigger_restart_min_framework
提出框架,顯示進度因為該設備幾乎沒有數據去加密了,進度條也不會顯示了,因為加密過程會很快。
當/data被加密之後,卸下框架vold設置vold.decrypt為 開始defaultcrypto 服務的trigger_default_encryption。(這個會開始下面的流用於掛載一個默認的加密用戶數據)。trigger_default_encryption檢查加密類型來查看/data是否是帶有密碼被加密的。因為Android5.0設備在首次啟動的時候被加密,應該沒有密碼設置;因此我們解密並且掛載/data。
掛載/datainit然後使用從ro.crypto.tmpfs_options中選出的參數在tmpfs的RAMDisk 中掛載/data,ro.crypto.tmpfs_options是在init.rc中被設置的。
啟動框架設置vold為trigger_restart_framework,他繼續常規的啟動進程。
這種情況發生在你加密一個未加密的Android k或更早版本的設備,該設備被一直到Android L的時候。注意,這個和在K中使用的流是一樣的。
這個進程是用戶初始化的,並且在代碼中被引用作為”就地加密”。當一個空戶選擇去加密一個設備的時候,UI確保電量是完全充電狀態並且AC適配器被插入,所以有足夠的變量來完成加密進程。
警告:如果設備在完成加密之前耗盡電量並且關機了,在部分加密狀態下會留下文件數據。設備必須要工廠重置,所有的數據都會丟失。
為了使能就地加密,vold開始一個循環來讀取真實塊設備的每一個扇區,然後將他寫到加密塊設備中。vold在讀取和寫數據之前,檢查扇區是否正在使用,這會使得在幾乎沒有數據的新設備上加密會很快。
設備狀態:設置ro.crypto.state = "unencrypted" 並且運行 on nonencrypted init觸發器來繼續啟動。
檢查密碼UI在passwd是用戶鎖屏密碼的地方調用帶有命令cryptfs enablecrypto inplace的vold。
卸載框架vold檢查錯誤,如果不能被加密,返回-1,並且在日志中打印原因。如果能夠加密,設置屬性 vold.decrypt為trigger_shutdown_framework。這會使init.rc停止位於類late_start和main中的服務。
卸載/datavold卸載/mnt/sdcard,然後卸載/data。
開始加密/datavold然後設置加密映射,該映射創建一個虛擬加密塊設備,該設備映射到真實的塊設備上,但是當寫入的時候加密每一個扇區,當讀取的時候解密每一個扇區。vold然後創建和編寫加密元數據。
當加密的時候,掛載tmpfsvold掛載一個tmpfs /data(從ro.crypto.tmpfs_options中使用tmpfs選項),並且設置屬性vold.encrypt_progress為0.vold為啟動一個加密系統准備tmpfs /data,並且設置屬性vold.decrypt為trigger_restart_min_framework。
提出框架,顯示進度trigger_restart_min_framework會使init.rc開始一個服務的main類。當框架看到vold.encrypt_progress被設置為0,他就會顯示進度條UI,他每5秒鐘查詢一下屬性然後更新進度條。每次他加密了一部分分區,加密程序就會更新 vold.encrypt_progress。
當/data被加密,重啟當/data被成功加密了,vold會清除位於元數據中的標志ENCRYPTION_IN_PROGRESS,然後重啟。
如果某些原因重啟失敗,vold會設置屬性 vold.encrypt_progress為 error_reboot_failed,並且UI應該會展示一個信息詢問用戶按下按鈕重啟。這種情況永遠也不期望發生。
開啟一個帶有默認加密的加密設備這種情況發生在當你想啟動一個沒有密碼的加密設備的時候。因為Android 5.0設備在首次啟動的時候被加密,應該沒有設置密碼,因此應該是默認加密狀態。
檢測加密的沒有密碼的/data檢測Android設備已被加密,因為/data不能被掛載,並且標志flagsencryptable 或forceencrypt 之一被設置了。vold設置 vold.decrypt為
trigger_default_encryption,他用於啟動defaultcrypto 。trigger_default_encryption 檢查加密類型來查看/data有無密碼加密。
解密/data在塊設備中,創建dm-crypt設備,所以設備已經可以使用。
掛載/datavold掛載加密的/data分區,然後准備一個新的分區。他設置屬性vold.post_fs_data_done 為0,並且設置vold.decrypt為trigger_post_fs_data. 這使得 init.rc運行他的post-fs-data命令。他們會創建必要的目錄和鏈接,然後設置vold.post_fs_data_done為1.
一旦vold在那個屬性中看到1,他設置屬性vold.decrypt為 trigger_restart_framework。這會使得init.rc再次啟動位於類main中的服務。然後自從啟動後,第一次開啟位於類late_start中的服務。
開啟框架現在,框架使用加密的/data啟動所有他的服務,並且系統也可以正常使用了。
開啟一個不是默認加密的加密設備這種情況發生在,當你啟動一個設置密碼的加密設備的時候。這個設備的密碼可以是pin,模式或密碼。
檢測帶有密碼的加密設備檢測到Android設備被加密了,因為標志ro.crypto.state = “encrypted”
vold設置vold.decrypt為trigger_restart_min_framework,因為/data是使用密碼加密的。
掛載tmpfsinit設置下面5個屬性來保存初始化掛載選項,這些選項用於帶參數的/data。他們是從init.rc. vold中傳過來的,使用這些屬性來設置加密映射。
ro.crypto.fs_typero.crypto.fs_real_blkdevro.crypto.fs_mnt_pointro.crypto.fs_optionsro.crypto.fs_flags (ASCII 8-digit hex number preceded by 0x)啟動框架以提示輸入密碼框架啟動,然後查看vold.decrypt是否被設置為 trigger_restart_min_framework。這告訴框架這是在tmpfs /data磁盤中啟動的,他需要獲取用戶密碼。
首先,他需要確定磁盤是否被正確加密。他發送命令cryptfs cryptocomplete到vold。如果加密完全成功,則返回0.如果內部錯誤,返回-1.或者是如果加密沒有完全成功返回-2。vold通過查看用於CRYPTO_ENCRYPTION_IN_PROGRESS標志的加密元數據來決定這個。如果被設置了,加密進程被中斷了,在設備中沒有可用的數據。如果vold返回一個錯誤,UI應該向用戶展示一個信息來重啟和工廠重置設備,並且給用戶一個按鈕來這樣做。
解密帶有密碼的數據一旦cryptfs cryptocomplete成功了,框架就會展示一個UI詢問磁盤密碼。UI通過向vold發送命令cryptfs checkpw 來檢查密碼。如果密碼正確(這是由正確掛載到臨時位置的加密/data決定的,然後卸載塔),vold在屬性ro.crypto.fs_crypto_blkdev中保存解密塊設備的名稱,並且向UI返回狀態0.如果密碼不正確,向UI返回-1。
停止框架UI彈出一個加密啟動圖形,然後使用命令 cryptfs restart. vold設置屬性vold.decrypt為trigger_reset_main來調用vold,這樣會使init.rc 去處理class_reset main。這會在主類中停止所有的服務,這允許tmpfs /data被卸載。
掛載/datavold然後掛載解密/data分區,然後准備新的分區(如果是帶有可擦選項加密的話,是不會被准備的,這在首次發行的時候是不支持的)。他設置屬性vold.post_fs_data_done為0,然後設置vold.decrypt為trigger_post_fs_data。這會使init.rc來運行他的post-fs-data命令。他們會創建任何必要的目錄或者是鏈接,然後設置vold.post_fs_data_done為1.一旦vold在那個屬性中看到1,他便會設置屬性 vold.decrypt 為trigger_restart_framework.這會使init.rc重新開始位於類main中的服務,並且從啟動後第一次啟動位於類late_start中的服務。
開啟全框架現在,框架就會使用解密/data文件系統啟動他所有的服務,並且系統准備投入使用。
失敗一個解密失敗的設備可能是下面幾個原因。設備使用常規系列步驟開始啟動:
檢測帶有密碼的加密設備掛載tmpfs開啟框架提示輸入密碼但是框架打開之後,設備可能會遇到一些錯誤:
密碼匹配但是不能解密數據用戶輸入錯誤密碼30次如果這些錯誤沒有解決,提示用戶進行工廠清除:
如果vold在加密過程中檢測到一個錯誤,並且如果數據還沒有被解密,框架啟動了,vold設置屬性vold.encrypt_progress為error_not_encrypted。UI提示用戶重啟,並且警告他們加密過程沒有開始。如果在框架卸下之後,在進度條開啟之前,錯誤發生了,vold將會重啟系統。如果重啟失敗,他會設置vold.encrypt_progress為error_shutting_down,並且返回-1;但是將不會有任何事情捕獲錯誤。這是不希望發生的。
如果vold在加密過程中檢測到一個錯誤,他會設置 vold.encrypt_progress為error_partially_encrypted,並且返回-1.UI應該會展示一個信息框說加密失敗,並且提供一個按鈕提示用戶恢復出廠重置設備。
存儲加密鍵加密鍵值存儲在加密元數據中。硬件支持是通過使用可信環境簽名實現的。在以前,我們通過向用戶密碼和存儲salt應用scrypt來加密主鍵。為了使鍵抵抗攻擊,我們通過使用一個存儲的TEE鍵簽名一個組合鍵值來繼承他的算法。組合簽名通過一個scrypt的應用編程一個合適的密鑰長度。這個密鑰被使用去加密和解密主密鑰。下面是存儲這個密鑰的過程:
生成隨機16位的磁盤加密密鑰(DEK)和16為salt。向用戶密碼應用scrypt和salt來生成32位的中間密鑰1(IK1)。使用0填充IK1到硬件綁定私鑰(HBK)的大小。特別的,我們填充為: 00 || IK1 || 00..00;一個0位:32 IK1 bytes, 223 zero bytes.簽名帶有HBK的IK1來生成256位的IK2將scrypt應用到IK2和salt中來生成32為IK3使用IK3的前16位作為KEK,後16位作為IV加密帶有AES_CBS,帶有密鑰KEK的DEK,並且初始化向量IV修改密碼當用戶選擇在設置中修改或移除密碼的時候,UI發送命令cryptfs changepw到vold中,vold重新加密帶有新密碼的磁盤主密鑰。
vold和init通過設置屬性相互交流。下面一些用於加密的可用屬性。
ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption
android studio上的基本動畫實現(第一篇),androidstudiohello,各位小伙伴們,在很多小伙伴們剛剛開始學習android的時候,常常會有一些p
Android Tab,androidtab原文地址:http://blog.csdn.net/crazy1235/article/details/42678877 效果
閱讀《Android 從入門到精通》(16)——表狀時鐘 表狀時鐘(AnalogClock) java.lang.Object; android.view.View; a
Android實現原生側滑菜單的超簡單方式 先來看看效果圖 當你點擊菜單可以更改圖標,例如點擊happy,首頁就會變一個笑臉,這個實現的過程超級簡單