@spinajs/authn-keys 0.0.0-stage → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/README.md +165 -2
  2. package/lib/cjs/bootstrap.d.ts +6 -0
  3. package/lib/cjs/bootstrap.d.ts.map +1 -0
  4. package/lib/cjs/bootstrap.js +23 -0
  5. package/lib/cjs/bootstrap.js.map +1 -0
  6. package/lib/cjs/challenge/challenge.d.ts +27 -0
  7. package/lib/cjs/challenge/challenge.d.ts.map +1 -0
  8. package/lib/cjs/challenge/challenge.js +56 -0
  9. package/lib/cjs/challenge/challenge.js.map +1 -0
  10. package/lib/cjs/challenge/index.d.ts +2 -0
  11. package/lib/cjs/challenge/index.d.ts.map +1 -0
  12. package/lib/cjs/challenge/index.js +18 -0
  13. package/lib/cjs/challenge/index.js.map +1 -0
  14. package/lib/cjs/cli/AddKey.d.ts +18 -0
  15. package/lib/cjs/cli/AddKey.d.ts.map +1 -0
  16. package/lib/cjs/cli/AddKey.js +65 -0
  17. package/lib/cjs/cli/AddKey.js.map +1 -0
  18. package/lib/cjs/cli/ListKeys.d.ts +11 -0
  19. package/lib/cjs/cli/ListKeys.d.ts.map +1 -0
  20. package/lib/cjs/cli/ListKeys.js +48 -0
  21. package/lib/cjs/cli/ListKeys.js.map +1 -0
  22. package/lib/cjs/cli/RevokeKey.d.ts +9 -0
  23. package/lib/cjs/cli/RevokeKey.d.ts.map +1 -0
  24. package/lib/cjs/cli/RevokeKey.js +42 -0
  25. package/lib/cjs/cli/RevokeKey.js.map +1 -0
  26. package/lib/cjs/cli/common.d.ts +9 -0
  27. package/lib/cjs/cli/common.d.ts.map +1 -0
  28. package/lib/cjs/cli/common.js +35 -0
  29. package/lib/cjs/cli/common.js.map +1 -0
  30. package/lib/cjs/cli/index.d.ts +5 -0
  31. package/lib/cjs/cli/index.d.ts.map +1 -0
  32. package/lib/cjs/cli/index.js +21 -0
  33. package/lib/cjs/cli/index.js.map +1 -0
  34. package/lib/cjs/config/authn-keys.d.ts +9 -0
  35. package/lib/cjs/config/authn-keys.d.ts.map +1 -0
  36. package/lib/cjs/config/authn-keys.js +23 -0
  37. package/lib/cjs/config/authn-keys.js.map +1 -0
  38. package/lib/cjs/httpsig/base.d.ts +8 -0
  39. package/lib/cjs/httpsig/base.d.ts.map +1 -0
  40. package/lib/cjs/httpsig/base.js +73 -0
  41. package/lib/cjs/httpsig/base.js.map +1 -0
  42. package/lib/cjs/httpsig/fields.d.ts +17 -0
  43. package/lib/cjs/httpsig/fields.d.ts.map +1 -0
  44. package/lib/cjs/httpsig/fields.js +137 -0
  45. package/lib/cjs/httpsig/fields.js.map +1 -0
  46. package/lib/cjs/httpsig/index.d.ts +3 -0
  47. package/lib/cjs/httpsig/index.d.ts.map +1 -0
  48. package/lib/cjs/httpsig/index.js +19 -0
  49. package/lib/cjs/httpsig/index.js.map +1 -0
  50. package/lib/cjs/index.d.ts +13 -0
  51. package/lib/cjs/index.d.ts.map +1 -0
  52. package/lib/cjs/index.js +29 -0
  53. package/lib/cjs/index.js.map +1 -0
  54. package/lib/cjs/jwk/base64url.d.ts +7 -0
  55. package/lib/cjs/jwk/base64url.d.ts.map +1 -0
  56. package/lib/cjs/jwk/base64url.js +22 -0
  57. package/lib/cjs/jwk/base64url.js.map +1 -0
  58. package/lib/cjs/jwk/ed25519.d.ts +9 -0
  59. package/lib/cjs/jwk/ed25519.d.ts.map +1 -0
  60. package/lib/cjs/jwk/ed25519.js +47 -0
  61. package/lib/cjs/jwk/ed25519.js.map +1 -0
  62. package/lib/cjs/jwk/index.d.ts +5 -0
  63. package/lib/cjs/jwk/index.d.ts.map +1 -0
  64. package/lib/cjs/jwk/index.js +21 -0
  65. package/lib/cjs/jwk/index.js.map +1 -0
  66. package/lib/cjs/jwk/keys.d.ts +18 -0
  67. package/lib/cjs/jwk/keys.d.ts.map +1 -0
  68. package/lib/cjs/jwk/keys.js +102 -0
  69. package/lib/cjs/jwk/keys.js.map +1 -0
  70. package/lib/cjs/jwk/signature.d.ts +11 -0
  71. package/lib/cjs/jwk/signature.d.ts.map +1 -0
  72. package/lib/cjs/jwk/signature.js +45 -0
  73. package/lib/cjs/jwk/signature.js.map +1 -0
  74. package/lib/cjs/jws/index.d.ts +4 -0
  75. package/lib/cjs/jws/index.d.ts.map +1 -0
  76. package/lib/cjs/jws/index.js +20 -0
  77. package/lib/cjs/jws/index.js.map +1 -0
  78. package/lib/cjs/jws/json.d.ts +11 -0
  79. package/lib/cjs/jws/json.d.ts.map +1 -0
  80. package/lib/cjs/jws/json.js +76 -0
  81. package/lib/cjs/jws/json.js.map +1 -0
  82. package/lib/cjs/jws/signer.d.ts +25 -0
  83. package/lib/cjs/jws/signer.d.ts.map +1 -0
  84. package/lib/cjs/jws/signer.js +83 -0
  85. package/lib/cjs/jws/signer.js.map +1 -0
  86. package/lib/cjs/jws/verifier.d.ts +10 -0
  87. package/lib/cjs/jws/verifier.d.ts.map +1 -0
  88. package/lib/cjs/jws/verifier.js +86 -0
  89. package/lib/cjs/jws/verifier.js.map +1 -0
  90. package/lib/cjs/migrations/AuthnKeys_2026_10_02_00_00_00.d.ts +7 -0
  91. package/lib/cjs/migrations/AuthnKeys_2026_10_02_00_00_00.d.ts.map +1 -0
  92. package/lib/cjs/migrations/AuthnKeys_2026_10_02_00_00_00.js +40 -0
  93. package/lib/cjs/migrations/AuthnKeys_2026_10_02_00_00_00.js.map +1 -0
  94. package/lib/cjs/migrations/index.d.ts +2 -0
  95. package/lib/cjs/migrations/index.d.ts.map +1 -0
  96. package/lib/cjs/migrations/index.js +18 -0
  97. package/lib/cjs/migrations/index.js.map +1 -0
  98. package/lib/cjs/models/AuthnKey.d.ts +22 -0
  99. package/lib/cjs/models/AuthnKey.d.ts.map +1 -0
  100. package/lib/cjs/models/AuthnKey.js +43 -0
  101. package/lib/cjs/models/AuthnKey.js.map +1 -0
  102. package/lib/cjs/models/AuthnNonce.d.ts +8 -0
  103. package/lib/cjs/models/AuthnNonce.d.ts.map +1 -0
  104. package/lib/cjs/models/AuthnNonce.js +31 -0
  105. package/lib/cjs/models/AuthnNonce.js.map +1 -0
  106. package/lib/cjs/models/index.d.ts +3 -0
  107. package/lib/cjs/models/index.d.ts.map +1 -0
  108. package/lib/cjs/models/index.js +19 -0
  109. package/lib/cjs/models/index.js.map +1 -0
  110. package/lib/cjs/nonce/index.d.ts +2 -0
  111. package/lib/cjs/nonce/index.d.ts.map +1 -0
  112. package/lib/cjs/nonce/index.js +18 -0
  113. package/lib/cjs/nonce/index.js.map +1 -0
  114. package/lib/cjs/nonce/store.d.ts +22 -0
  115. package/lib/cjs/nonce/store.d.ts.map +1 -0
  116. package/lib/cjs/nonce/store.js +98 -0
  117. package/lib/cjs/nonce/store.js.map +1 -0
  118. package/lib/cjs/options/index.d.ts +2 -0
  119. package/lib/cjs/options/index.d.ts.map +1 -0
  120. package/lib/cjs/options/index.js +18 -0
  121. package/lib/cjs/options/index.js.map +1 -0
  122. package/lib/cjs/options/options.d.ts +47 -0
  123. package/lib/cjs/options/options.d.ts.map +1 -0
  124. package/lib/cjs/options/options.js +42 -0
  125. package/lib/cjs/options/options.js.map +1 -0
  126. package/lib/cjs/package.json +1 -0
  127. package/lib/cjs/register-schema.d.ts +2 -0
  128. package/lib/cjs/register-schema.d.ts.map +1 -0
  129. package/lib/cjs/register-schema.js +9 -0
  130. package/lib/cjs/register-schema.js.map +1 -0
  131. package/lib/cjs/registry/index.d.ts +4 -0
  132. package/lib/cjs/registry/index.d.ts.map +1 -0
  133. package/lib/cjs/registry/index.js +20 -0
  134. package/lib/cjs/registry/index.js.map +1 -0
  135. package/lib/cjs/registry/orm-store.d.ts +15 -0
  136. package/lib/cjs/registry/orm-store.d.ts.map +1 -0
  137. package/lib/cjs/registry/orm-store.js +109 -0
  138. package/lib/cjs/registry/orm-store.js.map +1 -0
  139. package/lib/cjs/registry/registry.d.ts +54 -0
  140. package/lib/cjs/registry/registry.d.ts.map +1 -0
  141. package/lib/cjs/registry/registry.js +244 -0
  142. package/lib/cjs/registry/registry.js.map +1 -0
  143. package/lib/cjs/registry/store.d.ts +25 -0
  144. package/lib/cjs/registry/store.d.ts.map +1 -0
  145. package/lib/cjs/registry/store.js +66 -0
  146. package/lib/cjs/registry/store.js.map +1 -0
  147. package/lib/cjs/schema.d.ts +88 -0
  148. package/lib/cjs/schema.d.ts.map +1 -0
  149. package/lib/cjs/schema.js +41 -0
  150. package/lib/cjs/schema.js.map +1 -0
  151. package/lib/cjs/strategies/assertion.d.ts +29 -0
  152. package/lib/cjs/strategies/assertion.d.ts.map +1 -0
  153. package/lib/cjs/strategies/assertion.js +118 -0
  154. package/lib/cjs/strategies/assertion.js.map +1 -0
  155. package/lib/cjs/strategies/challenge.d.ts +25 -0
  156. package/lib/cjs/strategies/challenge.d.ts.map +1 -0
  157. package/lib/cjs/strategies/challenge.js +81 -0
  158. package/lib/cjs/strategies/challenge.js.map +1 -0
  159. package/lib/cjs/strategies/httpsig.d.ts +34 -0
  160. package/lib/cjs/strategies/httpsig.d.ts.map +1 -0
  161. package/lib/cjs/strategies/httpsig.js +127 -0
  162. package/lib/cjs/strategies/httpsig.js.map +1 -0
  163. package/lib/cjs/strategies/index.d.ts +5 -0
  164. package/lib/cjs/strategies/index.d.ts.map +1 -0
  165. package/lib/cjs/strategies/index.js +21 -0
  166. package/lib/cjs/strategies/index.js.map +1 -0
  167. package/lib/cjs/strategies/keys.d.ts +43 -0
  168. package/lib/cjs/strategies/keys.d.ts.map +1 -0
  169. package/lib/cjs/strategies/keys.js +93 -0
  170. package/lib/cjs/strategies/keys.js.map +1 -0
  171. package/lib/mjs/bootstrap.d.ts +6 -0
  172. package/lib/mjs/bootstrap.d.ts.map +1 -0
  173. package/lib/mjs/bootstrap.js +20 -0
  174. package/lib/mjs/bootstrap.js.map +1 -0
  175. package/lib/mjs/challenge/challenge.d.ts +27 -0
  176. package/lib/mjs/challenge/challenge.d.ts.map +1 -0
  177. package/lib/mjs/challenge/challenge.js +45 -0
  178. package/lib/mjs/challenge/challenge.js.map +1 -0
  179. package/lib/mjs/challenge/index.d.ts +2 -0
  180. package/lib/mjs/challenge/index.d.ts.map +1 -0
  181. package/lib/mjs/challenge/index.js +2 -0
  182. package/lib/mjs/challenge/index.js.map +1 -0
  183. package/lib/mjs/cli/AddKey.d.ts +18 -0
  184. package/lib/mjs/cli/AddKey.d.ts.map +1 -0
  185. package/lib/mjs/cli/AddKey.js +62 -0
  186. package/lib/mjs/cli/AddKey.js.map +1 -0
  187. package/lib/mjs/cli/ListKeys.d.ts +11 -0
  188. package/lib/mjs/cli/ListKeys.d.ts.map +1 -0
  189. package/lib/mjs/cli/ListKeys.js +44 -0
  190. package/lib/mjs/cli/ListKeys.js.map +1 -0
  191. package/lib/mjs/cli/RevokeKey.d.ts +9 -0
  192. package/lib/mjs/cli/RevokeKey.d.ts.map +1 -0
  193. package/lib/mjs/cli/RevokeKey.js +39 -0
  194. package/lib/mjs/cli/RevokeKey.js.map +1 -0
  195. package/lib/mjs/cli/common.d.ts +9 -0
  196. package/lib/mjs/cli/common.d.ts.map +1 -0
  197. package/lib/mjs/cli/common.js +30 -0
  198. package/lib/mjs/cli/common.js.map +1 -0
  199. package/lib/mjs/cli/index.d.ts +5 -0
  200. package/lib/mjs/cli/index.d.ts.map +1 -0
  201. package/lib/mjs/cli/index.js +5 -0
  202. package/lib/mjs/cli/index.js.map +1 -0
  203. package/lib/mjs/config/authn-keys.d.ts +9 -0
  204. package/lib/mjs/config/authn-keys.d.ts.map +1 -0
  205. package/lib/mjs/config/authn-keys.js +21 -0
  206. package/lib/mjs/config/authn-keys.js.map +1 -0
  207. package/lib/mjs/httpsig/base.d.ts +8 -0
  208. package/lib/mjs/httpsig/base.d.ts.map +1 -0
  209. package/lib/mjs/httpsig/base.js +67 -0
  210. package/lib/mjs/httpsig/base.js.map +1 -0
  211. package/lib/mjs/httpsig/fields.d.ts +17 -0
  212. package/lib/mjs/httpsig/fields.d.ts.map +1 -0
  213. package/lib/mjs/httpsig/fields.js +133 -0
  214. package/lib/mjs/httpsig/fields.js.map +1 -0
  215. package/lib/mjs/httpsig/index.d.ts +3 -0
  216. package/lib/mjs/httpsig/index.d.ts.map +1 -0
  217. package/lib/mjs/httpsig/index.js +3 -0
  218. package/lib/mjs/httpsig/index.js.map +1 -0
  219. package/lib/mjs/index.d.ts +13 -0
  220. package/lib/mjs/index.d.ts.map +1 -0
  221. package/lib/mjs/index.js +13 -0
  222. package/lib/mjs/index.js.map +1 -0
  223. package/lib/mjs/jwk/base64url.d.ts +7 -0
  224. package/lib/mjs/jwk/base64url.d.ts.map +1 -0
  225. package/lib/mjs/jwk/base64url.js +18 -0
  226. package/lib/mjs/jwk/base64url.js.map +1 -0
  227. package/lib/mjs/jwk/ed25519.d.ts +9 -0
  228. package/lib/mjs/jwk/ed25519.d.ts.map +1 -0
  229. package/lib/mjs/jwk/ed25519.js +42 -0
  230. package/lib/mjs/jwk/ed25519.js.map +1 -0
  231. package/lib/mjs/jwk/index.d.ts +5 -0
  232. package/lib/mjs/jwk/index.d.ts.map +1 -0
  233. package/lib/mjs/jwk/index.js +5 -0
  234. package/lib/mjs/jwk/index.js.map +1 -0
  235. package/lib/mjs/jwk/keys.d.ts +18 -0
  236. package/lib/mjs/jwk/keys.d.ts.map +1 -0
  237. package/lib/mjs/jwk/keys.js +95 -0
  238. package/lib/mjs/jwk/keys.js.map +1 -0
  239. package/lib/mjs/jwk/signature.d.ts +11 -0
  240. package/lib/mjs/jwk/signature.d.ts.map +1 -0
  241. package/lib/mjs/jwk/signature.js +39 -0
  242. package/lib/mjs/jwk/signature.js.map +1 -0
  243. package/lib/mjs/jws/index.d.ts +4 -0
  244. package/lib/mjs/jws/index.d.ts.map +1 -0
  245. package/lib/mjs/jws/index.js +4 -0
  246. package/lib/mjs/jws/index.js.map +1 -0
  247. package/lib/mjs/jws/json.d.ts +11 -0
  248. package/lib/mjs/jws/json.d.ts.map +1 -0
  249. package/lib/mjs/jws/json.js +72 -0
  250. package/lib/mjs/jws/json.js.map +1 -0
  251. package/lib/mjs/jws/signer.d.ts +25 -0
  252. package/lib/mjs/jws/signer.d.ts.map +1 -0
  253. package/lib/mjs/jws/signer.js +79 -0
  254. package/lib/mjs/jws/signer.js.map +1 -0
  255. package/lib/mjs/jws/verifier.d.ts +10 -0
  256. package/lib/mjs/jws/verifier.d.ts.map +1 -0
  257. package/lib/mjs/jws/verifier.js +83 -0
  258. package/lib/mjs/jws/verifier.js.map +1 -0
  259. package/lib/mjs/migrations/AuthnKeys_2026_10_02_00_00_00.d.ts +7 -0
  260. package/lib/mjs/migrations/AuthnKeys_2026_10_02_00_00_00.d.ts.map +1 -0
  261. package/lib/mjs/migrations/AuthnKeys_2026_10_02_00_00_00.js +37 -0
  262. package/lib/mjs/migrations/AuthnKeys_2026_10_02_00_00_00.js.map +1 -0
  263. package/lib/mjs/migrations/index.d.ts +2 -0
  264. package/lib/mjs/migrations/index.d.ts.map +1 -0
  265. package/lib/mjs/migrations/index.js +2 -0
  266. package/lib/mjs/migrations/index.js.map +1 -0
  267. package/lib/mjs/models/AuthnKey.d.ts +22 -0
  268. package/lib/mjs/models/AuthnKey.d.ts.map +1 -0
  269. package/lib/mjs/models/AuthnKey.js +40 -0
  270. package/lib/mjs/models/AuthnKey.js.map +1 -0
  271. package/lib/mjs/models/AuthnNonce.d.ts +8 -0
  272. package/lib/mjs/models/AuthnNonce.d.ts.map +1 -0
  273. package/lib/mjs/models/AuthnNonce.js +28 -0
  274. package/lib/mjs/models/AuthnNonce.js.map +1 -0
  275. package/lib/mjs/models/index.d.ts +3 -0
  276. package/lib/mjs/models/index.d.ts.map +1 -0
  277. package/lib/mjs/models/index.js +3 -0
  278. package/lib/mjs/models/index.js.map +1 -0
  279. package/lib/mjs/nonce/index.d.ts +2 -0
  280. package/lib/mjs/nonce/index.d.ts.map +1 -0
  281. package/lib/mjs/nonce/index.js +2 -0
  282. package/lib/mjs/nonce/index.js.map +1 -0
  283. package/lib/mjs/nonce/store.d.ts +22 -0
  284. package/lib/mjs/nonce/store.d.ts.map +1 -0
  285. package/lib/mjs/nonce/store.js +92 -0
  286. package/lib/mjs/nonce/store.js.map +1 -0
  287. package/lib/mjs/options/index.d.ts +2 -0
  288. package/lib/mjs/options/index.d.ts.map +1 -0
  289. package/lib/mjs/options/index.js +2 -0
  290. package/lib/mjs/options/index.js.map +1 -0
  291. package/lib/mjs/options/options.d.ts +47 -0
  292. package/lib/mjs/options/options.d.ts.map +1 -0
  293. package/lib/mjs/options/options.js +39 -0
  294. package/lib/mjs/options/options.js.map +1 -0
  295. package/lib/mjs/package.json +1 -0
  296. package/lib/mjs/register-schema.d.ts +2 -0
  297. package/lib/mjs/register-schema.d.ts.map +1 -0
  298. package/lib/mjs/register-schema.js +7 -0
  299. package/lib/mjs/register-schema.js.map +1 -0
  300. package/lib/mjs/registry/index.d.ts +4 -0
  301. package/lib/mjs/registry/index.d.ts.map +1 -0
  302. package/lib/mjs/registry/index.js +4 -0
  303. package/lib/mjs/registry/index.js.map +1 -0
  304. package/lib/mjs/registry/orm-store.d.ts +15 -0
  305. package/lib/mjs/registry/orm-store.d.ts.map +1 -0
  306. package/lib/mjs/registry/orm-store.js +106 -0
  307. package/lib/mjs/registry/orm-store.js.map +1 -0
  308. package/lib/mjs/registry/registry.d.ts +54 -0
  309. package/lib/mjs/registry/registry.d.ts.map +1 -0
  310. package/lib/mjs/registry/registry.js +239 -0
  311. package/lib/mjs/registry/registry.js.map +1 -0
  312. package/lib/mjs/registry/store.d.ts +25 -0
  313. package/lib/mjs/registry/store.d.ts.map +1 -0
  314. package/lib/mjs/registry/store.js +57 -0
  315. package/lib/mjs/registry/store.js.map +1 -0
  316. package/lib/mjs/schema.d.ts +88 -0
  317. package/lib/mjs/schema.d.ts.map +1 -0
  318. package/lib/mjs/schema.js +38 -0
  319. package/lib/mjs/schema.js.map +1 -0
  320. package/lib/mjs/strategies/assertion.d.ts +29 -0
  321. package/lib/mjs/strategies/assertion.d.ts.map +1 -0
  322. package/lib/mjs/strategies/assertion.js +115 -0
  323. package/lib/mjs/strategies/assertion.js.map +1 -0
  324. package/lib/mjs/strategies/challenge.d.ts +25 -0
  325. package/lib/mjs/strategies/challenge.d.ts.map +1 -0
  326. package/lib/mjs/strategies/challenge.js +78 -0
  327. package/lib/mjs/strategies/challenge.js.map +1 -0
  328. package/lib/mjs/strategies/httpsig.d.ts +34 -0
  329. package/lib/mjs/strategies/httpsig.d.ts.map +1 -0
  330. package/lib/mjs/strategies/httpsig.js +124 -0
  331. package/lib/mjs/strategies/httpsig.js.map +1 -0
  332. package/lib/mjs/strategies/index.d.ts +5 -0
  333. package/lib/mjs/strategies/index.d.ts.map +1 -0
  334. package/lib/mjs/strategies/index.js +5 -0
  335. package/lib/mjs/strategies/index.js.map +1 -0
  336. package/lib/mjs/strategies/keys.d.ts +43 -0
  337. package/lib/mjs/strategies/keys.d.ts.map +1 -0
  338. package/lib/mjs/strategies/keys.js +85 -0
  339. package/lib/mjs/strategies/keys.js.map +1 -0
  340. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  341. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  342. package/package.json +79 -4
