Skip to content

Commit

Permalink
refactor: 💡 修改 key hash 接口
Browse files Browse the repository at this point in the history
我当初为什么这么设计来着?

BREAKING CHANGE: 🧨 hmac kmac
  • Loading branch information
RSoraM committed Dec 12, 2024
1 parent 295aa69 commit 1e4b30e
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 50 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,11 @@ Specification: [RFC 2104](https://www.rfc-editor.org/rfc/rfc2104.txt)
const key = UTF8('password')
const m = UTF8('mima-kit')
// HMAC-SM3
hmac(sm3)(key)(m).to(HEX)
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, 80)(key, m).to(HEX)
// HMAC-SHA1-160 with 160-bit digest and 80-bit key
hmac(sha1, 160, 80)(key)(m).to(HEX)
hmac(sha1, 160, 80)(key, m).to(HEX)
```

### KMAC
Expand All @@ -357,10 +357,10 @@ 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)
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)
```

## 包装您的加密散列算法
Expand Down
14 changes: 7 additions & 7 deletions README/README-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,11 @@ Specification: [RFC 2104](https://www.rfc-editor.org/rfc/rfc2104.txt)
const key = UTF8('password')
const m = UTF8('mima-kit')
// HMAC-SM3
hmac(sm3)(key)(m).to(HEX)
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, 80)(key, m).to(HEX)
// HMAC-SHA1-160 with 160-bit digest and 80-bit key
hmac(sha1, 160, 80)(key)(m).to(HEX)
hmac(sha1, 160, 80)(key, m).to(HEX)
```

### KMAC
Expand All @@ -359,10 +359,10 @@ 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)
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)
```

