加密的本地存储区

EncryptedLocalStore 类 (ELS) 提供的加密本地存储机制可用作存储应用程序隐私数据的小缓存。ELS 数据不能在应用程序之间实现共享。使用 ELS 的目的在于,使应用程序可轻松存储重新创建的项目,如登录凭据及其他隐私信息。如下面“加密本地存储区的限制”和“最佳做法”中列出的内容,ELS 数据不应被视为永久数据。

注: 除了加密本地存储区之外,AIR 还可以对 SQL 数据库中存储的内容进行加密。有关详细信息,请参阅对 SQL 数据库使用加密

您可能想使用加密本地存储区来缓存必须保护的信息,如用于获取 Web 服务的登录凭据。ELS 适合存储不得向其他用户公开的信息。但是,使用同一用户帐户运行的其他进程仍可访问它存储的数据。因此,它不适用于合保护秘密应用程序数据,例如 DRM 或加密密钥。

在桌面平台上,通过在 Windows 中使用 DPAPI,在 Mac OS 和 iOS 中使用 KeyChain,以及在 Linux 中使用 KeyRing 或 KWallet,AIR 将加密本地存储区与每个应用程序和用户相关联。加密的本地存储区使用 AES-CBC 128 位加密。

在 Android 上,EncryptedLocalStorage 类存储的数据未加密。而该数据由操作系统提供的用户级别的安全性进行保护。Android 操作系统为每个应用程序分配一个单独的用户 ID。应用程序只能访问自己的文件和在公共位置创建的文件(如移动存储卡)。注意,在 Android 的“根”设备上,使用根权限运行的应用程序可以访问其他应用程序的文件。因此,在根设备上,加密的本地存储不提供与非根设备上级别一样高的数据保护。

加密的本地存储区中的信息仅可用于应用程序安全沙箱中的 AIR 应用程序内容。

如果更新 AIR 应用程序,则更新后的版本仍能够访问加密本地存储区中的任何现有数据,以下情况除外:

  • 使用 stronglyBound 参数添加的项目设置为 true

  • 现有和更新版本发布的时间都早于 AIR 1.5.3,并且更新使用迁移签名进行签名。

加密本地存储区的限制

加密本地存储区中的数据由用户操作系统帐户凭据进行保护。除非可以用该用户的身份进行登录,否则其他实体无法访问存储区中的数据。但是,已通过身份验证的用户运行的其他应用程序仍可访问这些数据。

由于用户必须经过身份验证才能使这些攻击生效,所以用户的隐私数据仍然受到保护(除非用户的帐户本身已被泄漏)。但是,应用程序希望对用户保密的数据(如用于授权或数字版权管理的密钥)是不安全的。因此,ELS 不是存储此类信息的适当位置。它只适合存储用户的隐私数据,如密码。

ELS 中的数据可能由于各种原因而丢失。例如,用户可能会卸载应用程序并删除加密的文件。或者,发行商 ID 可能由于更新而发生更改。因此,应将 ELS 用作私有缓存,而不是永久性数据存储。

stronglyBound 参数已弃用,不应将其设置为 true。此参数设置为 true 后,不会对数据进行任何额外保护。同时,即使发行商 ID 保持不变,应用程序每次更新后都会丢失对数据的访问。

如果存储的数据超过 10MB,则加密的本地存储区的运行速度可能变慢。

当卸载 AIR 应用程序时,卸载程序不会删除存储在加密的本地存储区中的数据。

最佳做法

使用 ELS 的最佳做法包括:

  • 使用 ELS 存储例如密码等敏感用户数据(将 stronglyBound 设置为 false)

  • 不使用 ELS 存储应用程序机密(如 DRM 密钥或授权令牌)。

  • 为应用程序提供在 ELS 数据丢失的情况下重新创建 ELS 中存储的数据的方法。例如,在必要时,通过提示用户重新输入帐户凭据来实现此操作。

  • 不要使用 stronglyBound 参数。

  • 如果 stronglyBound 确实设置为 true,则在更新期间不要迁移存储的项目。而应在更新后重新创建数据。

  • 仅存储较少数量的数据。对于大量数据,请使用加密的 AIR SQL 数据库。

将数据添加到加密本地存储区

使用 EncryptedLocalStore 类的 setItem() 静态方法将数据存储在本地存储区中。数据存储在哈希表中(使用字符串作为键,以字节数组的形式存储数据)。

例如,下面的代码将一个字符串存储在加密的本地存储区中:

var str:String = "Bob"; 
var bytes:ByteArray = new ByteArray(); 
bytes.writeUTFBytes(str); 
EncryptedLocalStore.setItem("firstName", bytes);

setItem() 方法的第三个参数(即 stronglyBound 参数)是可选参数。如果此参数设置为 true,则加密本地存储区会将存储的项目绑定到存储 AIR 应用程序的数字签名和位:

var str:String = "Bob"; 
var bytes:ByteArray = new ByteArray(); 
bytes.writeUTFBytes(str); 
EncryptedLocalStore.setItem("firstName", bytes, false); 

对于将 stronglyBound 设置为 true 后存储的项目,在以后调用 getItem() 时,仅当调用方 AIR 应用程序与存储方应用程序相同时才会成功(前提是应用程序目录中的文件未发生数据更改)。如果执行调用的 AIR 应用程序与执行存储的应用程序不同,则当您对强绑定项目调用 getItem() 时,该应用程序将引发 Error 异常。如果您更新应用程序,则该应用程序将无法读取先前写入到加密的本地存储区中的强绑定数据。忽略在移动设备上将 stronglyBound 设置为 true;始终将该参数视为 false

如果将 stronglyBound 参数设置为 false(默认值),则只有发行商 ID 需要保持不变,供应用程序读取数据。应用程序的位可以更改(需由同一发行商对这些位进行签名),但不需要与存储数据的应用程序中的位完全相同。如果更新后的应用程序与原始应用程序的发行商 ID 相同,则可继续访问这些数据。

注: 实际上,将 stronglyBound 设置为 true 不会增加任何额外数据保护。“恶意”用户仍可更改应用程序,从而访问存储在 ELS 中的项目。而且,无论将 stronglyBound 设置为 true 还是 false,保护数据免受外部非用户威胁的强度都是一样的。出于以上原因,建议不要将 stronglyBound 设置为 true

访问加密的本地存储区中的数据

您可以使用 EncryptedLocalStore.getItem() 方法从加密的本地存储区中检索值,如下例所示:

var storedValue:ByteArray = EncryptedLocalStore.getItem("firstName"); 
trace(storedValue.readUTFBytes(storedValue.length)); // "Bob" 

从加密的本地存储区中删除数据

您可以使用 EncryptedLocalStore.removeItem() 方法删除加密的本地存储区中的值,如下例所示:

EncryptedLocalStore.removeItem("firstName"); 

您可以通过调用 EncryptedLocalStore.reset() 方法清除加密的本地存储区中的所有数据,如下例所示:

EncryptedLocalStore.reset();