mima-kit is a cryptographic suite implemented in TypeScript. The goal is to provide an easy-to-use cryptographic library. mima-kit 是一个使用 TypeScript 实现的密码学套件。目标是提供一个简单易用的密码学库。
npm install mima-kitmima-kit 是一个使用 TypeScript 实现的密码学套件。目标是提供一个简单易用的密码学库。mima-kit 尚处于早期开发阶段,API 可能会发生变化。
在线使用: https://rsoram.github.io/mima-live/
``bash`
npm install mima-kit
- UTF8 UTF-8 编码HEX
- 十六进制编码B32
- Base32 编码 RFC 4648 RFC 4648-HEX CrockfordB64
- Base64 编码B64URL
- Base64URL 编码
密码学中的数据通常是二进制数据,在 JS 中通常以 Uint8Array 表示,string 和 Uint8Array 的转换需要 字符编码。
> 如果您使用 Node.js 这类支持 Buffer 的环境,那么您可以直接使用 Buffer 进行编解码。如果您使用的是浏览器环境,就可以使用 mima-kit 提供的解码器。
mima-kit 提供的编解码器会自动判断输入数据的类型。
- 输入 Uint8Array 类型的数据,会将其转换为 stringstring
- 输入 类型的数据,会将其转换为 Uint8Array
`typescript`
// convert utf-8 string to Uint8Array
const e = UTF8('mima-kit')
// convert Uint8Array to utf-8 string
const d = UTF8(e)
console.log(d) // 'mima-kit'
`typescript`
interface Codec {
/**
* Parse encoded string to Uint8Array
*
* 将编码字符串解析为 Uint8Array
*/
(input: string): U8
/**
* Stringify Uint8Array to encoded string
*
* 将 Uint8Array 编码为字符串
*/
(input: Uint8Array): string
FORMAT: string
}
在上述代码中,您可能留意到了 U8 类型。mima-kit 中绝大多数函数都会返回 U8 类型,她是 Uint8Array 的子类,旨在提供一些额外的方法。绝大多数情况下,您可以放心地将 U8 类型传递给其他使用 Uint8Array 的函数。
`typescript
// Parse encoded string to U8
U8.fromSting('6D696D612D6B6974', HEX)
// Stringify U8 to encoded string
U8.fromSting('6D696D612D6B6974', HEX)
.to(UTF8) // 'mima-kit'
// Convert BigInt to U8
U8.fromBI(0x12345678n) // [0x12, 0x34, 0x56, 0x78]
// Convert U8 to BigInt
U8.fromBI(0x12345678n)
.toBI() // 305419896n (0x12345678n)
`
B32 编码存在多种事实标准与变体,mima-kit 提供了三种变体的编解码器,B32 默认不进行填充。
`typescript
interface B32Params {
variant?: 'rfc4648' | 'rfc4648-hex' | 'crockford'
padding?: boolean
}
interface B32Codec extends Codec {
/**
* 创建一个 base32 编解码器
*
* Create a base32 codec
*/
(params: B32Params): Codec
}
// RFC 4648 Base32 with no padding by default
B32(UTF8('cat, 猫, 🐱')) // MNQXILBA46GKWLBA6CPZBMI
// using RFC 4648 Base32-hex with padding
const B32HP = B32({ variant: 'rfc4648-hex', padding: true })
B32HP(UTF8('cat, 猫, 🐱')) // CDGN8B10SU6AMB10U2FP1C8=
`
散列算法 是一种将任意长度的数据映射为固定长度数据的算法。该定义非常宽泛,但在密码学中,通常讨论的是 加密散列算法。带密钥的加密散列算法 会额外使用一个密钥产生更安全的散列值。
Specification: GM/T 0004-2012
`typescript`
const m = UTF8('mima-kit')
sm3(m).to(HEX)
Specification: RFC 1321
`typescript`
const m = UTF8('mima-kit')
md5(m).to(HEX)
Specification: FIPS PUB 180-4
`typescript`
const m = UTF8('mima-kit')
sha1(m).to(HEX)
Specification: FIPS PUB 180-4
`typescript
const m = UTF8('mima-kit')
sha224(m).to(HEX)
sha256(m).to(HEX)
sha384(m).to(HEX)
sha512(m).to(HEX)
const sha512_224 = sha512t(224)
sha512_224(m).to(HEX)
`
Specification: FIPS PUB 202
`typescript
const m = UTF8('mima-kit')
sha3_224(m).to(HEX)
sha3_256(m).to(HEX)
sha3_384(m).to(HEX)
sha3_512(m).to(HEX)
shake128(256)(m).to(HEX)
shake256(512)(m).to(HEX)
`
Specification: NIST SP 800-185
`typescript
// optional function name
const n = UTF8('name')
// optional customization string
const s = UTF8('custom')
const m = UTF8('mima-kit')
cshake128(256, n, s)(m).to(HEX)
cshake256(512, n, s)(m).to(HEX)
`
Specification: NIST SP 800-185
`typescript`
// optional customization string
const s = UTF8('custom')
const m = ['mima', '-', 'kit'].map(v => UTF8(v))
tuplehash128(256, s)(m).to(HEX)
tuplehash256(512, s)(m).to(HEX)
tuplehash128XOF(256, s)(m).to(HEX)
tuplehash256XOF(512, s)(m).to(HEX)
Specification: NIST SP 800-185
> 注意:mima-kit 提供的 ParallelHash 算法并不能真正并行计算,只是将输入分块后分别计算,最后将结果拼接。
`typescript`
// optional customization string
const s = UTF8('custom')
const m = UTF8('mima-kit')
const blockSize = 1024
parallelhash128(blockSize, 256, s)(m).to(HEX)
parallelhash256(blockSize, 512, s)(m).to(HEX)
parallelhash128XOF(blockSize, 256, s)(m).to(HEX)
parallelhash256XOF(blockSize, 512, s)(m).to(HEX)
Specification: TurboSHAKE
`typescript`
// optional Domain Separator
// range: 0x01 ~ 0x7F, default: 0x1F
const D = 0x0B
const m = UTF8('mima-kit')
turboshake128(256, D)(m).to(HEX)
turboshake256(512, D)(m).to(HEX)
Specification: KangarooTwelve
`typescript`
// optional customization string
const s = UTF8('custom')
const m = UTF8('mima-kit')
kt128(256, s)(m).to(HEX)
kt256(512, s)(m).to(HEX)
Specification: RFC 2104
> 密钥长度的参数 k_size 默认使用散列算法的 DIGEST_SIZE。该参数不会影响函数的结果,但会被其他函数使用,例如 ECIES。
`typescript`
const key = UTF8('password')
const m = UTF8('mima-kit')
// HMAC-SM3
hmac(sm3)(key, m).to(HEX)
// HMAC-SHA1-80 with 80-bit digest and 160-bit key
hmac(sha1, 80)(key, m).to(HEX)
// HMAC-SHA1-160 with 160-bit digest and 80-bit key
hmac(sha1, 160, 80)(key, m).to(HEX)
Specification: RFC 6238
> TOTP 是 HMAC 的拓展应用,它使用当前时间戳作为计数器,通过协商密钥输出一次性密码
`typescript
const otp = totp(B32('4B7X5MEKEFIJMWWVBQMMCLY6JI3YOC7Y')) // '000000'
const totp_256 = totp({
mac: hmac(sha256),
step: 60_000, // 1 minute
digits: 8, // 8 digits
})
const otp = totp_256(B32('4B7X5MEKEFIJMWWVBQMMCLY6JI3YOC7Y')) // '00000000'
`
`typescriptDate.now()
interface TOTPParams {
/**
* 带密钥的加密散列算法 / Keyed Hashing Algorithm (default: HMAC-SHA1)
*/
mac?: KeyHash
/**
* 当前时间戳 / Current timestamp (default: Date.now() milliseconds)
*
* 指定此参数时,将不再从 获取当前时间戳.Date.now()
*
* When this parameter is specified, the current timestamp will not be obtained from .counter = (cuttent_time - epoch_time) / step
*/
current?: number
/**
* 纪元时间戳 / Epoch timestamp (default: 0 milliseconds)
*/
epoch?: number
/**
* 时间步长 / Time step (default: 30000 milliseconds)
*/
step?: number
/**
* 计数器 / Counter
*
* `
*
* 指定此参数时,将不再从当前时间戳计算计数器.
*
* When this parameter is specified, the counter will not be calculated from the current timestamp.
*/
counter?: number | bigint | Uint8Array
/**
* 返回的数字位数 / Number of digits in the returned OTP (default: 6)
*/
digits?: number
}
Specification: NIST SP 800-185
`typescript
// customization string
const s = UTF8('custom')
const key = UTF8('password')
const m = UTF8('mima-kit')
kmac128(256, s)(key, m).to(HEX)
kmac256(512, s)(key, m).to(HEX)
kmac128XOF(256, s)(key, m).to(HEX)
kmac256XOF(512, s)(key, m).to(HEX)
`
如果您已经实现了一个伟大而又神秘的散列算法,您可以使用 createHash 函数将其包装成一个可被调用的 Hash 对象。然后您就可以像使用其他 加密散列算法 一样,将您的算法和 mima-kit 中其他高级算法一起使用。
> 如果您熟悉 JS,您会发现 createHash 的本质不过是 Object.assign 的包装。您完全可以用 Object.assign 替代 createHash,但 createHash 会为您提供一些类型提示,避免发生恼人的拼写错误。
`typescript`
const _greatHash: Digest = (M: Uint8Array) => new U8(M)
const greatHashDescription: HashDescription = {
ALGORITHM: 'GreatHash',
BLOCK_SIZE: 64,
DIGEST_SIZE: 64,
}
const greatHash = createHash(_greatHash, greatHashDescription)
// HMAC-GreatHash
const hmac_gh = hmac(greatHash)
`typescript`
interface Digest {
(M: Uint8Array): U8
}
interface HashDescription {
/* 算法名称 / Algorithm name /
ALGORITHM: string
/* 分块大小 / Block size (byte) /
BLOCK_SIZE: number
/* 摘要大小 / Digest size (byte) /
DIGEST_SIZE: number
OID?: string
}
对称密钥算法 是一种使用相同密钥进行 加密 和 解密 的加密算法。它可以分为 分组密码算法 和 流密码算法。分组密码算法 通常需要组合 填充模式 和 工作模式 一起使用。分组密码算法 可以通过特定的 工作模式 和 NO_PAD 转换为 流密码算法。
> 你可以在 /test/cipher.test.ts 中找到更多使用示例。
`typescript`
const k = HEX('')
const iv = HEX('')
const p = UTF8('mima-kit')
// using SM4-CBC
const cbc_sm4 = cbc(sm4)(k, iv)
const c = cbc_sm4.encrypt(p)
const m = cbc_sm4.decrypt(c)
m.to(UTF8) // 'mima-kit'
// using SM4-CTR in stream mode
const ctr_sm4 = ctr(sm4, NO_PAD)(k, iv)
const c = ctr_sm4.encrypt(p)
const m = ctr_sm4.decrypt(c)
m.to(UTF8) // 'mima-kit'
单独使用 分组密码算法 没有太大的意义,因为它只能对单个数据块进行加解密。
Specification: GM/T 0002-2012
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
sm4(k).encrypt(m) // c
sm4(k).decrypt(c) // m
`
Specification: FIPS PUB 197
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
aes(128)(k).encrypt(m) // c
aes(128)(k).decrypt(x) // m
aes(192)(k).encrypt(m) // c
aes(192)(k).decrypt(c) // m
aes(256)(k).encrypt(m) // c
aes(256)(k).decrypt(c) // m
`
Specification: RFC 5794
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
aria(128)(k).encrypt(m) // c
aria(128)(k).decrypt(c) // m
aria(192)(k).encrypt(m) // c
aria(192)(k).decrypt(c) // m
aria(256)(k).encrypt(m) // c
aria(256)(k).decrypt(c) // m
`
Specification: RFC 3713
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
camellia(128)(k).encrypt(m) // c
camellia(128)(k).decrypt(c) // m
camellia(192)(k).encrypt(m) // c
camellia(192)(k).decrypt(c) // m
camellia(256)(k).encrypt(m) // c
camellia(256)(k).decrypt(c) // m
`
Specification: FIPS PUB 46-3
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
des(k).encrypt(m) // c
des(k).decrypt(c) // m
`
Specification: FIPS PUB 46-3
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
t_des(128)(k).encrypt(m) // c
t_des(128)(k).decrypt(c) // m
t_des(192)(k).encrypt(m) // c
t_des(192)(k).decrypt(c) // m
`
Specification: ARC5
ARC5 算法是一个参数化的算法,可以接受长度为 0 < k.byteLength < 256 的密钥。参数化后算法标记为 ARC5-w/r,其中 w 是工作字的比特长度,r 是轮数。
`typescript
// 推荐的参数化配置
// +-----+----+
// | w | r |
// +-----+----+
// | 8 | 8 |
// | 16 | 12 |
// | 32 | 16 | (default)
// | 64 | 20 |
// | 128 | 24 |
// +-----+----+
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
const spec8 = arc5(8, 8) // ARC5-8/8
const spec16 = arc5(16, 12) // ARC5-16/12
const spec32 = arc5(32, 16) // ARC5-32/16 (default)
const spec64 = arc5(64, 20) // ARC5-64/20
const spec128 = arc5(128, 24) // ARC5-128/24
spec32(k).encrypt(m) // c
spec32(k).decrypt(c) // m
`
Specification: Blowfish
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
blowfish(k).encrypt(m) // c
blowfish(k).decrypt(c) // m
`
Specification: Twofish
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
twofish(128)(k).encrypt(m) // c
twofish(128)(k).decrypt(x) // m
twofish(192)(k).encrypt(m) // c
twofish(192)(k).decrypt(c) // m
twofish(256)(k).encrypt(m) // c
twofish(256)(k).decrypt(c) // m
`
Specification: TEA
向 TEA 算法传递一个代表 轮数 的参数。TEA 算法的 轮数 可以是任意正整数,默认使用 32。
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
tea(32)(k).encrypt(m) // c
tea(32)(k).decrypt(c) // m
`
Specification: XTEA
向 XTEA 算法传递一个代表 轮数 的参数。XTEA 算法的 轮数 可以是任意正整数,默认使用 32。
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
xtea(32)(k).encrypt(m) // c
xtea(32)(k).decrypt(c) // m
`
Specification: XXTEA
XXTEA 本身设计用于加密任意数量的数据块,其中每个数据块是 4 字节。
`typescript
let k: Uint8Array
let m: Uint8Array
let c: Uint8Array
// using default config
xxtea()(k).encrypt(m) // c
xxtea()(k).decrypt(c) // m
`
默认情况下,XXTEA 对数据进行 6 + 52 / n 轮加密,其中 n 是数据块的数量。您可以通过 round 参数设置一个固定的轮数。
`typescript`
const config: XXTEAConfig = {
round: 64,
}
xxtea(config)(k).encrypt(m) // c
xxtea(config)(k).decrypt(c) // m
在实际使用中,数据通常需要填充,以保证数据的字节长度是 4 的倍数。您可以通过 padding 参数设置填充模式。默认情况下,XXTEA 使用 PKCS7 填充模式。如果您确定数据的字节长度是 4 的倍数,您可以通过将 padding 设置为 NO_PAD 来跳过填充。
`typescript`
// using X923_PAD
const config: XXTEAConfig = {
padding: X923_PAD,
}
// skip padding
const config: XXTEAConfig = {
padding: NO_PAD,
}
xxtea(config)(k).encrypt(m) // c
xxtea(config)(k).decrypt(c) // m
如果您希望像其他分组密码一样使用 XXTEA,例如使用 GCM 模式
1. 将 padding 设置为 NO_PAD,让 工作模式 处理填充BLOCK_SIZE
2. 设置 告知 工作模式 每次处理数据块的大小XXTEA
3. 因为 的数据块大小是 4 字节,所以请确保 BLOCK_SIZE 是 4 的倍数且大于 8
> 注意: 这不是 XXTEA 的标准用法,缺乏相关的安全分析。
`typescript
const config: XXTEAConfig = {
padding: NO_PAD,
BLOCK_SIZE: 16,
}
const cipher = xxtea(config)
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = gcm(cipher)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
`typescriptXXTEA
interface XXTEAConfig {
/**
* 分组大小 / Block size (default: 16)
*
* 本身设计用于加密任意数量的数据块。单独使用 XXTEA 时,该选项不起作用。XXTEA
* 但是,如果需要将 用作分组密码和 工作模式 一起使用,则可以通过此选项设置分组大小。XXTEA
*
* 注意: 这不是 的标准用法且缺乏相关的安全分析。XXTEA
*
* is natively designed to encrypt arbitrary amounts of data blocks.XXTEA
* When used alone, this option does not take effect.
* However, if you need to use as a block cipher and use it with Operation Mode,BLOCK_SIZE
* you can set the through this option.XXTEA
*
* Note: This is not the standard usage of and lacks relevant security analysis.XXTEA
*/
BLOCK_SIZE?: number
/**
* 填充方式 / Padding method (default: PKCS7)
*
* 如果要像其他分组密码一样使用 ,例如使用 CBC 模式,padding
* 应该将 设置为 NO_PAD 并让 工作模式 处理填充。XXTEA
*
* If you want to use like other block ciphers, such as with CBC mode,padding
* you should set the to NO_PAD and let the Operation Mode handle the padding.XXTEA
*/
padding?: Padding
/**
* 轮数 / Rounds (default: undefined)
*
* 的轮数可以通过这个选项设置,如果不设置则使用默认的轮数计算方式。XXTEA
*
* The rounds of can be set through this option,`
* if not set, the default round calculation method will be used.
*/
round?: number
}
- PKCS7_PAD PKCS#7 填充模式X923_PAD
- ANSI X9.23 填充模式ISO7816_PAD
- ISO/IEC 7816-4 填充模式ZERO_PAD
- 零填充模式NO_PAD
- 无填充模式
单独使用 填充模式 没有太大的意义,因为它只是对数据进行填充或者去填充。
`typescript`
let block_size: number
let m = new Uint8Array()
let p = new Uint8Array()
// add padding
p = PKCS7_PAD(m, block_size)
// remove padding
m = PKCS7_PAD(p)
`typescript`
interface Padding {
/**
* 添加填充 / Add padding
* @param {Uint8Array} M - Message
* @param {number} BLOCK_SIZE - Block size
*/
(M: Uint8Array, BLOCK_SIZE: number): U8
/**
* 移除填充 / remove padding
* @param {Uint8Array} P - Padded message
*/
(P: Uint8Array): U8
ALGORITHM: string
}
`typescript`
const cbc_sm4 = cbc(sm4, PKCS7_PAD)
`typescript`
const cbc_sm4 = cbc(sm4, X923_PAD)
`typescript`
const cbc_sm4 = cbc(sm4, ISO7816_PAD)
`typescript`
const cbc_sm4 = cbc(sm4, ZERO_PAD)
> NO_PAD 模式不会对数据进行填充,这一模式仅用于将 分组密码算法 转换为 流密码算法。
`typescript`
// run SM4-OFB in stream mode
const ofb_sm4 = ofb(sm4, NO_PAD)
- ecb Electronic Codebookcbc
- Cipher Block Chainingpcbc
- Progressive Chaining Block Ciphercfb
- Cipher Feedbackofb
- Output Feedbackctr
- Counter Modegcm
- Galois/Counter Mode
mima-kit 将 工作模式 与 分组密码算法 完全解偶,这意味着您可以将任意 分组密码算法 与任意 工作模式 结合使用。
Electronic Codebook (ECB) 是最简单的工作模式。ECB 模式将明文分成固定长度的数据块,然后对每个数据块进行加密。
- ECB 模式不需要 iv。ECB
- 向 模式传递的 iv 参数会被忽略。
`typescript
const k = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = ecb(sm4)(k)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Cipher Block Chaining (CBC) 是最常用的工作模式。CBC 模式每个明文块都会与前一个密文块进行异或操作,然后再进行加密。
- CBC 模式需要 iv。iv
- 的长度与加密算法的 BLOCK_SIZE 相同。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = cbc(sm4)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Progressive Chaining Block Cipher (PCBC) 是 CBC 的变种。PCBC 模式每个明文块都会与前一个明文和前一个密文块进行异或操作,然后再进行加密。PCBC 模式旨在将密文中的微小变化在加解密时无限传播。
- PCBC 模式需要 iv。iv
- 的长度与加密算法的 BLOCK_SIZE 相同。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = pcbc(sm4)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Cipher Feedback (CFB) 将分组密码转换为流密码。CFB 模式通过加密前一个密文块获得加密数据流,然后与明文块进行异或操作,获得密文块。
- CFB 模式需要 iv。iv
- 的长度与加密算法的 BLOCK_SIZE 相同。CFB
- 可以通过 NO_PAD 转换为 流密码算法。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = cfb(sm4)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Output Feedback (OFB) 将分组密码转换为流密码。OFB 模式通过加密 iv 获得加密数据流,然后与明文块进行异或操作,获得密文块。
- OFB 模式需要 iv。iv
- 的长度与加密算法的 BLOCK_SIZE 相同。OFB
- 可以通过 NO_PAD 转换为 流密码算法。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = ofb(sm4)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Counter Mode (CTR) 将分组密码转换为流密码。CTR 模式将 iv 与计数器组合以生成唯一的 计数器块,通过加密 计数器块 获得加密数据流,然后与明文块进行异或操作,获得密文块。
- CTR 模式需要 iv。iv
- 的长度与加密算法的 BLOCK_SIZE 相同。CTR
- 可以通过 NO_PAD 转换为 流密码算法。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const c = HEX('')
const CIPHER = ctr(sm4)(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
`
Galois/Counter Mode (GCM) 将分组密码转换为流密码。GCM 模式可以看作是 CTR 模式的变种,它在 CTR 模式的基础上增加了 认证 功能。
- GCM 模式需要 iv。iv
- 的长度没有限制,但推荐使用 96 位长度的 iv。GCM
- 可以通过 NO_PAD 转换为 流密码算法。AUTH_TAG
- 签名生成的 长度由 AUTH_TAG_SIZE 参数决定。AUTH_TAG 最大长度为 128 位,设置任意长度都不会影响程序的运行,但一般推荐使用 128、120、112、104、96 位长度,对于某些应用也可以使用 64、32 位长度。
mima-kit 实现的 GCM 模式并没有进行查表优化,因此性能可能会比较慢。
`typescript
const k = HEX('')
const iv = HEX('')
const m = HEX('')
const a = HEX('')
const c = HEX('')
const t = HEX('')
const CIPHER = gcm(aes(128))(k, iv)
CIPHER.encrypt(m) // c
CIPHER.decrypt(c) // m
CIPHER.sign(c, a) // auth tag
CIPHER.verify(t, c, a) // true or false
`
通常 流密码算法 不需要复杂的配置,一般只需要 key 和 iv。
`typescript`
const k = HEX('')
const iv = HEX('')
const cipher = salsa20(k, iv)
const p = UTF8('mima-kit')
const c = cipher.encrypt(p)
const m = cipher.decrypt(c)
// p === m
ZUC 是 3GPP 规范中的流密码算法,它包含机密性算法 128-EEA3 和完整性算法 128-EIA3。由于 ZUC 算法主要用于移动通信,所以函数接口和其他流密码算法有所不同。
参考 /test/cipher.test.ts 以获取更多使用示例。
`typescript`
const k = new Uint8Array(16)
const m = new Uint8Array(4)
const c = new Uint8Array([0x27, 0xBE, 0xDE, 0x74])
const mac = new Uint8Array([0xC8, 0xA9, 0x59, 0x5E])
const params: ZUCParams = {
KEY: k,
M: m,
COUNTER: 0,
BEARER: 0,
DIRECTION: 0,
LENGTH: 1,
}
// 128-EEA3 加密消息
eea3(params) // c
// 128-EIA3 计算消息认证码
eia3(params) // mac
// 128-EEA3 解密消息
params.M = c
eea3(params) // m
Specification: ARC4
ARC4 算法可以接受长度为 0 < k.byteLength < 256 的密钥,同时 ARC4 算法不需要 iv。
`typescript`
const k = HEX('')
const cipher = arc4(k)
const c = cipher.encrypt(UTF8('mima-kit'))
const m = cipher.decrypt(c)
Specification: Salsa20
Salsa20 算法可以接受长度为 16 或 32 字节的密钥和 8 字节的 iv。
`typescript`
const k = HEX('')
const iv = HEX('')
const cipher = salsa20(k, iv)
const c = cipher.encrypt(UTF8('mima-kit'))
const m = cipher.decrypt(c)
Specification: Rabbit
Rabbit 算法可以接受长度为 16 字节的密钥。对于 iv,Rabbit 算法可以接受长度为 0 或 8 字节的 iv。当 iv 长度为 0 字节时,Rabbit 算法会跳过 iv Setup 步骤。
`typescript
const p = UTF8('mima-kit')
const k = HEX('')
const iv = new Uint8Array(8)
const cipher = rabbit(k, iv)
const c = cipher.encrypt(p)
const m = cipher.decrypt(c)
// skip iv setup
const cipher = rabbit(k, new Uint8Array(0))
const c = cipher.encrypt(p)
const m = cipher.decrypt(c)
`
与 包装您的加密散列算法 一样,您可以使用 createCipher 函数将您的 对称密钥算法 包装成一个可被调用的 Cipher 对象。然后您就可以像使用其他 对称密钥算法 一样,将您的算法和 mima-kit 中其他高级算法一起使用。
> 如果您熟悉 JS,您会发现 createCipher 的本质不过是 Object.assign 的包装。您完全可以用 Object.assign 替代 createCipher,但 createCipher 会为您提供一些类型提示,避免发生恼人的拼写错误。
`typescript`
const _greatCipher: Cipher = (k: Uint8Array) => {
const cipher = {
encrypt: (M: Uint8Array) => new U8(k.map((v, i) => v ^ M[i])),
decrypt: (C: Uint8Array) => new U8(k.map((v, i) => v ^ C[i])),
}
return cipher
}
const greatCipherDescription: BlockCipherInfo = {
ALGORITHM: 'GreatCipher',
BLOCK_SIZE: 16,
KEY_SIZE: 16,
MIN_KEY_SIZE: 16,
MAX_KEY_SIZE: 16,
}
const greatCipher = createCipher(_greatCipher, greatCipherDescription)
// GCM-GreatCipher
const gcm_gc = gcm(greatCipher)
`typescript`
interface Cipher {
(key: Uint8Array): Cipherable
}
interface Cipherable {
encrypt: (plaintext: Uint8Array) => U8
decrypt: (ciphertext: Uint8Array) => U8
}
interface BlockCipherInfo {
ALGORITHM: string
/* 分组大小 / Block size (byte) /
BLOCK_SIZE: number
/* 推荐的密钥大小 / Recommended key size (byte) /
KEY_SIZE: number
/* 最小密钥大小 / Minimum key size (byte) /
MIN_KEY_SIZE: number
/* 最大密钥大小 / Maximum key size (byte) /
MAX_KEY_SIZE: number
}
非对称密钥算法是一种使用不同密钥进行加密和解密的加密算法。非对称密钥算法通常包含 公钥 和 私钥,公钥 用于加密,私钥 用于解密。
> mima-kit 不支持也不打算支持 ASN.1 编码。如果您真的需要将密钥对导出为 ASN.1 编码,您可以使用 asn1js 这个库。Node.js
>
> 在 环境中,mima-kit 使用本机 crypto 模块产生素数。而在浏览器环境中,mima-kit 使用 Miller-Rabin 算法产生素数。
Specification: RFC 8017
RSA 算法是一种基于大素数分解的非对称加密算法。mima-kit 提供的 RSA 算法支持大于 256 位的密钥。因为 mima-kit 内部实现的大数运算相关的函数在处理太小的数字时可能会产生错误的结果。且我并没有测试过小于 256 位的密钥,所以我无法保证小于 256 位的密钥是否能正常工作。
> 我想这个世界上应该没有人会使用这么小的密钥吧...
在 PKCS#1 中规定了 RSA 算法的 密码学原语,这些原语是实现规范中其他高级方案的基础。当传入 number 时,rsa 会生成一个带有 原语 能力的 RSA 密钥对。当传入 RSAPrivateKey 或 RSAPublicKey 时,会使用传入的对象作为密钥提供 原语 能力。
> 需要注意的是,原语 的 encrypt, decrypt, sign, verify 方法返回的是 bigint 类型,而不是 U8 类型。
`typescript
// Generate RSA key pair
const key = rsa(2048)
const p = UTF8('mima-kit')
const c = U8.fromBI(key.encrypt(p))
const m = U8.fromBI(key.decrypt(c))
// p === m
const s = U8.fromBI(key.sign(p))
const v = U8.fromBI(key.verify(s))
// v === m
// Using existing key pair
const k: RSAPrivateKey = {
n: 82829320812173273978971929158153744899206558830123557057765054811547521644103n,
e: 65537n,
d: 2824085895826802885484730392051734790667622575612305367583022267256127084981n,
p: 259507137283474348662341935422619692757n,
q: 319179355447530963616684534587734455979n,
dP: 244693883692716798906542597942783565521n,
dQ: 232625874131426773839982556335858160883n,
qInv: 143180457747603899913822528225463864868n,
}
const key = rsa(k)
`
MGF1 是 PKCS#1 标准中的一个函数组件,它用于生成 OAEP 和 PSS 等密码学方案中的 Mask。MGF1 需要组合 Hash 函数,通常 MGF1 不会直接使用,而是作为 OAEP 和 PSS 的一部分。
`typescript`
const mgf = mgf1(sha1)
const seed = new U8()
const length = 32
const mask = mgf(seed, length)
`typescript`
interface MGF {
(mdfSeed: Uint8Array, maskLen: number): Uint8Array
}
RSAES-PKCS1-v1_5 是 PKCS#1 标准中的一个加密方案。
`typescript`
const p = UTF8('mima-kit')
const key = rsa(2048)
const cipher = pkcs1_es_1_5(key)
const c = cipher.encrypt(p)
const m = cipher.decrypt(c)
// p === m
RSAES-OAEP 是 PKCS#1 标准中的一个加密方案。它需要组合 Hash 函数、MGF 函数和 Label 数据。
`typescript
const p = UTF8('mima-kit')
const key = rsa(2048)
// using SHA-256, MGF1-SHA-256, and empty label by default
const cipher = pkcs1_es_oaep(key)
// using SHA-1, MGF1-SHA-1, and empty label
const cipher = pkcs1_es_oaep(key, sha1)
// using SHA-1, MGF1-SHA-256, and label 'mima-kit'
const cipher = pkcs1_es_oaep(key, sha1, mgf1(sha256), UTF8('mima-kit'))
const c = cipher.encrypt(p)
const m = cipher.decrypt(c)
// p === m
`
RSASSA-PKCS1-v1_5 是 PKCS#1 标准中的一个签名方案。它需要组合 Hash 函数。
> RSASSA-PKCS1-v1_5 会用到 Hash 的 OID,mima-kit 中只有部份 Hash 函数记录了 OID,请务必在使用 RSASSA-PKCS1-v1_5 时检查 Hash 函数的 OID 是否正确。
`typescript
const p = UTF8('mima-kit')
const key = rsa(2048)
// check OID before using
sha256.OID = '2.16.840.1.101.3.4.2.1'
// using SHA-256 by default
const cipher = pkcs1_ssa_1_5(key)
// using SHA-1
const cipher = pkcs1_ssa_1_5(key, sha1)
const s = cipher.sign(p)
const v = cipher.verify(p, s)
// v === true
`
RSASSA-PSS 是 PKCS#1 标准中的一个签名方案。它需要组合 Hash 函数、MGF 函数和 Salt Length。
`typescript
const p = UTF8('mima-kit')
const key = rsa(2048)
// using SHA-256, MGF1-SHA-256, and sha256.DIGEST_SIZE
const cipher = pkcs1_ssa_pss(key)
// using SHA-1, MGF1-SHA-1, and sha1.DIGEST_SIZE
const cipher = pkcs1_ssa_pss(key, sha1)
// using SHA-1, MGF1-SHA-256, and sha1.DIGEST_SIZE
const cipher = pkcs1_ssa_pss(key, sha1, mgf1(sha256))
// using SHA-1, MGF1-SHA-256, and 32
const cipher = pkcs1_ssa_pss(key, sha1, mgf1(sha256), 32)
const s = cipher.sign(p)
const v = cipher.verify(p, s)
// v === true
`
> ⚠️ 0.1.0 版本对 ECC 相关接口进行了较多修改;如果您的应用依赖相关模块,请务必检查相关代码。
Specification: SEC 1
Elliptic-Curve Cryptography 是一种基于椭圆曲线的非对称加密算法。mima-kit 支持下列椭圆曲线的 ECC 算法:
- 素域 Weierstrass 曲线Montgomery
- 素域 曲线Koblitz
- 二元扩域 曲线
使用 ECC 算法前需要选择一个 椭圆曲线。参考 椭圆曲线列表。
> 在 mima-kit 的仓库中有许多未导出到包外的 椭圆曲线,您可以在 /src/core/ec_params.ts 中找到这些 椭圆曲线。这些 椭圆曲线 大多是过于老旧且不常用的曲线,我也没有测试过是否能正常地工作。
`typescript`
const ecc = ECC(secp256r1)
// Generate ECC key pair: ECKeyPair
const key = ecc.gen()
const key = ecc.gen('key_pair')
// Generate ECC private key: ECPrivateKey
const s_key = ecc.gen('private_key')
// Generate ECC public key: ECKeyPair
const p_key = ecc.gen('public_key', s_key)
`typescript`
/* 仿射坐标系的点 / Affine Coordinate Point /
interface AffinePoint {
type: 'affine'
isInfinity: boolean
x: bigint
y: bigint
}
interface ECPublicKey {
/* 椭圆曲线公钥 / Elliptic Curve Public Key /
readonly Q: Readonly
}
interface ECPrivateKey {
/* 椭圆曲线私钥 / Elliptic Curve Private Key /
readonly d: bigint
}
interface ECKeyPair extends ECPrivateKey, ECPublicKey {}
Point Compress 是 ECC 算法的公钥压缩方法,用于转换 AffinePoint 和 U8。
`typescript`
const ecc = ECC(secp256r1)
const { PointToU8, U8ToPoint } = ecc.utils
const P = ecc.gen().Q
// will not compress by default
const U = pointToU8(P)
// compress
const U = pointToU8(P, true)
// decompress: AffinePoint
const P = U8ToPoint(U)
Elliptic Curve Diffie-Hellman 是 ECC 算法的一种密钥协商协议。在计算得到共享密钥后,通常会使用 KDF 从共享密钥中派生出一个或多个密钥。
> ECDH 的结果是一个 AffinePoint,通常会使用 x 作为 KDF 的密钥材料。
`typescript`
const ecc = ECC(secp256r1)
const keyA = ecc.gen()
const keyB = ecc.gen()
const secretA = ecc.dh(keyA, keyB).x
const secretB = ecc.dh(keyB, keyA).x
// secretA === secretB
Elliptic Curve Co-factor Diffie-Hellman 是基于 ECDH 的一种密钥协商协议。对曲线参数中 co-factor 为 1 的曲线,ECDH 和 ECCDH 的结果是相同的。
> ECCDH 的结果是一个 AffinePoint,通常会使用 x 作为 KDF 的密钥材料。
`typescript`
const ecc = ECC(w25519)
const keyA = ecc.gen()
const keyB = ecc.gen()
const secretAc = ecc.cdh(keyA, keyB).x
const secretBc = ecc.cdh(keyB, keyA).x
// secretAc === secretBc
Elliptic Curve Menezes-Qu-Vanstone 是基于 ECDH 的一种密钥协商协议。
> ECMQV 的结果是一个 AffinePoint,通常会使用 x 作为 KDF 的密钥材料。
`typescript`
const ecc = ECC(secp256r1)
const u_k1 = ecc.gen()
const u_k2 = ecc.gen()
const v_k1 = ecc.gen()
const v_k2 = ecc.gen()
const secretA = ecc.mqv(u_k1, u_k2, v_k1, v_k2).x
const secretB = ecc.mqv(v_k1, v_k2, u_k1, u_k2).x
// secretA === secretB
Elliptic Curve Digital Signature Algorithm 是 ECC 算法的一种签名方案。
> 需要注意的是,ECDSA 的 签名 方法返回的是 ECDSASignature 对象,而不是 U8 类型。因为 ECDSA 签名的结果包含了 r 和 s 两个值。而在不同的标准下,对 r 和 s 的转换和拼接方式有可能不同。所以返回 ECDSASignature 可以提供更多的灵活性。
`typescript`
const ecc = ECC(secp256r1)
const key = ecc.gen()
const p = UTF8('mima-kit')
// using SHA-256 by default
const signer = ecc.dsa()
// using SHA-1
const signer = ecc.dsa(sha1)
// sign: ECDSASignature
const s = signer.sign(key, p)
const v = signer.verify(key, p, s)
// v === true
`typescript`
interface ECDSASignature {
/* 临时公钥 / Temporary Public Key /
r: bigint
/* 签名值 / Signature Value /
s: bigint
}
ECIES 是 ECC 算法的一种集成加密方案。ECIES 的配置内容比较多,请参考 ECIESConfig 接口。
> ECIES 的结果是一个 ECIESCiphertext 类型,它包含了 临时公钥、密文 和 校验值。
`typescript`
const ecc = ECC(secp256r1)
const key = ecc.gen()
const cipher = ecc.ies()
const p = UTF8('mima-kit')
const c = cipher.encrypt(key, p)
const m = cipher.decrypt(key, c)
// p === m
`typescript`
interface ECIESConfig {
/* 分组密码算法 / Block Cipher Algorithm (default: AES-256-GCM) /
cipher?: IVBlockCipher
/* 密钥哈希函数 / Key Hash Function (default: HMAC-SHA-256) /
mac?: KeyHash
/* 密钥派生函数 / Key Derivation Function (default: ANSI-X9.63-KDF with SHA-256) /
kdf?: KDF
/* 附加数据1 / Additional Data 1 (default: empty) /
S1?: Uint8Array
/* 附加数据2 / Additional Data 2 (default: empty) /
S2?: Uint8Array
/* 初始化向量 / Initialization Vector (default: Uint8Array(cipher.BLOCK_SIZE)) /
iv?: Uint8Array
}
interface ECIESCiphertext {
/* 临时公钥 / Temporary Public Key /
R: ECPublicKey
/* 密文 / Ciphertext /
C: Uint8Array
/* 校验值 / Check Value /
D: Uint8Array
}
Specification: GB/T 35276-2017
SM2 算法是中国国家密码管理局发布的一种基于 椭圆曲线 的 非对称加密算法。理论上,SM2 算法可以使用任意的 椭圆曲线,但是在实际应用中,SM2 算法通常使用 sm2p256v1 曲线,所以 mima-kit 使用 sm2p256v1 曲线作为 SM2 算法的默认曲线。
> 由于 SM2 和 ECC 使用相同的运算底层,ECC 支持的曲线 SM2 也同样可用。请注意,这不是 SM2 的标准用法且缺乏相关的安全分析。
`typescript`
const sm2ec = sm2()
// Generate SM2 key pair
const key = sm2ec.gen()
const key = sm2ec.gen('key_pair')
// Generate SM2 private key
const s_key = sm2ec.gen('private_key')
// Generate SM2 public key
const p_key = sm2ec.gen('public_key', s_key)
SM2 在 ECC 的基础上增加了 可辨别标识 (Distinguishing Identifier) 的概念。可辨别标识 利用用户标识、公钥和曲线的部分参数,实现无歧义地标识实体的身份信息。
`typescript`
const sm2ec = sm2()
const ID = UTF8('alice@rabbit.panic')
const KA = sm2ec.gen()
const ZA = sm2ec.di(ID, KA)
`typescript`
interface SM2DI {
/**
* @param {Uint8Array} id - 用户标识 / User Identity
* @param {ECPublicKey} key - 公钥 / Public Key
* @param {Hash} hash - 哈希算法 / Hash Algorithm (default: SM3)
*/
(id: Uint8Array, key: ECPublicKey, hash?: Hash): U8
}
SM2 算法的密钥协商协议。与标准不同,mima-kit 的 SM2-DH 直接返回 共享密钥。你需要另外使用 KDF 从 共享密钥 中派生密钥。SM2 标准使用的 KDF 是 ANSI-X9.63-KDF with SM3。ANSI-X9.63-KDF 和 SM3 都是 mima-kit 支持的算法,你可以直接使用她们。
`typescript
const sm2ec = sm2()
const kdf = x963kdf(sm3)
// Initiator: Alice
// Responder: Bob
// Step 1: Alice
const KA = sm2ec.gen()
const KX = sm2ec.gen()
const ka = { Q: KA.Q } // public key of Alice
const kx = { Q: KX.Q } // temporary public key of Alice
const ID_A = UTF8('alice@rabbit.panic')
const ZA = sm2ec.di(ID_A, KA) // Alice's distinguishable identifier
// send ZA, ka, kx to Bob
// Step 2: Bob
const KB = sm2ec.gen()
const KY = sm2ec.gen()
const kb = { Q: KB.Q } // public key of Bob
const ky = { Q: KY.Q } // temporary public key of Bo
const ID_B = UTF8('bob@rolling.stone')
const ZB = sm2ec.di(ID_B, KB) // Bob's distinguishable identifier
const SB = sm2ec.dh(KB, KY, ka, kx, ZA, ZB) // shared secret key
const DKB = kdf(256, S) // derive key
// send ZB, kb, ky to Alice
// Step 3: Alice
const SA = sm2ec.dh(KA, KX, kb, ky, ZA, ZB) // shared secret key
const DKA = kdf(256, S) // derive key
SA === SB
DKA === DKB
`
`typescript`
interface SM2DH {
/**
* @param {ECKeyPair} KA - 己方密钥对 / Self Key Pair
* @param {ECPublicKey} KX - 己方临时密钥对 / Self Temporary Key Pair
* @param {ECPublicKey} KB - 对方公钥 / Opposite Public Key
* @param {ECPublicKey} KY - 对方临时公钥 / Opposite Temporary Public Key
* @param [Uint8Array] ZA - 发起方标识派生值 / Initiator Identity Derived Value
* @param [Uint8Array] ZB - 接收方标识派生值 / Receiver Identity Derived Value
* @returns {U8} - 密钥材料 / Keying Material
*/
(KA: ECKeyPair, KX: ECKeyPair, KB: ECPublicKey, KY: ECPublicKey, ZA?: Uint8Array, ZB?: Uint8Array): U8
}
SM2 Digital Signature Algorithm 是 SM2 算法的签名方案。她接受一个 Hash 函数作为参数,SM2-DSA 使用 SM3 作为默认的 Hash 函数。
> SM2-DSA 的 签名 方法返回的是 SM2DSASignature 类型,而不是 U8 类型。SM2-DSA 签名的结果包含了 r 和 s 两个值。
`typescript
const sm2ec = sm2()
const ID = UTF8('alice@rabbit.panic')
const KA = sm2ec.gen()
const ZA = sm2ec.di(ID, KA)
const M = UTF8('mima-kit')
const signer = sm2ec.dsa() // using SM3 by default
const signature = signer.sign(ZA, KA, M)
signer.verify(ZA, KA, M, signature) // true
`
`typescript`
interface SM2DSASignature {
r: bigint
s: bigint
}
interface SM2DSA {
/**
* @param {Hash} hash - 哈希算法 / Hash Algorithm (default: SM3)
*/
(hash?: Hash): {
/**
* @param {Uint8Array} Z - 标识派生值 / Identity Derived Value
* @param {ECPrivateKey} key - 签名方私钥 / Signer Private Key
* @param {Uint8Array} M - 消息 / Message
*/
sign: (Z: Uint8Array, key: ECPrivateKey, M: Uint8Array) => SM2DSASignature
/**
* @param {Uint8Array} Z - 标识派生值 / Identity Derived Value
* @param {ECPublicKey} key - 签名方公钥 / Signer Public Key
* @param {Uint8Array} M - 消息 / Message
* @param {SM2DSASignature} S - 签名 / Signature
*/
verify: (Z: Uint8Array, key: ECPublicKey, M: Uint8Array, S: SM2DSASignature) => boolean
}
}
SM2-ES 是 SM2 算法的集成加密方案。
`typescript
const sm2ec = sm2(curve)
const M = UTF8('Labhraí Loingseach has donkey’s ears')
const key = sm2ec.gen()
const cipher = sm2ec.es()
const C = cipher.encrypt(key, M)
cipher.decrypt(key, C) // M
`
`typescript`
interface SM2Encrypt {
/**
* @param {ECPublicKey} p_key - 接收方公钥 / Receiver Public Key
* @param {Uint8Array} M - 明文 / Plaintext
*/
(p_key: ECPublicKey, M: Uint8Array): U8
}
interface SM2Decrypt {
/**
* @param {ECPrivateKey} s_key - 解密方私钥 / Decryptor Private Key
* @param {Uint8Array} C - 密文 / Ciphertext
*/
(s_key: ECPrivateKey, C: Uint8Array): U8
}
interface SM2EncryptionScheme {
/**
* @param {Hash} hash - 哈希算法 / Hash Algorithm (default: SM3)
* @param {KDF} kdf - 密钥派生函数 / Key Derivation Function (default: X9.63 KDF with SM3)
* @param {'c1c2c3' | 'c1c3c2'} order - 密文分段顺序 / Ciphertext Segment Order (default: 'c1c3c2')
*/
(hash?: Hash, kdf?: KDF, order?: 'c1c2c3' | 'c1c3c2'): {
encrypt: SM2Encrypt
decrypt: SM2Decrypt
}
}
Specification: RFC 7748
x25519 和 x448 是基于 Montgomery 曲线的 ECC 算法。他们不是 ECC 的实例,而是单独的算法。
> 需要注意 mima-kit 提供的 x25519 和 x448 可能无法与其他实现完全兼容。因为 RFC 7748 规定以 小端序 作为编码方式,而 mima-kit 使用 大端序 作为编码方式。通过转换 端序 应该可以与其他实现兼容。
> 虽然 ECC 也可以进行 Montgomery 曲线的计算,但是 x25519 和 x448 算法只需要 x 坐标,且他们的算法实施都会对私钥进行 clamp 处理,所以他们的底层是更高效的独立算法。
`typescript`
// Generate key pair: X25519KeyPair
const key = x25519.gen()
const key = x25519.gen('key_pair')
// Generate private key: X25519PrivateKey
const s_key = x25519.gen('private_key')
// Generate public key: X25519KeyPair
const p_key = x25519.gen('public_key', s_key)
`typescript`
interface X25519PrivateKey
/* 私钥 / Private Key /
d: T
}
interface X25519PublicKey
/* 公钥 / Public Key /
Q: T
}
interface X25519KeyPair
}
x25519 和 x448 算法的密钥协商协议。与标准不同,他们直接返回 共享密钥。你需要另外使用 KDF 从 共享密钥 中派生密钥。
`typescript`
const keyA = x25519.gen()
const keyB = x25519.gen()
const secretA = x25519.dh(keyA, keyB)
const secretB = x25519.dh(keyB, keyA)
// secretA === secretB
密钥派生函数 (KDF) 是一种从一个密钥派生出另一个或多个密钥的算法。KDF 很少直接使用,而是作为其他算法方案的一部分。
`typescript`
interface KDF {
/**
* @param {number} k_byte - 期望的密钥长度 / output keying material length
* @param {Uint8Array} ikm - 输入密钥材料 / input keying material
* @param {Uint8Array} salt - 盐 / salt value
*/
(k_byte: number, ikm: Uint8Array, salt?: Uint8Array): U8
}
X9.63KDF 是 ANSI-X9.63 标准中的一个密钥派生函数。X9.63KDF 需要组合 Hash 函数和一个可选的 info。
对 X9.63KDF 输入的 salt 将被忽略。
`typescript
const info = new U8(0)
const kdf = x963kdf(sha256, info)
const k_byte = 64
const ikm = new U8(32)
const salt = new U8(32) // ignore
const k0 = kdf(k_byte, ikm, salt)
const k1 = kdf(k_byte, ikm)
k0 === k1 // true
`
HKDF 是 RFC 5869 标准中的一个密钥派生函数。HKDF 需要组合 KeyHash 函数和一个可选的 info。
`typescript`
const mac = hmac(sha256)
const info = new U8(0)
const kdf = hkdf(mac, info)
PBKDF2 是 PKCS#5 标准中的一个密钥派生函数。PBKDF2 需要组合 KeyHash 函数。
默认情况下 iteration 为 1000。
`typescript`
const mac = hmac(sha256)
const kdf = pbkdf2(mac, 1000)
scrypt 是 RFC 7914 标准中的一个密钥派生函数。scrypt 可以指定开销因子、块数、并行因子、最大内存使用量,甚至是内部使用的 kdf。mima-kit 提供的 scrypt 基于 noble-hashes 的实现。
`typescript
const kdf = scrypt()
const config: ScryptConfig = {
N: 16384, // 开销因子
r: 8, // 块数
p: 1, // 并行因子
}
const kdf = scrypt(config)
`
`typescriptPBKDF2-HMAC-SHA256
interface ScryptConfig {
/**
* 开销因子 / Cost factor (default: 16384)
*
* 必须是 2 的幂
*/
N?: number
/**
* 块数 / Block count (default: 8)
*/
r?: number
/**
* 并行因子 / Parallelization factor (default: 1)
*/
p?: number
/**
* 最大内存使用量 / Maximum memory usage
*
* 如果设置为 0,则不限制内存使用量
*
* (default: 0x40000400 bytes, 1GB + 1KB)
*/
maxmem?: number
/**
* 密钥派生函数 / Key Derivation Function
*
* scrypt 标准使用了 作为 KDF。scrypt
* 该参数允许用户指定其他 KDF,改变 scrypt 的内部行为。
*
* 注意: 这不是 的标准用法且缺乏相关的安全分析。`
*
* (default: pbkdf2(hmac(sha256), 1))
*/
kdf?: KDF
}
mima-kit 并没有导出所有的 椭圆曲线,但是您可以在 /src/core/ec_params.ts 中找到所有的 椭圆曲线。
> 在表格之外,sm2p256v1 也是导出的 Weierstrass 曲线。它适用于所有 ECC 算法,但是它常用于 SM2 算法,所以不写入表格之中。
| SEC | NIST | X9.63 | RFC 5639 |
|-------------|----------|--------------|-----------|
| - | w25519 | - | - |w448
| - | | - | - |secp192k1
| | - | - | - |secp192r1
| | p192 | prime192v1 | - |secp224k1
| | - | - | - |secp224r1
| | p224 | - | - |secp256r1
| | p256 | prime256v1 | - |secp256k1
| | - | - | - |secp384r1
| | p384 | - | - |secp521r1
| | p521 | - | - |bp192r1
| - | - | - | |bp224r1
| - | - | - | |bp256r1
| - | - | - | |bp320r1
| - | - | - | |bp384r1
| - | - | - | |bp512r1` |
| - | - | - |
| NIST |
|------------|
| Curve25519 |
| Curve448 |
| Type | SEC |
|---------|-----------|
| Koblitz | sect163k1 |
| Random | sect163r1 |
| Random | sect163r2 |
| Koblitz | sect233k1 |
| Random | sect233r1 |
| Koblitz | sect239k1 |
| Koblitz | sect283k1 |
| Random | sect283r1 |
| Koblitz | sect409k1 |
| Random | sect409r1 |
| Koblitz | sect571k1 |
| Random | sect571r1 |
MIT License © 2023-PRESENT RSoraM
[npm-version-src]: https://img.shields.io/npm/v/mima-kit?style=for-the-badge
[npm-version-href]: https://npmjs.com/package/mima-kit
[npm-downloads-src]: https://img.shields.io/npm/dm/mima-kit?style=for-the-badge
[npm-downloads-href]: https://npmjs.com/package/mima-kit
[bundle-src]: https://img.shields.io/bundlephobia/minzip/mima-kit?style=for-the-badge&label=minzip
[bundle-href]: https://bundlephobia.com/result?p=mima-kit
[license-src]: https://img.shields.io/github/license/RSoraM/mima-kit.svg?style=for-the-badge
[license-href]: https://github.com/RSoraM/mima-kit/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsDocs-reference-pink?style=for-the-badge
[jsdocs-href]: https://www.jsdocs.io/package/mima-kit