@@ -22,6 +22,7 @@ import {
2222} from "./Type.js" ;
2323import { Brand } from "./Brand.js" ;
2424import { assert } from "./Assert.js" ;
25+ import { utf8ToBytes } from "./Buffer.js" ;
2526
2627/** `Uint8Array` created by {@link createRandomBytes}. */
2728export type RandomBytes = Uint8Array & Brand < "RandomBytes" > ;
@@ -56,25 +57,37 @@ export const mnemonicToMnemonicSeed = (mnemonic: Mnemonic): MnemonicSeed =>
5657 * https://github.com/satoshilabs/slips/blob/master/slip-0021.md
5758 */
5859export const createSlip21 = (
59- seed : MnemonicSeed ,
60+ seed : Uint8Array ,
6061 path : ReadonlyArray < string > ,
6162) : Uint8Array => {
6263 assert (
6364 seed . length >= 16 && seed . length <= 64 ,
6465 `Unusual SLIP-0021 seed length: ${ seed . length } bytes` ,
6566 ) ;
6667
67- let m = hmac ( sha512 , "Symmetric key seed" , seed ) ;
68+ let m = hmac ( sha512 , utf8ToBytes ( "Symmetric key seed" ) , seed ) ;
6869 for ( const component of path ) {
69- const p = new TextEncoder ( ) . encode ( component ) ;
70- const e = new globalThis . Uint8Array ( p . byteLength + 1 ) ;
71- e [ 0 ] = 0 ;
72- e . set ( p , 1 ) ;
73- m = hmac ( sha512 , m . slice ( 0 , 32 ) , e ) ;
70+ m = deriveSlip21Node ( component , m ) ;
7471 }
7572 return m . slice ( 32 , 64 ) ;
7673} ;
7774
75+ /**
76+ * Derives a single node in the SLIP-21 hierarchical key derivation.
77+ *
78+ * @see {@link createSlip21 }
79+ */
80+ export const deriveSlip21Node = (
81+ component : string ,
82+ m : Uint8Array ,
83+ ) : Uint8Array => {
84+ const p = utf8ToBytes ( component ) ;
85+ const e = new globalThis . Uint8Array ( p . byteLength + 1 ) ;
86+ e [ 0 ] = 0 ;
87+ e . set ( p , 1 ) ;
88+ return hmac ( sha512 , m . slice ( 0 , 32 ) , e ) ;
89+ } ;
90+
7891/**
7992 * Creates a 21-character Base64URL ID (also known as nanoid) from a SLIP-21
8093 * derived key.
0 commit comments