slip10.hoon 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. :: slip-10 implementation in hoon using the cheetah curve
  2. ::
  3. :: to use, call one of the core initialization arms.
  4. :: using the produced core, derive as needed and take out the data you want.
  5. ::
  6. :: NOTE: tested to be correct against the SLIP-10 spec
  7. :: https://github.com/satoshilabs/slips/blob/master/slip-0010.md
  8. ::
  9. /= * /common/zose
  10. /= * /common/zeke
  11. =, hmac:crypto
  12. =, cheetah:zeke
  13. =+ ecc=cheetah
  14. ::
  15. :: prv: private key
  16. :: pub: public key
  17. :: cad: chain code
  18. :: dep: depth in chain
  19. :: ind: index at depth
  20. :: pif: parent fingerprint (4 bytes)
  21. => |%
  22. +$ base [prv=@ pub=a-pt:curve cad=@ dep=@ud ind=@ud pif=@]
  23. --
  24. |_ base
  25. +$ base ^base
  26. ::
  27. +$ keyc [key=@ cai=@] :: prv/pub key + chain code
  28. ::
  29. :: elliptic curve operations and values
  30. ::
  31. ++ point ch-scal:affine:curve
  32. ::
  33. ++ ser-p ser-a-pt
  34. ::
  35. ++ n g-order:curve
  36. ::
  37. ++ domain-separator [14 'dees niahckcoN']
  38. ::
  39. ::
  40. :: rendering
  41. ::
  42. ++ private-key ?.(=(0 prv) prv ~|(%know-no-private-key !!))
  43. ++ public-key (ser-p pub)
  44. ++ chain-code cad
  45. ::
  46. ++ identity (hash160 public-key)
  47. ++ fingerprint (cut 3 [16 4] identity)
  48. ::
  49. ++ hash160
  50. |= d=@
  51. (ripemd-160:ripemd:crypto 32 (sha-256:sha d))
  52. ::
  53. :: core initialization
  54. ::
  55. ++ from-seed
  56. |= byts
  57. ^+ +>
  58. =+ der=(hmac-sha512l domain-separator [wid dat])
  59. =/ [left=@ right=@]
  60. [(cut 3 [32 32] der) (cut 3 [0 32] der)]
  61. ::
  62. :: In the case where the left is greater than or equal to the curve order,
  63. :: We have an invalid key and will use the right digest to rehash until we
  64. :: obtain a valid key. This prevents the distribution from being biased.
  65. |-
  66. ?: (lth left n)
  67. +>.^$(prv left, pub (point left a-gen:curve), cad right)
  68. =/ der (hmac-sha512l domain-separator 64^der)
  69. %= $
  70. der der
  71. left (cut 3 [32 32] der)
  72. right (cut 3 [0 32] der)
  73. ==
  74. ::
  75. ++ from-private
  76. |= keyc
  77. +>(prv key, pub (point key a-gen:curve), cad cai)
  78. ::
  79. ++ from-public
  80. |= keyc
  81. +>(pub (de-a-pt key), cad cai)
  82. ::
  83. :: derivation arms: Only used for testing.
  84. ::
  85. :: +derive-path
  86. ::
  87. :: Given a bip32-style path, i.e "m/0'/25", derive the key associated
  88. :: with that path.
  89. ::
  90. ++ derive-path
  91. |= t=tape
  92. %- derive-sequence
  93. (scan t derivation-path)
  94. ::
  95. :: +derivation-path
  96. ::
  97. :: Parses the bip32-style derivation path and return a list of indices
  98. ::
  99. ++ derivation-path
  100. ;~ pfix
  101. ;~(pose (jest 'm/') (easy ~))
  102. %+ most fas
  103. ;~ pose
  104. %+ cook
  105. |=(i=@ (add i (bex 31)))
  106. ;~(sfix dem soq)
  107. ::
  108. dem
  109. == ==
  110. ::
  111. :: +derive-sequence
  112. ::
  113. :: Derives a key from a list of indices associated with a bip32-style path.
  114. ::
  115. ++ derive-sequence
  116. |= j=(list @u)
  117. ?~ j +>
  118. =. +> (derive i.j)
  119. $(j t.j)
  120. ::
  121. :: +derive
  122. ::
  123. :: Checks if prv has been set to 0, denoting a wallet which only
  124. :: contains public keys. If prv=0, call derive-public otherwise
  125. :: call derive-private.
  126. ::
  127. ++ derive
  128. ?: =(0 prv)
  129. derive-public
  130. derive-private
  131. ::
  132. :: +derive-private
  133. ::
  134. :: derives the i-th child key from `prv`
  135. ::
  136. ++ derive-private
  137. |= i=@u
  138. ^+ +>
  139. :: we must have a private key to derive the next one
  140. ?: =(0 prv)
  141. ~| %know-no-private-key
  142. !!
  143. :: derive child at i
  144. =/ [left=@ right=@]
  145. =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
  146. %+ hmac-sha512l [32 cad]
  147. ?: (gte i (bex 31))
  148. :: hardened child
  149. [37 (can 3 ~[4^i 32^prv 1^0])]
  150. :: normal child
  151. [101 (can 3 ~[4^i 97^(ser-p (point prv a-gen:curve))])]
  152. =+ key=(mod (add left prv) n)
  153. ::
  154. :: In the case where `left` is greater than or equal to the curve order,
  155. :: or the key is the identity point, we have an invalid key and will
  156. :: rehash `0x1 || right || i` to obtain a valid key. This prevents the
  157. :: distribution from being biased.
  158. |-
  159. ?: &(!=(0 key) (lth left n))
  160. %_ +>.^$
  161. prv key
  162. pub (point key a-gen:curve)
  163. cad right
  164. dep +(dep)
  165. ind i
  166. pif fingerprint
  167. ==
  168. =/ [left=@ right=@]
  169. =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
  170. %+ hmac-sha512l [32 cad]
  171. [37 (can 3 ~[4^i 32^right 1^0x1])]
  172. %= $
  173. left left
  174. right right
  175. key (mod (add left prv) n)
  176. ==
  177. ::
  178. :: +derive-public
  179. ::
  180. :: derives the i-th child key from `pub`
  181. ++ derive-public
  182. |= i=@u
  183. ^+ +>
  184. :: public keys can't be hardened
  185. ?: (gte i (bex 31))
  186. ~| %cant-derive-hardened-public-key
  187. !!
  188. :: derive child at i
  189. =/ [left=@ right=@]
  190. =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
  191. %+ hmac-sha512l [32 cad]
  192. 101^(can 3 ~[4^i 97^(ser-p pub)])
  193. =+ key=(ch-add:affine:curve (point left a-gen:curve) pub)
  194. ::
  195. :: In the case where `left` is greater than or equal to the curve order,
  196. :: or the key is the identity point, we have an invalid key and will
  197. :: rehash `0x1 || right || i` to obtain a valid key. This prevents the
  198. :: distribution from being biased.
  199. |-
  200. ?: &((lth left n) !=(a-id:curve key))
  201. %_ +>.^$
  202. pub key
  203. cad right
  204. dep +(dep)
  205. ind i
  206. pif fingerprint
  207. ==
  208. =/ [left=@ right=@]
  209. =- [(cut 3 [32 32] -) (cut 3 [0 32] -)]
  210. %+ hmac-sha512l [32 cad]
  211. [37 (can 3 ~[4^i 32^right 1^0x1])]
  212. %= $
  213. left left
  214. right right
  215. key (ch-add:affine:curve (point left a-gen:curve) pub)
  216. ==
  217. --