nichoth/simple-hpke
GitHub: nichoth/simple-hpke
基于 RFC 9180 的轻量级 JavaScript 混合公钥加密库,将密钥封装与 AES-GCM 消息加密简化为 seal/open 和 encrypt/decrypt 等极简接口。
Stars: 0 | Forks: 0
# 简单 HPKE
[](https://github.com/nichoth/simple-hpke/actions/workflows/nodejs.yml)
[](README.md)
[](README.md)
[](https://semver.org/)
[](./CHANGELOG.md)
[](https://packagephobia.com/result?p=@substrate-system/simple-hpke)
[](https://bundlephobia.com/package/@substrate-system/simple-hpke)
[](LICENSE)
混合公钥加密
([RFC 9180](https://www.rfc-editor.org/rfc/rfc9180.html))
1 个依赖项 —— `uint8arrays`。
- [安装](#install)
- [示例](#example)
* [密钥封装](#key-wrapping)
* [混合加密](#hybrid-encryption)
+ [加密 / 解密](#encrypt--decrypt)
- [`encrypt`](#encrypt)
- [加密为字符串](#encrypt-to-a-string)
- [`decrypt`](#decrypt)
- [模块](#modules)
* [ESM](#esm)
* [Common JS](#common-js)
* [预构建 JS](#pre-built-js)
+ [复制](#copy)
+ [HTML](#html)
## 安装
```
npm i -S @substrate-system/simple-hpke
```
## 示例
封装一个 AES 密钥,或加密一条消息。
### 密钥封装
将一个 AES 密钥加密给你自己,以便日后恢复。
```
import { seal, open } from '@substrate-system/simple-hpke'
// An X25519 keypair. The private key can be non-extractable.
// HPKE needs only `deriveBits`.
const keypair = await crypto.subtle.generateKey(
{ name: 'X25519' },
false, // extractable
['deriveBits']
)
// create a new AES key, and encrypt it to your public key.
const { wrapped, key } = await seal(keypair)
// Or wrap an existing AES key. The supplied key must be extractable.
const aesKey = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
true, // extractable
['encrypt', 'decrypt']
)
// if you pass in a key, the return value is just the wrapped key
const { wrapped } = await seal(keypair, aesKey)
// Later, recover the same key with your private key.
const recoveredKey = await open(keypair, wrapped)
```
完整的 API 和原理请参阅 [docs/README.md](./docs/README.md)。
### 混合加密
封装一个密钥,然后使用它通过 AES-GCM 加密一条消息。
封装后的密钥会与密文以及 IV 拼接在一起。
接收者使用其私钥打开 AES 密钥并解密消息。
```
import { seal, open } from '@substrate-system/simple-hpke'
const recipient = await crypto.subtle.generateKey(
{ name: 'X25519' },
false, // not extractable
['deriveBits']
)
// Create and seal a fresh AES-GCM key, and encrypt a message with it.
const { wrapped, key } = await seal(recipient)
const iv = crypto.getRandomValues(new Uint8Array(12))
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
new TextEncoder().encode('attack at dawn')
)
// Send `wrapped`, `iv`, and `ciphertext` together. `wrapped` is a fixed
// 80 bytes for this suite, and the AES-GCM IV is 12 bytes, so the recipient
// can slice the payload back apart at known offsets.
const ciphertext = new Uint8Array(ciphertext)
const message = new Uint8Array(wrapped.length + iv.length + ciphertext.length)
message.set(wrapped, 0)
message.set(iv, wrapped.length)
message.set(ciphertext, wrapped.length + iv.length)
// On the other side, split the payload back into its parts.
const wrapped2 = message.subarray(0, 80)
const iv2 = message.subarray(80, 80 + 12)
const ciphertext2 = message.subarray(80 + 12)
// Recover the key, then decrypt the message.
const recovered = await open(recipient, wrapped2)
const plaintext = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv: iv2 },
recovered,
ciphertext2
)
new TextDecoder().decode(plaintext) // => 'attack at dawn'
```
#### 加密 / 解密
加密和解密一条消息需要这么多代码……
这个包暴露了 `encrypt` 和 `decrypt` 函数,它们做的是同样的事情。
`encrypt` 将一个 AES 密钥封装给接收者,使用该密钥加密消息,
并返回一个单一的信封:`wrappedLen + wrapped + iv + ciphertext`
(一个 2 字节的长度前缀、封装的密钥、12 字节的 AES-GCM IV,
以及密文)。`decrypt` 执行相反的操作,返回明文字节。
```
import {
encrypt,
decrypt
} from '@substrate-system/simple-hpke'
// need a public key for the recipient
const recipient = await crypto.subtle.generateKey(
{ name: 'X25519' },
false,
['deriveBits']
)
// create a new AES key, encrypt a message, and get back one envelope
const encryptedMessage = await encrypt(recipient, 'hello encryption')
// the recipient recovers the message with their private key
const text = await decrypt.asString(recipient, encryptedMessage)
// use `decrypt` to get a Uint8Array
const bytes = await decrypt(recipient, encryptedMessage)
//
// use an existing AES key
//
const existingKey = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
true, // extractable
['encrypt', 'decrypt']
)
const anotherEncryptedMsg = await encrypt(
recipient,
'hello again',
existingKey
)
```
##### `encrypt`
接收者可以是一个 crypto 密钥、一个 Uint8Array 或一个字符串形式的公钥。
```
type RecipientKey =
| CryptoKey
| CryptoKeyPair
| Uint8Array
| { publicKey:string; encoding?:Uint8ArrayEncodings }
async function encrypt (
recipient:RecipientKey,
message:Uint8Array|string,
aesKey?:CryptoKey|Uint8Array|null,
opts?:{
keysize?:128|256
info?:Uint8Array|string
}
):Promise
```
##### 加密为字符串
`encrypt.asString` 就是 `encrypt`,只不过信封被编码成了字符串,非常适合
传输文本(JSON、URL、headers)的场景。`opts.encoding` 用于设置字符串
编码。默认编码是 `base64url`。
```
import { encrypt, decrypt } from '@substrate-system/ecies'
import { fromString } from 'uint8arrays'
// recipient is any RecipientKey; keypair holds the matching private key
const encryptedString = await encrypt.asString(
recipient,
'message for them',
null, // an AES key if you want
{ encoding: 'base64url' }
)
// Decode it back to bytes before decrypting.
const message = fromString(encryptedString, 'base64url')
const plaintext = await decrypt.asString(keypair, message)
// 'message for them'
```
返回的字符串编码了与 `encrypt` 返回的相同信封,因此
接收者使用匹配的解码器(这里是 `fromString`)对其进行解码,并将这些
字节传递给 `decrypt` / `decrypt.asString`。
##### `decrypt`
```
async function decrypt (
keypair:CryptoKeyPair,
message:Uint8Array,
opts?:{ info?:Uint8Array|string }
):Promise
```
## 模块
这个包通过
[package.json `exports` 字段](https://nodejs.org/api/packages.html#exports) 暴露了 ESM 和 Common JS。
### ESM
```
import { seal, open, encrypt, decrypt } from '@substrate-system/simple-hpke'
```
### Common JS
```
require('@substrate-system/simple-hpke')
```
### 预构建 JS
这个包也暴露了压缩后的 JS 文件。将它们复制到你的
Web 服务器可访问的位置,然后在 HTML 中链接到它们。
#### 复制
```
cp ./node_modules/@substrate-system/simple-hpke/dist/index.min.js ./public/hpke.min.js
```
#### HTML
```
```
目录
- [安装](#install)
- [示例](#example)
* [密钥封装](#key-wrapping)
* [混合加密](#hybrid-encryption)
+ [加密 / 解密](#encrypt--decrypt)
- [`encrypt`](#encrypt)
- [加密为字符串](#encrypt-to-a-string)
- [`decrypt`](#decrypt)
- [模块](#modules)
* [ESM](#esm)
* [Common JS](#common-js)
* [预构建 JS](#pre-built-js)
+ [复制](#copy)
+ [HTML](#html)
标签:HPKE, MITM代理, TypeScript, 加密库, 安全插件, 密码学, 密钥封装, 手动系统调用, 数据可视化, 混合加密, 自动化攻击, 蓝队防御