目錄
- 按鍵大小
- 該怎麼辦
- 默認提供者
- 對稱鍵
- 按鍵包裝
- 使用範例
- 下一步是什麼
- 安全提示
按鍵大小
到目前爲止,我們已經嘗試加密小的“ Hello World”消息。讓我們嘗試加密更大的一個,然後再加密250個符號。糟糕,IllegalBlockSizeException
:
RSA原爲 沒有設計 處理大量數據。您只能處理有限長度的消息,這取決於密鑰大小。密鑰越大,則可以加密越大的消息。
請注意,使用大密鑰會增加加密時間,並可能影響應用程序性能。避免在主應用程序線程上進行大數據加密。
在密鑰生成過程中,您可以使用setKeySize()
方法指定密鑰大小:
無法在Android Key Store提供程序中的API 18上自定義密鑰大小。
如果沒有手動設置,將使用默認密鑰大小。默認值可能取決於提供商和平臺版本。對於RSA密鑰,在Android密鑰存儲提供程序中,它是2048位。
支持的RSA密鑰大小爲:512、768、1024、2048、3072、4096。請在文檔中查看有關支持的算法和密鑰大小的更多詳細信息。
您可以使用一個公式來計算最大RSA消息長度。對於n位RSA密鑰(帶有PKCS1填充),直接加密適用於任意二進制消息,最高可達:
<span style="color:#292929">floor(n / 8)-11個字節</span>
對於1024位RSA密鑰(128個字節),您可以使用最大117個字節的消息。因此,我們可以通過RSA密鑰獲得的最長消息可以包含最大468字節(使用4096位密鑰)。
該怎麼辦
這裏的情況非常糟糕,無法使用非對稱密鑰,而對稱僅可從API 23+獲得。並且沒有太多選擇可以逃脫:
- 使用默認的Java提供程序之一創建對稱密鑰。用它加密/解密消息。然後使用
RSA
公共密鑰對該密鑰原始數據進行加密,並將其保存到磁盤中的某個位置。解密時,獲取加密的原始密鑰數據,使用RSA
私鑰對其進行解密,然後將其用於消息解密。 - 在部件上分離大消息,並分別加密/解密每個部件。
我知道您對第二種選擇的想法:“但是我們已經在使用ECB模式,它會自動執行此操作,不是嗎?” (請參閱加密,模式和填充)。
不幸的是,即使使用ECB模式(在Android Key Store提供程序實現中),RSA算法也只能處理一個數據塊,並且如果消息長於一個塊大小,它將崩潰。
要解決此問題,您可以手動分離數據並對其進行處理(模擬ECB模式)。但是同樣,RSA不是爲此類任務設計的。
這將是更安全的繼續第一個選項。
您可以在此處檢查第二個選項的實現。
默認提供者
我們要做的第一件事是:使用默認的Java提供程序之一生成對稱密鑰。
android中最常見的默認Java提供BC
程序是由流行的第三方Java密碼庫提供程序Bouncy Castle創建的提供程序的簡化版本。
KeyGenerator
類負責對稱密鑰的生成。使用其getInstance()
方法之一創建AES
密鑰的實例。
您可以通過調用Security.getProviders()
方法來獲取所有可用的提供程序:
<span style="color:#292929">Security.getProviders()。forEach <strong>{ </strong><em>logi</em>(<strong>it</strong> .name)<strong>}</strong></span>
注意:可用的提供程序可能會因不同的平臺和供應商而異。如果您要查找的提供程序在設備上不存在,則可以通過調用以下方法之一來註冊自己的(或某些第三方)提供程序:
Security.addProvider(提供者)//這樣,您就可以控制
應用程序的首選提供程序。請參見Android中的加密(第2部分)
Security.insertProviderAt(提供者,位置)
//這樣,您就可以控制
應用程序的首選提供程序。請參見Android中的加密(第2部分)
Security.insertProviderAt(提供者,位置)
或者,您可以使用getInstance(algorithm)
,這將根據您的提供程序列表爲您返回最優選的實現。
val keyGenerator = KeyGenerator.getInstance(“ AES”)//提供者列表:
// 1. 1. Android密鑰庫
// 2.自定義提供者
// 3. BC//如果Android密鑰存儲區和自定義提供程序不具有AES算法,則將輸出BC。
keyGenerator.provider.name
//提供者列表:
// 1. 1. Android密鑰庫
// 2.自定義提供者
// 3. BC//如果Android密鑰存儲區和自定義提供程序不具有AES算法,則將輸出BC。
keyGenerator.provider.name
對稱鍵
基本上,我們沒有最多23個API的對稱密鑰。但是從M開始,我們只能使用Android Key Store提供程序中的一個對稱密鑰。
使用KeyGenerator
在對與KeyGenParameterSpec
創建一個。同樣不要忘記Cipher
對稱加密需要的轉換:
按鍵包裝
爲了保護我們的AES
密鑰並將其安全地保存在設備的公共持久性存儲(例如首選項,文件或數據庫)中,我們將使用RSA
存儲在Android Key Store中的密鑰對其進行加密和解密。此過程也稱爲密鑰包裝。
爲此,Cipher
有單獨WRAP_MODE
和wrap()
方法。要解密密鑰,請使用UNWRAP_MODE
和unwrap()
方法。
使用範例
讓我們嘗試使用新方法對大型郵件進行加密和解密:
在M及更高版本上運行,請使用一個對稱密鑰:
在M之前,使用兩個非對稱和對稱密鑰:
而且這還不夠,我們能夠加密消息,但不能解密消息。