目录
- 按键大小
- 该怎么办
- 默认提供者
- 对称键
- 按键包装
- 使用范例
- 下一步是什么
- 安全提示
按键大小
到目前为止,我们已经尝试加密小的“ 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(提供者,位置)
或者,您可以使用getInstance(algorithm)
,这将根据您的提供程序列表为您返回最优选的实现。
val keyGenerator = KeyGenerator.getInstance(“ AES”)//提供者列表:
// 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之前,使用两个非对称和对称密钥:
而且这还不够,我们能够加密消息,但不能解密消息。