@@ -0,0 +1,67 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { parseByteSequenceDictionary } from './fields.js';
3
+ const DERIVED = ['@method', '@target-uri', '@authority', '@path', '@query'];
4
+ const HEADER_NAME = /^[a-z0-9!#$%&'*+\-.^_`|~]+$/;
5
+ // A signature never covers the headers that carry it.
6
+ const NOT_COVERABLE = ['signature', 'signature-input'];
7
+ export const lowerCaseHeaders = (headers) => Object.fromEntries(Object.entries(headers ?? {}).map(([k, v]) => [k.toLowerCase(), v]));
8
+ function componentValue(req, headers, name) {
9
+ if (name.startsWith('@')) {
10
+ let url;
11
+ try {
12
+ url = new URL(req.targetUri);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ switch (name) {
18
+ case '@method':
19
+ return req.method.toUpperCase();
20
+ case '@target-uri':
21
+ return req.targetUri;
22
+ case '@authority':
23
+ return url.host.toLowerCase();
24
+ case '@path':
25
+ return url.pathname || '/';
26
+ case '@query':
27
+ return url.search || '?';
28
+ default:
29
+ return null;
30
+ }
31
+ }
32
+ const v = headers[name];
33
+ return typeof v === 'string' ? v.trim() : null;
34
+ }
35
+ /** RFC 9421 §2.5 for the covered components; null when one may not be covered or has no value. */
36
+ export function signatureBase(req, input) {
37
+ const headers = lowerCaseHeaders(req.headers);
38
+ const lines = [];
39
+ for (const name of input.components) {
40
+ if (!(DERIVED.includes(name) || (HEADER_NAME.test(name) && !NOT_COVERABLE.includes(name)))) {
41
+ return null;
42
+ }
43
+ const value = componentValue(req, headers, name);
44
+ if (value === null || /[\r\n]/.test(value)) {
45
+ return null;
46
+ }
47
+ lines.push(`"${name}": ${value}`);
48
+ }
49
+ lines.push(`"@signature-params": ${input.value}`);
50
+ return lines.join('\n');
51
+ }
52
+ const DIGESTS = { 'sha-256': 'sha256', 'sha-512': 'sha512' };
53
+ /** RFC 9530 Content-Digest: every member is sha-256 or sha-512 and matches the body. */
54
+ export function digestMatches(header, body) {
55
+ const members = parseByteSequenceDictionary(header);
56
+ if (!members) {
57
+ return false;
58
+ }
59
+ for (const [alg, digest] of members) {
60
+ const hash = DIGESTS[alg];
61
+ if (!hash || !createHash(hash).update(body).digest().equals(digest)) {
62
+ return false;
63
+ }
64
+ }
65
+ return true;
66
+ }
67
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/httpsig/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export type ParamValue = number | string;
2
+ export interface SignatureInput {
3
+ readonly label: string;
4
+ readonly components: readonly string[];
5
+ readonly params: ReadonlyMap<string, ParamValue>;
6
+ /** The member value as sent; it is the `@signature-params` line of the signature base. */
7
+ readonly value: string;
8
+ }
9
+ /**
10
+ * `Signature-Input` with exactly one member: `<label>=("<component>" …);<name>=<integer or string>…`. Component
11
+ * names carry no parameters; parameter values are integers or strings. Null for anything else, a second member,
12
+ * a duplicate parameter or component, or text that is not in canonical form.
13
+ */
14
+ export declare function parseSignatureInput(header: unknown): SignatureInput | null;
15
+ /** A dictionary whose members are all byte sequences (`Signature`, `Content-Digest`); null when not exactly that. */
16
+ export declare function parseByteSequenceDictionary(header: unknown): Map<string, Buffer> | null;
17
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../../src/httpsig/fields.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjD,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAoCD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CA0D1E;AAWD,qHAAqH;AACrH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAkBvF"}
@@ -0,0 +1,133 @@
1
+ // The RFC 8941 structured-field subset RFC 9421 signatures and RFC 9530 digests need, parsed strictly: one canonical
2
+ // text form per value, so the signature base can use the Signature-Input text exactly as sent.
3
+ const KEY = /^[a-z*][a-z0-9_\-.*]*$/;
4
+ const MAX_KEY = 64;
5
+ const INTEGER = /^-?[0-9]{1,15}$/;
6
+ const BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
7
+ /** An sf-string at `s[i]` (which must be '"'): its value and the index after it, or null. */
8
+ function readString(s, i) {
9
+ let value = '';
10
+ for (let j = i + 1; j < s.length; j += 1) {
11
+ const c = s[j];
12
+ if (c === '\\') {
13
+ const n = s[j + 1];
14
+ if (n !== '"' && n !== '\\') {
15
+ return null;
16
+ }
17
+ value += n;
18
+ j += 1;
19
+ }
20
+ else if (c === '"') {
21
+ return { value, end: j + 1 };
22
+ }
23
+ else {
24
+ const code = c.charCodeAt(0);
25
+ if (code < 0x20 || code > 0x7e) {
26
+ return null;
27
+ }
28
+ value += c;
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ const serializeString = (v) => `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
34
+ /** A dictionary key ending at the first '=' from `i`, or null. */
35
+ function readKey(s, i) {
36
+ const eq = s.indexOf('=', i);
37
+ const key = eq < 0 ? '' : s.slice(i, eq);
38
+ return KEY.test(key) && key.length <= MAX_KEY ? { key, end: eq + 1 } : null;
39
+ }
40
+ /**
41
+ * `Signature-Input` with exactly one member: `<label>=("<component>" …);<name>=<integer or string>…`. Component
42
+ * names carry no parameters; parameter values are integers or strings. Null for anything else, a second member,
43
+ * a duplicate parameter or component, or text that is not in canonical form.
44
+ */
45
+ export function parseSignatureInput(header) {
46
+ if (typeof header !== 'string') {
47
+ return null;
48
+ }
49
+ const s = header.trim();
50
+ const key = readKey(s, 0);
51
+ if (!key || s[key.end] !== '(') {
52
+ return null;
53
+ }
54
+ const components = [];
55
+ let i = key.end + 1;
56
+ while (s[i] !== ')') {
57
+ if (components.length > 0) {
58
+ if (s[i] !== ' ') {
59
+ return null;
60
+ }
61
+ i += 1;
62
+ }
63
+ if (s[i] !== '"') {
64
+ return null;
65
+ }
66
+ const str = readString(s, i);
67
+ if (!str || str.value.length === 0 || components.includes(str.value)) {
68
+ return null;
69
+ }
70
+ components.push(str.value);
71
+ i = str.end;
72
+ }
73
+ i += 1;
74
+ const params = new Map();
75
+ while (i < s.length) {
76
+ if (s[i] !== ';') {
77
+ return null;
78
+ }
79
+ const name = readKey(s, i + 1);
80
+ if (!name || params.has(name.key)) {
81
+ return null;
82
+ }
83
+ i = name.end;
84
+ if (s[i] === '"') {
85
+ const str = readString(s, i);
86
+ if (!str) {
87
+ return null;
88
+ }
89
+ params.set(name.key, str.value);
90
+ i = str.end;
91
+ }
92
+ else {
93
+ const m = /^-?[0-9]+/.exec(s.slice(i));
94
+ if (!m || !INTEGER.test(m[0]) || (m[0].length > 1 && /^-?0/.test(m[0]))) {
95
+ return null;
96
+ }
97
+ params.set(name.key, Number(m[0]));
98
+ i += m[0].length;
99
+ }
100
+ }
101
+ const value = s.slice(key.end);
102
+ const canonical = `(${components.map(serializeString).join(' ')})${[...params].map(([k, v]) => `;${k}=${typeof v === 'number' ? v : serializeString(v)}`).join('')}`;
103
+ return canonical === value ? { label: key.key, components, params, value } : null;
104
+ }
105
+ /** RFC 8941 byte sequence in standard base64, canonical (padded, no stray bits). */
106
+ function decodeByteSequence(text) {
107
+ if (!BASE64.test(text) || text.length % 4 !== 0) {
108
+ return null;
109
+ }
110
+ const bytes = Buffer.from(text, 'base64');
111
+ return bytes.toString('base64') === text ? bytes : null;
112
+ }
113
+ /** A dictionary whose members are all byte sequences (`Signature`, `Content-Digest`); null when not exactly that. */
114
+ export function parseByteSequenceDictionary(header) {
115
+ if (typeof header !== 'string') {
116
+ return null;
117
+ }
118
+ const out = new Map();
119
+ for (const member of header.split(',')) {
120
+ const m = member.trim();
121
+ const key = readKey(m, 0);
122
+ if (!key || out.has(key.key) || m[key.end] !== ':' || !m.endsWith(':') || m.length < key.end + 2) {
123
+ return null;
124
+ }
125
+ const bytes = decodeByteSequence(m.slice(key.end + 1, -1));
126
+ if (!bytes) {
127
+ return null;
128
+ }
129
+ out.set(key.key, bytes);
130
+ }
131
+ return out.size > 0 ? out : null;
132
+ }
133
+ //# sourceMappingURL=fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.js","sourceRoot":"","sources":["../../../src/httpsig/fields.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,+FAA+F;AAE/F,MAAM,GAAG,GAAG,wBAAwB,CAAC;AACrC,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAClC,MAAM,MAAM,GAAG,wBAAwB,CAAC;AAYxC,6FAA6F;AAC7F,SAAS,UAAU,CAAC,CAAS,EAAE,CAAS;IACtC,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACf,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACnB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,KAAK,IAAI,CAAC,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;gBAC/B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,eAAe,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAEpG,kEAAkE;AAClE,SAAS,OAAO,CAAC,CAAS,EAAE,CAAS;IACnC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzC,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IACpB,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACpB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACjB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,CAAC,IAAI,CAAC,CAAC;QACT,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;IACd,CAAC;IACD,CAAC,IAAI,CAAC,CAAC;IACP,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;QACb,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACnB,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACrK,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED,oFAAoF;AACpF,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED,qHAAqH;AACrH,MAAM,UAAU,2BAA2B,CAAC,MAAe;IACzD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './fields.js';
2
+ export * from './base.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/httpsig/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './fields.js';
2
+ export * from './base.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/httpsig/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,13 @@
1
+ export * from './jwk/index.js';
2
+ export * from './challenge/index.js';
3
+ export * from './options/index.js';
4
+ export * from './models/index.js';
5
+ export * from './migrations/index.js';
6
+ export * from './registry/index.js';
7
+ export * from './jws/index.js';
8
+ export * from './nonce/index.js';
9
+ export * from './strategies/index.js';
10
+ export * from './httpsig/index.js';
11
+ export * from './schema.js';
12
+ export * from './bootstrap.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,13 @@
1
+ export * from './jwk/index.js';
2
+ export * from './challenge/index.js';
3
+ export * from './options/index.js';
4
+ export * from './models/index.js';
5
+ export * from './migrations/index.js';
6
+ export * from './registry/index.js';
7
+ export * from './jws/index.js';
8
+ export * from './nonce/index.js';
9
+ export * from './strategies/index.js';
10
+ export * from './httpsig/index.js';
11
+ export * from './schema.js';
12
+ export * from './bootstrap.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Strict unpadded base64url: Node's decoder skips bad characters and stray bits, so the result is re-encoded and
3
+ * compared, and every value has exactly one text form (canvas C8 `decodeB64url`).
4
+ */
5
+ export declare function decodeB64url(text: unknown): Buffer | null;
6
+ export declare function encodeB64url(data: Uint8Array | string): string;
7
+ //# sourceMappingURL=base64url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../../src/jwk/base64url.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAE9D"}
@@ -0,0 +1,18 @@
1
+ import { _custom, _is_string, _reg_match, _try_check_arg } from '@spinajs/util';
2
+ const ALPHABET = /^[A-Za-z0-9_-]*$/;
3
+ /**
4
+ * Strict unpadded base64url: Node's decoder skips bad characters and stray bits, so the result is re-encoded and
5
+ * compared, and every value has exactly one text form (canvas C8 `decodeB64url`).
6
+ */
7
+ export function decodeB64url(text) {
8
+ const [ok, encoded] = _try_check_arg(_is_string(_reg_match(ALPHABET), _custom((s) => s.length % 4 !== 1)))(text, 'text');
9
+ if (!ok) {
10
+ return null;
11
+ }
12
+ const bytes = Buffer.from(encoded, 'base64url');
13
+ return bytes.toString('base64url') === encoded ? bytes : null;
14
+ }
15
+ export function encodeB64url(data) {
16
+ return (typeof data === 'string' ? Buffer.from(data, 'utf8') : Buffer.from(data)).toString('base64url');
17
+ }
18
+ //# sourceMappingURL=base64url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64url.js","sourceRoot":"","sources":["../../../src/jwk/base64url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEhF,MAAM,QAAQ,GAAG,kBAAkB,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjI,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAiB,EAAE,WAAW,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,OAAO,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1G,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * RFC 8032 §5.1.3 decoding: y < p, x² = (y² − 1) / (d y² + 1) has a root, and x = 0 has no sign bit. The root itself
3
+ * is not needed, so the sqrt(−1) correction reduces to accepting v x² = −u as well as v x² = u.
4
+ */
5
+ export declare function isCanonicalPoint(bytes: Uint8Array): boolean;
6
+ /** Canonical encodings of the 8 points of order 1, 2, 4 and 8 (canvas C8 `SMALL_ORDER`, checked complete there). */
7
+ export declare const SMALL_ORDER: readonly string[];
8
+ export declare function isSmallOrder(bytes: Uint8Array): boolean;
9
+ //# sourceMappingURL=ed25519.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../../../src/jwk/ed25519.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAiB3D;AAED,oHAAoH;AACpH,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAAojB,CAAC;AAE9lB,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,42 @@
1
+ // Ed25519 point checks that node:crypto skips: `createPublicKey` takes any 32 bytes, and `verify` (cofactorless)
2
+ // accepts forgeries under small-order keys. Ported from canvas C8 (`contracts/ts/plane-api/src/ed25519.ts`).
3
+ const P = 2n ** 255n - 19n;
4
+ const mod = (a) => ((a % P) + P) % P;
5
+ function pow(base, exp) {
6
+ let result = 1n;
7
+ for (let b = mod(base), e = exp; e > 0n; b = (b * b) % P, e >>= 1n) {
8
+ if (e & 1n) {
9
+ result = (result * b) % P;
10
+ }
11
+ }
12
+ return result;
13
+ }
14
+ const D = mod(-121665n * pow(121666n, P - 2n));
15
+ /**
16
+ * RFC 8032 §5.1.3 decoding: y < p, x² = (y² − 1) / (d y² + 1) has a root, and x = 0 has no sign bit. The root itself
17
+ * is not needed, so the sqrt(−1) correction reduces to accepting v x² = −u as well as v x² = u.
18
+ */
19
+ export function isCanonicalPoint(bytes) {
20
+ if (bytes.length !== 32) {
21
+ return false;
22
+ }
23
+ const n = BigInt(`0x${Buffer.from(bytes).reverse().toString('hex')}`);
24
+ const y = n & ((1n << 255n) - 1n);
25
+ if (y >= P) {
26
+ return false;
27
+ }
28
+ const u = mod(y * y - 1n);
29
+ const v = mod(D * y * y + 1n);
30
+ const x = mod(u * pow(v, 3n) * pow(u * pow(v, 7n), (P - 5n) / 8n));
31
+ const vxx = mod(v * x * x);
32
+ if (vxx !== u && vxx !== mod(-u)) {
33
+ return false;
34
+ }
35
+ return !(u === 0n && n >> 255n === 1n);
36
+ }
37
+ /** Canonical encodings of the 8 points of order 1, 2, 4 and 8 (canvas C8 `SMALL_ORDER`, checked complete there). */
38
+ export const SMALL_ORDER = Object.freeze(['0100000000000000000000000000000000000000000000000000000000000000', 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', '0000000000000000000000000000000000000000000000000000000000000000', '0000000000000000000000000000000000000000000000000000000000000080', '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05', '26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85', 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a', 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa']);
39
+ export function isSmallOrder(bytes) {
40
+ return bytes.length === 32 && SMALL_ORDER.includes(Buffer.from(bytes).toString('hex'));
41
+ }
42
+ //# sourceMappingURL=ed25519.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../../../src/jwk/ed25519.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,6GAA6G;AAE7G,MAAM,CAAC,GAAG,EAAE,IAAI,IAAI,GAAG,GAAG,CAAC;AAE3B,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AAErD,SAAS,GAAG,CAAC,IAAY,EAAE,GAAW;IACpC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;QACnE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACX,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAE/C;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,oHAAoH;AACpH,MAAM,CAAC,MAAM,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,EAAE,kEAAkE,CAAC,CAAC,CAAC;AAE9lB,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,OAAO,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACzF,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './base64url.js';
2
+ export * from './ed25519.js';
3
+ export * from './keys.js';
4
+ export * from './signature.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/jwk/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './base64url.js';
2
+ export * from './ed25519.js';
3
+ export * from './keys.js';
4
+ export * from './signature.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/jwk/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { KeyObject } from 'node:crypto';
2
+ import type { KeyAlgorithm, KeyMaterial, PublicJwk } from '@spinajs/authn/contracts';
3
+ export declare const KEY_ALGORITHMS: readonly KeyAlgorithm[];
4
+ export declare function isValidKid(kid: unknown): kid is string;
5
+ /**
6
+ * Design §22.10, canvas C8 D5: an Ed25519 key (RFC 8037) whose `x` is a canonical point and not of small order, or a
7
+ * P-256 key whose `x` and `y` are 32 bytes and on the curve; never a private part. Members other than the required ones
8
+ * are dropped, never trusted (the algorithm comes from the key type). Null for anything else.
9
+ */
10
+ export declare function checkPublicJwk(input: unknown, allowed?: readonly KeyAlgorithm[]): KeyMaterial | null;
11
+ /** RFC 7638: the required members only, in lexicographic order, no whitespace; SHA-256, base64url. */
12
+ export declare function thumbprint(jwk: PublicJwk): string;
13
+ /**
14
+ * The node:crypto key for a material that passes checkPublicJwk with its own algorithm, or null. Materials can come
15
+ * from a caller's key lookup, so they are checked again here (cached, as the point check costs a few modular powers).
16
+ */
17
+ export declare function publicKeyObject(material: KeyMaterial): KeyObject | null;
18
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../../src/jwk/keys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAoB,YAAY,EAAE,WAAW,EAAiB,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAKtH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAAsC,CAAC;AAIzF,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAEtD;AAYD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,SAAS,YAAY,EAAmB,GAAG,WAAW,GAAG,IAAI,CAmBpH;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAGjD;AAmBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAyBvE"}
@@ -0,0 +1,95 @@
1
+ import { createHash, createPublicKey } from 'node:crypto';
2
+ import { isPlainObject } from '@spinajs/util';
3
+ import { decodeB64url } from './base64url.js';
4
+ import { isCanonicalPoint, isSmallOrder } from './ed25519.js';
5
+ export const KEY_ALGORITHMS = Object.freeze(['EdDSA', 'ES256']);
6
+ const KID = /^[A-Za-z0-9._-]{1,64}$/;
7
+ export function isValidKid(kid) {
8
+ return typeof kid === 'string' && KID.test(kid);
9
+ }
10
+ const has32Bytes = (v) => decodeB64url(v)?.length === 32;
11
+ function importable(jwk) {
12
+ try {
13
+ return createPublicKey({ key: { ...jwk }, format: 'jwk' });
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
19
+ /**
20
+ * Design §22.10, canvas C8 D5: an Ed25519 key (RFC 8037) whose `x` is a canonical point and not of small order, or a
21
+ * P-256 key whose `x` and `y` are 32 bytes and on the curve; never a private part. Members other than the required ones
22
+ * are dropped, never trusted (the algorithm comes from the key type). Null for anything else.
23
+ */
24
+ export function checkPublicJwk(input, allowed = KEY_ALGORITHMS) {
25
+ if (!isPlainObject(input) || 'd' in input) {
26
+ return null;
27
+ }
28
+ let material = null;
29
+ if (input.kty === 'OKP' && input.crv === 'Ed25519' && has32Bytes(input.x)) {
30
+ const x = decodeB64url(input.x);
31
+ if (isCanonicalPoint(x) && !isSmallOrder(x)) {
32
+ const jwk = { kty: 'OKP', crv: 'Ed25519', x: input.x };
33
+ material = { alg: 'EdDSA', jwk };
34
+ }
35
+ }
36
+ else if (input.kty === 'EC' && input.crv === 'P-256' && has32Bytes(input.x) && has32Bytes(input.y)) {
37
+ const jwk = { kty: 'EC', crv: 'P-256', x: input.x, y: input.y };
38
+ material = { alg: 'ES256', jwk };
39
+ }
40
+ if (!material || !allowed.includes(material.alg) || !importable(material.jwk)) {
41
+ return null;
42
+ }
43
+ return material;
44
+ }
45
+ /** RFC 7638: the required members only, in lexicographic order, no whitespace; SHA-256, base64url. */
46
+ export function thumbprint(jwk) {
47
+ const json = jwk.kty === 'OKP' ? JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x }) : JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y });
48
+ return createHash('sha256').update(json, 'utf8').digest('base64url');
49
+ }
50
+ const CACHE_LIMIT = 1024;
51
+ const checked = new Map();
52
+ function cacheKey(m) {
53
+ const jwk = m.jwk;
54
+ if ('d' in jwk || typeof jwk.x !== 'string') {
55
+ return null;
56
+ }
57
+ if (m.alg === 'EdDSA' && jwk.kty === 'OKP' && jwk.crv === 'Ed25519') {
58
+ return `EdDSA:${jwk.x}`;
59
+ }
60
+ if (m.alg === 'ES256' && jwk.kty === 'EC' && jwk.crv === 'P-256' && typeof jwk.y === 'string') {
61
+ return `ES256:${jwk.x}:${jwk.y}`;
62
+ }
63
+ return null;
64
+ }
65
+ /**
66
+ * The node:crypto key for a material that passes checkPublicJwk with its own algorithm, or null. Materials can come
67
+ * from a caller's key lookup, so they are checked again here (cached, as the point check costs a few modular powers).
68
+ */
69
+ export function publicKeyObject(material) {
70
+ if (!isPlainObject(material) || !isPlainObject(material.jwk)) {
71
+ return null;
72
+ }
73
+ const key = cacheKey(material);
74
+ if (key === null) {
75
+ return null;
76
+ }
77
+ const hit = checked.get(key);
78
+ if (hit) {
79
+ return hit;
80
+ }
81
+ const ok = checkPublicJwk(material.jwk);
82
+ if (!ok || ok.alg !== material.alg) {
83
+ return null;
84
+ }
85
+ const object = importable(ok.jwk);
86
+ if (!object) {
87
+ return null;
88
+ }
89
+ if (checked.size >= CACHE_LIMIT) {
90
+ checked.delete(checked.keys().next().value);
91
+ }
92
+ checked.set(key, object);
93
+ return object;
94
+ }
95
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../../src/jwk/keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { KeyObject } from 'node:crypto';
2
+ import type { KeyAlgorithm, KeyMaterial } from '@spinajs/authn/contracts';
3
+ /** Raw signature length for both algorithms: Ed25519, and ES256 as IEEE P1363 r || s. */
4
+ export declare const SIGNATURE_BYTES = 64;
5
+ /** Verifies with the key's own algorithm; false for a key that fails the key checks or any other signature length. */
6
+ export declare function verifySignature(material: KeyMaterial, data: Uint8Array, signature: Uint8Array): boolean;
7
+ /** Raw signature: Ed25519, or ES256 over SHA-256 as IEEE P1363. */
8
+ export declare function signRaw(alg: KeyAlgorithm, privateKey: KeyObject, data: Uint8Array): Buffer;
9
+ /** The work of one verification under a key nobody holds, so an unknown key costs what a known one does (A02). */
10
+ export declare function dummyVerify(alg: KeyAlgorithm, data: Uint8Array, signature: Uint8Array): false;
11
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../../src/jwk/signature.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAI1E,yFAAyF;AACzF,eAAO,MAAM,eAAe,KAAK,CAAC;AAiBlC,sHAAsH;AACtH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAGvG;AAED,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAE1F;AAOD,kHAAkH;AAClH,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,KAAK,CAG7F"}
@@ -0,0 +1,39 @@
1
+ import { createPublicKey, generateKeyPairSync, sign, verify } from 'node:crypto';
2
+ import { isSmallOrder } from './ed25519.js';
3
+ import { publicKeyObject } from './keys.js';
4
+ /** Raw signature length for both algorithms: Ed25519, and ES256 as IEEE P1363 r || s. */
5
+ export const SIGNATURE_BYTES = 64;
6
+ function verifyWith(alg, key, data, signature) {
7
+ if (signature.length !== SIGNATURE_BYTES) {
8
+ return false;
9
+ }
10
+ try {
11
+ if (alg === 'EdDSA') {
12
+ // ed25519-dalek's verify_strict refuses a small-order R and OpenSSL does not; canvas C8 refuses it on both sides.
13
+ return !isSmallOrder(signature.subarray(0, 32)) && verify(null, data, key, signature);
14
+ }
15
+ return verify('sha256', data, { key, dsaEncoding: 'ieee-p1363' }, signature);
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ /** Verifies with the key's own algorithm; false for a key that fails the key checks or any other signature length. */
22
+ export function verifySignature(material, data, signature) {
23
+ const key = publicKeyObject(material);
24
+ return key !== null && verifyWith(material.alg, key, data, signature);
25
+ }
26
+ /** Raw signature: Ed25519, or ES256 over SHA-256 as IEEE P1363. */
27
+ export function signRaw(alg, privateKey, data) {
28
+ return alg === 'EdDSA' ? sign(null, data, privateKey) : sign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' });
29
+ }
30
+ const dummies = {
31
+ EdDSA: createPublicKey(generateKeyPairSync('ed25519').privateKey),
32
+ ES256: createPublicKey(generateKeyPairSync('ec', { namedCurve: 'P-256' }).privateKey),
33
+ };
34
+ /** The work of one verification under a key nobody holds, so an unknown key costs what a known one does (A02). */
35
+ export function dummyVerify(alg, data, signature) {
36
+ verifyWith(alg, dummies[alg], data, signature.length === SIGNATURE_BYTES ? signature : Buffer.alloc(SIGNATURE_BYTES, 1));
37
+ return false;
38
+ }
39
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../../../src/jwk/signature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,yFAAyF;AACzF,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,SAAS,UAAU,CAAC,GAAiB,EAAE,GAAc,EAAE,IAAgB,EAAE,SAAqB;IAC5F,IAAI,SAAS,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,kHAAkH;YAClH,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,eAAe,CAAC,QAAqB,EAAE,IAAgB,EAAE,SAAqB;IAC5F,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,GAAG,KAAK,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACxE,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,OAAO,CAAC,GAAiB,EAAE,UAAqB,EAAE,IAAgB;IAChF,OAAO,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;AAC/H,CAAC;AAED,MAAM,OAAO,GAAoC;IAC/C,KAAK,EAAE,eAAe,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC;IACjE,KAAK,EAAE,eAAe,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC;CACtF,CAAC;AAEF,kHAAkH;AAClH,MAAM,UAAU,WAAW,CAAC,GAAiB,EAAE,IAAgB,EAAE,SAAqB;IACpF,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;IACzH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './json.js';
2
+ export * from './verifier.js';
3
+ export * from './signer.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/jws/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './json.js';
2
+ export * from './verifier.js';
3
+ export * from './signer.js';
4
+ //# sourceMappingURL=index.js.map