## Wrap Your Hash Algorithm
Expand Down
6 changes: 2 additions & 4 deletions src/cipher/pkcs/ecc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,10 +451,9 @@ export function FpECC(curve: FpWECParams): FpECCrypto {
const KE = K.slice(0, cipher.KEY_SIZE)
const KM = K.slice(cipher.KEY_SIZE, cipher.KEY_SIZE + mac.KEY_SIZE)
const _cipher = cipher(KE, iv)
const _mac = mac(KM)
const R: ECPublicKey = { Q: s_key.Q }
const C = _cipher.encrypt(M)
const D = _mac(joinBuffer(C, S2))
const D = mac(KM, joinBuffer(C, S2))
return { R, C, D }
}
const decrypt = (s_key: ECPrivateKey, CT: ECIESCiphertext) => {
Expand All @@ -469,9 +468,8 @@ export function FpECC(curve: FpWECParams): FpECCrypto {
const KE = K.slice(0, cipher.KEY_SIZE)
const KM = K.slice(cipher.KEY_SIZE, cipher.KEY_SIZE + mac.KEY_SIZE)
const _cipher = cipher(KE, iv)
const _mac = mac(KM)
// 校验
if (_mac(joinBuffer(C, S2)).some((v, i) => v !== D[i])) {
if (mac(KM, joinBuffer(C, S2)).some((v, i) => v !== D[i])) {
throw new KitError('ECIES Decryption failed')
}
const M = _cipher.decrypt(C)
Expand Down
13 changes: 8 additions & 5 deletions src/core/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ export const createTupleHash = (digest: TupleDigest, description: TupleHashDescr

// * 密钥散列函数

export interface KeyDigest {
/**
* @param {Uint8Array} K - 密钥 / key
* @param {Uint8Array} M - 消息 / message
*/
(K: Uint8Array, M: Uint8Array): U8
}
export interface KeyHashDescription extends HashDescription {
/**
* Recommended key size (byte)
Expand All @@ -91,9 +98,5 @@ export interface KeyHashDescription extends HashDescription {
*
* Keyed hash function
*/
export interface KeyHash extends KeyHashDescription {
/**
* @param {Uint8Array} K - 密钥 / key
*/
(K: Uint8Array): Hash
export interface KeyHash extends KeyDigest, KeyHashDescription {
}
6 changes: 3 additions & 3 deletions src/core/kdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ export function hkdf(k_hash: KeyHash, salt = new Uint8Array(k_hash.DIGEST_SIZE))
const d_bit = k_hash.DIGEST_SIZE << 3
return (k_bit: number, ikm: Uint8Array, info = new Uint8Array(0)) => {
/** Pseudo-Random Key */
const prk = k_hash(salt)(ikm)
const prk = k_hash(salt, ikm)
/** Output Keying Material */
const okm: Uint8Array[] = []

const counter = new Uint8Array([1])
let prv = new Uint8Array(0)
for (let okm_bit = 0; okm_bit < k_bit; okm_bit += d_bit) {
prv = k_hash(prk)(joinBuffer(prv, info, counter))
prv = k_hash(prk, joinBuffer(prv, info, counter))
okm.push(prv)
counter[0]++
}
Expand Down Expand Up @@ -80,7 +80,7 @@ export function pbkdf2(k_hash: KeyHash, salt = new Uint8Array(k_hash.DIGEST_SIZE
T = new Uint8Array(k_hash.DIGEST_SIZE)
U = joinBuffer(salt, counter)
for (let i = 0; i < iterations; i++) {
U = k_hash(ikm)(U)
U = k_hash(ikm, U)
T.forEach((_, j) => T[j] ^= U[j])
}
okm.push(T)
Expand Down
6 changes: 1 addition & 5 deletions src/hash/hmac.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Hash, KeyHash, KeyHashDescription } from '../core/hash'
import { createHash } from '../core/hash'
import { joinBuffer, wrap } from '../core/utils'

function _hmac(hash: Hash, K: Uint8Array, M: Uint8Array) {
Expand Down Expand Up @@ -40,10 +39,7 @@ export function hmac(hash: Hash, d_size?: number, k_size?: number): KeyHash {
KEY_SIZE: k_size,
}
return wrap(
(K: Uint8Array) => {
const digest = (M: Uint8Array) => _hmac(hash, K, M).slice(0, d_size)
return createHash(digest, description)
},
(K: Uint8Array, M: Uint8Array) => _hmac(hash, K, M).slice(0, d_size),
description,
)
}
8 changes: 4 additions & 4 deletions src/hash/sha3Derived.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export function kmac128(d: number, S = new Uint8Array(0), k_size: number = 128):
return Keccak_c(256, d, cShakePadding)(joinBuffer(...X))
}
return wrap(
(K: Uint8Array) => createHash((M: Uint8Array) => digest(K, M), description),
(K: Uint8Array, M: Uint8Array) => digest(K, M),
description,
)
}
Expand Down Expand Up @@ -280,7 +280,7 @@ export function kmac256(d: number, S = new Uint8Array(0), k_size: number = 256):
return Keccak_c(512, d, cShakePadding)(joinBuffer(...X))
}
return wrap(
(K: Uint8Array) => createHash((M: Uint8Array) => digest(K, M), description),
(K: Uint8Array, M: Uint8Array) => digest(K, M),
description,
)
}
Expand Down Expand Up @@ -311,7 +311,7 @@ export function kmac128XOF(d: number, S = new Uint8Array(0), k_size: number = 12
return Keccak_c(256, d, cShakePadding)(joinBuffer(...X))
}
return wrap(
(K: Uint8Array) => createHash((M: Uint8Array) => digest(K, M), description),
(K: Uint8Array, M: Uint8Array) => digest(K, M),
description,
)
}
Expand Down Expand Up @@ -342,7 +342,7 @@ export function kmac256XOF(d: number, S = new Uint8Array(0), k_size: number = 25
return Keccak_c(512, d, cShakePadding)(joinBuffer(...X))
}
return wrap(
(K: Uint8Array) => createHash((M: Uint8Array) => digest(K, M), description),
(K: Uint8Array, M: Uint8Array) => digest(K, M),
description,
)
}
Expand Down
30 changes: 15 additions & 15 deletions test/hash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,17 @@ describe('sha3', () => {
expect(cShake256(512, fn2, custom)(meow).to(HEX)).toMatchInlineSnapshot('"6ba1b872ade77effc824d222654c841d8a99369b533e540007ac3383693d3ff68687892dbd2cc2ea3c8ae61578a6c3c0c7a89235db524db223ff7770293724a3"')
})
it('kmac', () => {
const _ = UTF8('')
const empty = UTF8('')
const meow = UTF8('meow, 喵, 🐱')
const custom = UTF8('custom')
const key = UTF8('password')
expect(kmac128(256, _)(_)(_).to(HEX)).toMatchInlineSnapshot('"5c135c615152fb4d9784dd1155f9b6034e013fd77165c327dfa4d36701983ef7"')
expect(kmac128(256, custom)(key)(meow).to(HEX)).toMatchInlineSnapshot(`"ef74e577ff0eef49974b6c2a707067ac6d3fba7afeccc2ff3ea40935d0471635"`)
expect(kmac128XOF(256, custom)(key)(meow).to(HEX)).toMatchInlineSnapshot(`"8e8b4b4eacf9feee5bec9559a6091f48ee3c26de38adb4191e9eadf8f428f0fd"`)
expect(kmac128(256, empty)(empty, empty).to(HEX)).toMatchInlineSnapshot('"5c135c615152fb4d9784dd1155f9b6034e013fd77165c327dfa4d36701983ef7"')
expect(kmac128(256, custom)(key, meow).to(HEX)).toMatchInlineSnapshot(`"ef74e577ff0eef49974b6c2a707067ac6d3fba7afeccc2ff3ea40935d0471635"`)
expect(kmac128XOF(256, custom)(key, meow).to(HEX)).toMatchInlineSnapshot(`"8e8b4b4eacf9feee5bec9559a6091f48ee3c26de38adb4191e9eadf8f428f0fd"`)

expect(kmac256(512, _)(_)(_).to(HEX)).toMatchInlineSnapshot('"2b70c18a81bb6446868dbc411e0dc1331c4399101d6b8b14ea16e951eee001033207bfe3bede15b946bfc209c62fc5d95e3e7b530b507319f24947d6ad7c18fe"')
expect(kmac256(512, custom)(key)(meow).to(HEX)).toMatchInlineSnapshot(`"7ac4bd71ef93bfa57560f069ed832b785b9ddd855200974a9025240c44f39d8739c31c201f92919c075bcac16313761765c32a20b8a1dbae1cef32e015e3e7f5"`)
expect(kmac256XOF(512, custom)(key)(meow).to(HEX)).toMatchInlineSnapshot(`"16066139244a9b649547be5fa349a3f9ce568ab6dcb753b00573cca1d2f6b47e354e175520fff098c3124048f8524771518e4cae9de9f026c76b347dc79058f2"`)
expect(kmac256(512, empty)(empty, empty).to(HEX)).toMatchInlineSnapshot('"2b70c18a81bb6446868dbc411e0dc1331c4399101d6b8b14ea16e951eee001033207bfe3bede15b946bfc209c62fc5d95e3e7b530b507319f24947d6ad7c18fe"')
expect(kmac256(512, custom)(key, meow).to(HEX)).toMatchInlineSnapshot(`"7ac4bd71ef93bfa57560f069ed832b785b9ddd855200974a9025240c44f39d8739c31c201f92919c075bcac16313761765c32a20b8a1dbae1cef32e015e3e7f5"`)
expect(kmac256XOF(512, custom)(key, meow).to(HEX)).toMatchInlineSnapshot(`"16066139244a9b649547be5fa349a3f9ce568ab6dcb753b00573cca1d2f6b47e354e175520fff098c3124048f8524771518e4cae9de9f026c76b347dc79058f2"`)
})
it('tupleHash', () => {
const m = ['meow', '喵', '🐱'].map(v => UTF8(v))
Expand Down Expand Up @@ -154,16 +154,16 @@ it('hmac', () => {
const lorem = UTF8('xqxokmcswidaxxhpihnxorkqijxcuimukvkfpajpmxpgvvsoalctwhduvnatkhswijvngzpfwyxyycaxxiggtxhfucubguovxpwenosdnanqhefmqypqcehjmqxhnonipdlkfqufitmznkaautleeeestcwhvtdwmnfqsvjbxvsocmvshdqufdaxmvrjafpqcxwiczgoyhzgmxttlvydtnltebuqrwwoftgwokpuvnyccmeewauzvnixzpdksdlrqvdxthtyarobmwbyymqdnqaekczrhdupfcbtvzvdathjgrcytefgplbjfenjnzwohktafimwixswiggnidoatbeejlweuznphnxyhbbbwnubzuvwgjcdhhxszhnjulsavzfkkcbmjfgwiedqqzlhtjfcjeulcbjsaagglvmplprxqwhpxnyqfgtcqxghvbcahhguenbbzaaodqhlexgwpohwzmvcovmsksmvgkmbtfkomztnaabjzngbwujqbpuopytsotzyooikasrwftsjzkavfzhikvicsghrrmxeskcjrnhvlwaikwdjpdytnbfebliygpjzhsgcidtoyihtwlbwgrpngigonpjzbvuyyseibdgwgfefobvnduwympccyfevseqtbhwmbknldvzlkskbrxuxjdocpazjizixmthntuclfigpraiekufbpfgsfpytegmwdqvtxgxygcytxwjvjildrrqhfpittjnlydthgoysgfkpbypnbtagmpdyzmodogrxoxqiicjhzlmfqavbhtopxnmhdzzcukcqywzcyajckxqljnqzpsqkfenboayiqbfbqbjtiyxbxwzbirpbeikuyyhwbbrirzfbrbvkjpsftokpiezyiroxycqdjkrgssakuwrvuqqppecvwnufvapbgmblxleesdncjlhlqjiszvcxevtcnhgjdeoimdrziqjbmdqjiaoryodxepmweypxwwjczzkdnzmwbpmmpicihclwgxaxvrwfvsyawelwhwjzqeilmgykdyxzbtbnwlzyhyzsyolbwjujxlbilcjtgqqzrirznypkzwavchlwjzbjfmijoxacbdowbjbmifwctonqmxqvgsgmqnqraoqxezdkcqnmnpojxuktqopsuocsiqfjvtolsnflouvicscngescvvtoskngblqjwbxcczqgxfhjhajqhifylpuksaafoialypdgnywpevcmmepvopdircucjaylvecunojfyngozadyysfetqfutropvlewfkmpnefyttwogjevmriqbaxpddnajhhoxjvbbcnidkqlrtpgngqzxwcxfwjpldxwyoeuocafvhiooyhsdvpdahrivovnmzwgkbgorgcmatpkepzczorvfhmcnqazvykpxxwxjuxydtilfsrkxubzjcweqfywabddkuiqupungujxvjxlyifvfudnbnwahjpnyfnnjsmcebnoqxpqvxysygyrynxjuktjeojgklxbmxlulqrlfmiyjzvhkxikzesoxalpgxjwyhlxflyhzufoiskghnzrzcunmhhcdpmudbfipxdjaivyhamnxrseyoskjnnhpzpjkrqltrbcbnaodiiigfyxugifgujnqxhgumegxeyaonanmzcnjkidmnacxjzncfgpcagfbwcukjvusgtclkeouoqwpngtixbpixrdtlkxjysslzmorfbnnbmnehokdtqiwxmppmimfowmigausofrjflkotlhdszumlrtjrxkxlndzanfoalhvibkitklnrshlhpjzofjztsxmdfexhunxlkdpuhttxrppnflqsvwepneyvskubezsvnzwgsshclwgizsckghlxeyffkczxyrqdjtdrqasxybrdntputkarkxrqsdvueefrdctnltnnlmdedkqimqdvflnfqrlydsxzmriaydhirlyccpbtwhfxcraofzyrydpedrrirgfnbadexjbwuiufsozncrlgqqtuiwtaxscljvbfbpbpefzvecuoqc')
const password = UTF8('password')

const hmac_sha256 = hmac(sha256)(password)
expect(hmac_sha256(meow).to(HEX)).toMatchInlineSnapshot('"d1460c736797bff7d4ff11940451421e7f693a7d1d7b10e2a2c163f11a9ca53c"')
expect(hmac_sha256(lorem).to(HEX)).toMatchInlineSnapshot('"6298a318f4926c6dab11ce985146d60fec36b6c10f863bbff67d0c301e0fb140"')
const hmac_sha256 = hmac(sha256)
expect(hmac_sha256(password, meow).to(HEX)).toMatchInlineSnapshot('"d1460c736797bff7d4ff11940451421e7f693a7d1d7b10e2a2c163f11a9ca53c"')
expect(hmac_sha256(password, lorem).to(HEX)).toMatchInlineSnapshot('"6298a318f4926c6dab11ce985146d60fec36b6c10f863bbff67d0c301e0fb140"')

const hmac_sm3 = hmac(sm3)(password)
expect(hmac_sm3(meow).to(HEX)).toMatchInlineSnapshot('"c8e111cdad100b08d04315081893bd5ac0b75180c492abe2fadcfbe027924904"')
expect(hmac_sm3(lorem).to(HEX)).toMatchInlineSnapshot('"396a39e89a34ed585d29c30ea316dac259cbcf6424512424e04f1cb96975f671"')
const hmac_sm3 = hmac(sm3)
expect(hmac_sm3(password, meow).to(HEX)).toMatchInlineSnapshot('"c8e111cdad100b08d04315081893bd5ac0b75180c492abe2fadcfbe027924904"')
expect(hmac_sm3(password, lorem).to(HEX)).toMatchInlineSnapshot('"396a39e89a34ed585d29c30ea316dac259cbcf6424512424e04f1cb96975f671"')

const hmac_sha3 = hmac(sha3_256)(password)
expect(hmac_sha3(meow).to(HEX)).toMatchInlineSnapshot('"969bdb3d05db27ee7df5ba69b6e2e2bf5d7abb3b13e8c181d6418d6f0403f3f0"')
const hmac_sha3 = hmac(sha3_256)
expect(hmac_sha3(password, meow).to(HEX)).toMatchInlineSnapshot('"969bdb3d05db27ee7df5ba69b6e2e2bf5d7abb3b13e8c181d6418d6f0403f3f0"')
})
// * TurboSHAKE
function ptn(n: number) {
Expand Down

0 comments on commit 1e4b30e

Please sign in to comment.