# @animo-id/expo-secure-environment 中文文档

规范地址：https://npmcn.com/package/%40animo-id/expo-secure-environment/

版本：0\.3\.0
npm 元数据更新时间：2026-10-28T11:06:18.998Z
中文译文更新时间：2026-11-06T04:47:10.756Z
软件包许可：APACHE-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40animo-id/expo-secure-environment
原文对照：https://npmcn.com/package/%40animo-id/expo-secure-environment/?lang=original
项目主页：https://github.com/animo/expo-secure-environment#readme
源码仓库：https://github.com/animo/expo-secure-environment

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：183 kB，46 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：3 个
- peer 依赖：expo \>=53\.0\.0，react \*，react-native \*
- 首次发布：2024-07-26T12:37:09.322Z
- 最新版本发布：2026-10-28T11:06:18.588Z
- 近 30 天下载量：9494（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：22（近 12 个月 2 个）

## 中文简介

博览安全环境

## 安装

```sh
npm install @animo-id/expo-secure-environment
```

也可以使用：`pnpm add @animo-id/expo-secure-environment`、`yarn add @animo-id/expo-secure-environment`、`bun add @animo-id/expo-secure-environment`

## README

# **博览会-安全环境**

#### 电源   

  

 [![](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](https://typescriptlang.org/)[![](https://img.shields.io/npm/v/@animo-id/expo-secure-environment) ](https://www.npmjs.com/package/@animo-id/expo-secure-environment)[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/animo/expo-secure-environment/main/LICENSE)

[开始](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-getting-started)  |  [使用量](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-usage)  |  [捐款](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-contributing)  |  [许可证](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-contributing)

* * *

一个 [博览模块](https://docs.expo.dev/modules/overview/) 利用设备的安全环境(HSM、SE等)锁定的生物鉴别认证支持加密操作.

需要博览会SDK 53或更新。 支持Android 11(API 30)和更新,以及iOS 16.4和更新.

支持更古老的Android版本的应用程序仍然可以包括库. 那边 `isSecureEnvironmentSupported` 财务报告和审定财务报表 `isUserAuthenticationAvailable` 返回时 `false`,其他函数则丢出一个 `SecureEnvironmentNotSupportedError`。 。 。 .

## 开始

首先使用您的软件包管理器安装模块 .

```sh
npm install @animo-id/expo-secure-environment
```

然后预建应用程序, 以使 Expo 模块包可以添加为本地依赖 :

```sh
npx expo prebuild
```

您已经安装并配置了安全环境模块 .

## 使用量

您现在可以导入 `@animo-id/expo-secure-environment` 在您的申请.

### 支持加密算法

**密钥算法**页:1

**签名算法**: ECDSA和SHA256

### 检查支持

密钥被存储在iOS上的"安全飞地"中,并存储在StrongBox,Android上的"信任执行环境"(TEE)或软件中. 检查设备在生成密钥前是否有一个 :

```typescript
import { isSecureEnvironmentSupported } from "@animo-id/expo-secure-environment";

isSecureEnvironmentSupported(); // Secure Enclave on iOS, StrongBox on Android
isSecureEnvironmentSupported({ minimumKeyStorage: "trustedEnvironment" }); // TEE or StrongBox on Android
```

需要用户认证的密钥也需要注册生物鉴别技术或设备密码. 在创建此密钥的流程前选中此项, 例如, 请用户先设置 Face ID :

```typescript
import { isUserAuthenticationAvailable } from "@animo-id/expo-secure-environment";

isUserAuthenticationAvailable(); // biometrics enrolled
isUserAuthenticationAvailable({ methods: ["biometric", "deviceCredential"] }); // biometrics or a device passcode
```

在iOS上,这也是 `false` 生物鉴别技术在尝试失败后被锁定.

### 创建密钥对

默认使用密钥需要每次生物鉴别认证:

```typescript
import { generateKeypair } from "@animo-id/expo-secure-environment";

await generateKeypair("my-key");
```

用选项配置密钥 :

```typescript
await generateKeypair("my-key", {
  userAuthentication: {
    methods: ["biometric", "deviceCredential"],
    invalidateOnBiometricChange: true,
  },
  minimumKeyStorage: "trustedEnvironment",
});
```

| 选项 | 默认 | 说明 |
| --- | --- | --- |
| `userAuthentication` |  | 需要签名的用户认证,或 `false` 没有. |
| `userAuthentication.methods` | `['biometric']` | `biometric` (身份证、触摸身份证、Android 第3类生物鉴别技术)和/或 `deviceCredential` (device passcode,PIN,图案或密码). |
| `userAuthentication.invalidateOnBiometricChange` | `true` | 当在设备上添加或去除生物鉴别技术时,密钥是否变得无法使用. 仅适用于下列情况: `methods` 实值 `['biometric']`。 。 。 . |
| `userAuthentication.validitySeconds` | `0` | 仅限Android. 该密钥在用户认证后可以使用多久 . `0` 需要认证每个签名. |
| `minimumKeyStorage` | `'strongBox'` | 仅限Android. 将密钥存储在最安全的存储器中 [Android 上的密钥存储](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-key-storage-on-android)iOS总是使用安全飞地. |
| `preferStrongBox` | `true` | 仅限Android. 设备拥有时是否将密钥存储在 StrongBox 中, 以及何时 `minimumKeyStorage` 不需要这样. |
| `attestationChallenge` |  | 仅限Android. 创建包含此挑战的密钥验证, 参见 [密钥证明](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-key-attestation-android)。 。 。 . |

#### Android 上的密钥存储

Android在索取时会将密钥存储于StrongBox. 所有其他密钥都去设备的默认密钥存储:TEE,或者没有TEE设备上的软件,如模拟器. Apps不能选择TEE和软件,所以 `minimumKeyStorage` 设置您接受的最低安全存储 :

| `minimumKeyStorage` | 存储密钥的地方 | 失败的时间 |
| --- | --- | --- |
| `strongBox` | StrongBox, 一个单独的安全元素. | 该设备没有"强框". |
| `trustedEnvironment` | 当设备拥有了它时强框,否则默认的密钥存储,必须是TEE. | 该装置没有TEE. |
| `software` | 设备拥有后有强框,否则默认密钥存储:TEE,或软件. | 从来没有. |

当StrongBox无法存储密钥时,它会转到默认密钥存储处取而代之. StrongBox比TEE慢,可以同时运行较少的操作. 要总是使用默认密钥存储, 例如当您同时生成许多密钥时, 设置 `preferStrongBox: false`。 。 。 .

软件中的一键无法被你的应用程序所读取,但Android本身可以读取,因此它不能被保护免受被损坏(如被扎入)的设备.

`getKeyStorage` 返回键的结尾 :

```typescript
import { getKeyStorage } from "@animo-id/expo-secure-environment";

await getKeyStorage("my-key"); // 'strongBox', 'trustedEnvironment', 'software' or 'secureHardware'
```

Android 11 不说安全硬件中的密钥是StrongBox还是TEE,所以它返回了 `secureHardware` 两者都有 核查人也可以从 [密钥验证](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-key-attestation-android)。 。 。 .

### 拿公用钥匙

返回 P-256 公钥的压缩形式(而不是 DER 编码的主题PublicKeyInfo ):

```typescript
import { getPublicBytesForKeyId } from "@animo-id/expo-secure-environment";

const publicKey: Uint8Array = await getPublicBytesForKeyId("my-key");
```

### 签名数据

返回原始签名(而不是一个编码为 ECDSA-Sig-Value) 。 当密钥需要用户认证时,请用户先认证:

```typescript
import { sign } from "@animo-id/expo-secure-environment";

const signature = await sign("my-key", message, {
  prompt: { title: "Sign in to Example", cancel: "Cancel" },
});
```

等待一个显示提示的签名, 然后再开始下一个 。 iOS 显示一个提示, 所以第二个提示取消第一个提示, 然后丢出一个 `UserAuthenticationCanceledError`Android 显示一个接一个的提示.

### 多次签名

一次创建多个签名, 例如要提交多个证书, 使用 `withUserAuthentication`。在iOS上,用户在第一次签名时用需要的密钥进行认证一次,下一次签名则重新使用该认证。 不需要用户认证的密钥从不问. 在Android上 它的标志像 `sign`: 保存默认值 `validitySeconds` 联 合 国 `0` 并显示每个签名一个提示, 标题中写着用户的签名 。 安全硬件随后允许每个认证一个签名,所以应用程序中没有任何其他代码可以不经询问用户而签名.

```typescript
import { withUserAuthentication } from "@animo-id/expo-secure-environment";

async function signCredentials(credentials: { keyId: string; name: string }[], message: Uint8Array) {
  return withUserAuthentication(
    async ({ sign }) => {
      const signatures = [];
      for (const [index, { keyId, name }] of credentials.entries()) {
        // The prompt of each signature on Android
        const prompt = { title: `Share ${name}`, subtitle: `${index + 1} of ${credentials.length}` };
        signatures.push(await sign(keyId, message, { prompt }));
      }
      return signatures;
    },
    // The prompt of the one authentication on iOS
    { prompt: { title: `Share ${credentials.length} credentials` } }
  );
}
```

只有 `sign` 联 合 国 `withUserAuthentication` 重用认证, 并且直到调用返回为止 。 后被掷出. 其它 `sign` 应用程序中的呼叫仍然询问用户, 也当回调运行时, 所以通过 `sign` 用于共享认证的代码。 它一次签一个消息,所以第二个提示不能取消第一个. 在iOS上,下一个密钥在接受用户认证的方法时重新使用认证:这个密钥只接受密码在生物鉴别后再次询问.

在Android上,键生成方式为 `validitySeconds` 上文 `0` 询问一次,然后在有效结束之前不急于签名。 有效性不那么可靠。 在它结束之前,应用程序中的任何代码都可以在不迅速的情况下签名,而不只是 `sign` 联 合 国 `withUserAuthentication`,并用其中一把钥匙解锁设备 `methods` 也开始吧 如果你使用它, 请保持足够长的时间 以便你马上创建的签名.

### 密钥证明 (Android)

在Android上,一个密钥可以用密钥验证来创建:来自设备安全硬件的证书链,证明密钥是在那里生成的,描述密钥是如何被保护的,包括挑战. 创建密钥时通过挑战,然后获得证书链(base64被编码为 DER 证书,叶先:

```typescript
import {
  generateKeypair,
  getAttestationCertificateChain,
} from "@animo-id/expo-secure-environment";

await generateKeypair("my-key", { attestationChallenge: challenge });
const certificateChain: string[] = await getAttestationCertificateChain("my-key");
```

iOS没有安全飞地密钥的密钥证明. 挑战被忽视 `getAttestationCertificateChain` 掷出.

OpenID4VCI 中的密钥证明 `key_storage` 财务报告和审定财务报表 `user_authentication` 键的级别(攻击潜在阻力,ISO 18045)。 您的钱包从如何配置密钥来决定这些关卡 `userAuthentication`,从何处 `getKeyStorage` 说一个密钥被存储。 这个库没有指定关卡.

### 错误

所有错误延伸 `SecureEnvironmentError`,具有 `keyId` 和本地错误 `code`。有特定原因的错误有自己的类:

| 错误 | 掷出时 |
| --- | --- |
| `SecureEnvironmentNotSupportedError` | 设备没有安全飞地, 或者没有请求 `minimumKeyStorage`,或运行Android 10或以上. |
| `KeyNotFoundError` | 此 ID 不存在密钥 . |
| `KeyAlreadyExistsError` | 此 ID 的密钥已经存在 . |
| `KeyInvalidatedError` | 仅限Android. 该密钥被永久作废,因为生物鉴别技术改变或屏幕锁被去掉. |
| `UserAuthenticationCanceledError` | 用户,应用程序或系统取消了认证提示. |
| `UserAuthenticationFailedError` | 用户没有成功认证,例如指纹不被识别. |
| `UserAuthenticationLockedOutError` | 生物测量在尝试失败太多后被锁定. 当用户进入设备密码时,它们会解锁,在Android上,第一次闭锁也于30秒后结束. |
| `UserAuthenticationUnavailableError` | 用户无法使用所请求的方法进行认证,例如没有注册生物鉴别技术. |

## 从0.2.0移走

用0.2.0创建的密钥继续工作. `sign` 从密钥本身读取它是否需要用户认证.

目前最低iOS版本为16.4 (was 13.4),最低Expo SDK为53.

### 选项代替 `biometricsBacked`

`generateKeypair` 财务报告和审定财务报表 `sign` 不再需要一个 `biometricsBacked` 参数。 默认值与0.2.0相同:每个签名的生物鉴别认证,当生物鉴别仪改变时,密钥无效,而Android存储于StrongBox.

```typescript
// 0.2.0
await generateKeypair("my-key", false);
await sign("my-key", message, false);

// now
await generateKeypair("my-key", { userAuthentication: false });
await sign("my-key", message);
```

第三个论点是: `sign` 现在设置认证提示的文本,参见 [签名数据](https://npmcn.com/package/%40animo-id/expo-secure-environment/#readme-sign-data)。 。 。 .

### 撤回安全的环境被移除

`setFallbackSecureEnvironment`, (中文(简体) ), `shouldUseFallbackSecureEnvironment`, (中文(简体) ), `isLocalSecureEnvironmentSupported` 编辑 `SecureEnvironment` 界面被删除。 现在的功能总是使用设备的安全环境,以及 `generateKeypair` 丢出一个 `SecureEnvironmentNotSupportedError` 当设备没有它.

如果您使用后退, 请检查支持 `isSecureEnvironmentSupported` 并呼唤你的后退你自己。 继续使用存储在那里的后退键 :

-   `isSecureEnvironmentSupported` 不总是给出与0.2.0相同的结果. 在iOS上它现在返回 `false` 没有安全飞地,例如模拟器。 在Android上它会返回 `true` 用于每个带有 StrongBox 的设备,其中0.2.0 需要 KeyMint 1.0 或更新。 存储每个密钥创建位置, 而不是再次检查支持 .
-   在Android设备上,没有强框,您可以在TEE中存储密钥 `minimumKeyStorage: "trustedEnvironment"` 而不是用倒计时 装有"强Box"的设备仍然存放在那里.

### 错误

-   `nativeError` 改为: `code`,本地错误代码(例如:. `ERR_KEY_NOT_FOUND`) (中文(简体) ). 原始错误在 `cause`。 。 。 .
-   构造器选择: `new SecureEnvironmentError(message, { keyId, code, cause })`。 。 。 . `SecureEnvironmentError.fromNative` 删除.
-   认证提示的错误现在有自己的类 。 在Android上,0.2.0 扔这些作为一个平地 `SecureEnvironmentError`。 。 。 .

`KeyNotFoundError` 财务报告和审定财务报表 `KeyAlreadyExistsError` 不变。 其他错误类别被删除 :

| 0.2.0 (中文(简体) ) | 现在 |
| --- | --- |
| `BiometricAuthenticationFailed` | `UserAuthenticationCanceledError`, (中文(简体) ), `UserAuthenticationFailedError`, (中文(简体) ), `UserAuthenticationLockedOutError` 或者说 `UserAuthenticationUnavailableError` |
| `NoHardwareKeyStore` | `SecureEnvironmentNotSupportedError` |
| `KeychainQueryError`, (中文(简体) ), `CouldNotConvertIntoPublicKey`, (中文(简体) ), `CouldNotConvertIntoExternalRepresentation`, (中文(简体) ), `CouldNotCreateSignature`, (中文(简体) ), `CouldNotGenerateKeyPair`, (中文(简体) ), `NoSignatureOnCryptoObject`, (中文(简体) ), `NotExecutedFromMainThread` | `SecureEnvironmentError` |

## 捐款

你想修补还是补充? 太好了,我们喜欢社区贡献! 要参与,请跟随我们 [捐款准则](https://github.com/animo/.github/blob/main/CONTRIBUTING.md)。 。 。 .

测试在例应用中运行 [反应原生机理](https://react-native-harness.dev/)。 。 。 . `pnpm test:ios` 财务报告和审定财务报表 `pnpm test:android` 用模拟器或仿真器运行它们, `pnpm test:ios:device` 财务报告和审定财务报表 `pnpm test:android:device` 电话连接到你的电脑上 只有电话测试安全硬件 见 [一般事务人员(其他职等)](https://npmcn.com/package/%40animo-id/expo-secure-environment/AGENTS.md#tests) 详细情况.

## 许可证

此寄存器根据 [Apache 2.0 (英语)](https://npmcn.com/package/%40animo-id/expo-secure-environment/LICENSE) 执照.

## 常见问题

### @animo-id/expo-secure-environment 是什么？

博览安全环境

### 如何安装 @animo-id/expo-secure-environment？

在项目目录运行 npm install @animo-id/expo-secure-environment，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：expo（\>=53\.0\.0）、react（\*）、react-native（\*）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @animo-id/expo-secure-environment 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @animo-id/expo-secure-environment 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @animo-id/expo-secure-environment 可以商用吗？

@animo-id/expo-secure-environment 使用 APACHE-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @animo-id/expo-secure-environment 的下载量有多少？

根据 npm 官方下载统计，@animo-id/expo-secure-environment 在 2026/10/06 – 2026/11/04 这 30 天内被下载 9,494 次，日均约 316 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @animo-id/expo-secure-environment 还在维护吗？

最新版本 0\.3\.0 发布于 2026/10/28（10 天前）；至今共发布 22 个版本，其中过去 12 个月发布了 2 个；首次发布于 2024/07/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

