diff --git a/README.md b/README.md index 464bab0..d07ff1f 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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) ``` ## 包装您的加密散列算法 diff --git a/README/README-en.md b/README/README-en.md index f8281f7..a7feb34 100644 --- a/README/README-en.md +++ b/README/README-en.md @@ -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 @@ -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 diff --git a/src/cipher/pkcs/ecc.ts b/src/cipher/pkcs/ecc.ts index 6bf8c36..51bf775 100644 --- a/src/cipher/pkcs/ecc.ts +++ b/src/cipher/pkcs/ecc.ts @@ -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) => { @@ -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) diff --git a/src/core/hash.ts b/src/core/hash.ts index f55bb45..b65a2ff 100644 --- a/src/core/hash.ts +++ b/src/core/hash.ts @@ -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) @@ -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 { } diff --git a/src/core/kdf.ts b/src/core/kdf.ts index 35db86a..7880fee 100644 --- a/src/core/kdf.ts +++ b/src/core/kdf.ts @@ -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]++ } @@ -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) diff --git a/src/hash/hmac.ts b/src/hash/hmac.ts index 1d907f6..22c7ab5 100644 --- a/src/hash/hmac.ts +++ b/src/hash/hmac.ts @@ -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) { @@ -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, ) } diff --git a/src/hash/sha3Derived.ts b/src/hash/sha3Derived.ts index 1766144..5096265 100644 --- a/src/hash/sha3Derived.ts +++ b/src/hash/sha3Derived.ts @@ -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, ) } @@ -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, ) } @@ -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, ) } @@ -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, ) } diff --git a/test/hash.test.ts b/test/hash.test.ts index a43733b..ce396c9 100644 --- a/test/hash.test.ts +++ b/test/hash.test.ts @@ -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)) @@ -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) {