@labacacia/nps-sdk 1.0.0-alpha.6 → 1.0.0-alpha.8

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 (369) hide show
  1. package/CHANGELOG.cn.md +126 -0
  2. package/CHANGELOG.md +135 -0
  3. package/README.cn.md +9 -2
  4. package/README.md +9 -2
  5. package/dist/core/anchor-cache.d.ts +42 -0
  6. package/dist/core/anchor-cache.d.ts.map +1 -0
  7. package/dist/core/anchor-cache.js +104 -0
  8. package/dist/core/anchor-cache.js.map +1 -0
  9. package/dist/core/cache.d.ts +14 -0
  10. package/dist/core/cache.d.ts.map +1 -0
  11. package/dist/core/cache.js +80 -0
  12. package/dist/core/cache.js.map +1 -0
  13. package/dist/core/canonical-json.d.ts +12 -0
  14. package/dist/core/canonical-json.d.ts.map +1 -0
  15. package/dist/core/canonical-json.js +44 -0
  16. package/dist/core/canonical-json.js.map +1 -0
  17. package/dist/core/codec.d.ts +32 -0
  18. package/dist/core/codec.d.ts.map +1 -0
  19. package/dist/core/codec.js +119 -0
  20. package/dist/core/codec.js.map +1 -0
  21. package/dist/core/codecs/index.d.ts +4 -0
  22. package/dist/core/codecs/index.d.ts.map +1 -0
  23. package/{src/core/codecs/index.ts → dist/core/codecs/index.js} +1 -0
  24. package/dist/core/codecs/index.js.map +1 -0
  25. package/dist/core/codecs/ncp-codec.d.ts +39 -0
  26. package/dist/core/codecs/ncp-codec.d.ts.map +1 -0
  27. package/dist/core/codecs/ncp-codec.js +93 -0
  28. package/dist/core/codecs/ncp-codec.js.map +1 -0
  29. package/dist/core/codecs/tier1-json-codec.d.ts +10 -0
  30. package/dist/core/codecs/tier1-json-codec.d.ts.map +1 -0
  31. package/{src/core/codecs/tier1-json-codec.ts → dist/core/codecs/tier1-json-codec.js} +11 -16
  32. package/dist/core/codecs/tier1-json-codec.js.map +1 -0
  33. package/dist/core/codecs/tier2-msgpack-codec.d.ts +10 -0
  34. package/dist/core/codecs/tier2-msgpack-codec.d.ts.map +1 -0
  35. package/{src/core/codecs/tier2-msgpack-codec.ts → dist/core/codecs/tier2-msgpack-codec.js} +10 -14
  36. package/dist/core/codecs/tier2-msgpack-codec.js.map +1 -0
  37. package/dist/core/crypto-provider.d.ts +31 -0
  38. package/dist/core/crypto-provider.d.ts.map +1 -0
  39. package/dist/core/crypto-provider.js +10 -0
  40. package/dist/core/crypto-provider.js.map +1 -0
  41. package/dist/core/exceptions.d.ts +27 -0
  42. package/dist/core/exceptions.d.ts.map +1 -0
  43. package/dist/core/exceptions.js +52 -0
  44. package/dist/core/exceptions.js.map +1 -0
  45. package/dist/core/frame-header.d.ts +87 -0
  46. package/dist/core/frame-header.d.ts.map +1 -0
  47. package/dist/core/frame-header.js +185 -0
  48. package/dist/core/frame-header.js.map +1 -0
  49. package/dist/core/frame-registry.d.ts +35 -0
  50. package/dist/core/frame-registry.d.ts.map +1 -0
  51. package/dist/core/frame-registry.js +63 -0
  52. package/dist/core/frame-registry.js.map +1 -0
  53. package/dist/core/frames.d.ts +82 -0
  54. package/dist/core/frames.d.ts.map +1 -0
  55. package/dist/core/frames.js +155 -0
  56. package/dist/core/frames.js.map +1 -0
  57. package/dist/core/index.d.ts +11 -0
  58. package/dist/core/index.d.ts.map +1 -0
  59. package/{src/core/index.ts → dist/core/index.js} +3 -23
  60. package/dist/core/index.js.map +1 -0
  61. package/dist/core/registry.d.ts +11 -0
  62. package/dist/core/registry.d.ts.map +1 -0
  63. package/dist/core/registry.js +17 -0
  64. package/dist/core/registry.js.map +1 -0
  65. package/dist/core/status-codes.d.ts +29 -0
  66. package/dist/core/status-codes.d.ts.map +1 -0
  67. package/dist/core/status-codes.js +39 -0
  68. package/dist/core/status-codes.js.map +1 -0
  69. package/dist/index.d.ts +2 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/{src/index.ts → dist/index.js} +1 -1
  72. package/dist/index.js.map +1 -0
  73. package/dist/ncp/frames/anchor-frame.d.ts +29 -0
  74. package/dist/ncp/frames/anchor-frame.d.ts.map +1 -0
  75. package/dist/ncp/frames/anchor-frame.js +54 -0
  76. package/dist/ncp/frames/anchor-frame.js.map +1 -0
  77. package/dist/ncp/frames/caps-frame.d.ts +29 -0
  78. package/dist/ncp/frames/caps-frame.d.ts.map +1 -0
  79. package/dist/ncp/frames/caps-frame.js +29 -0
  80. package/dist/ncp/frames/caps-frame.js.map +1 -0
  81. package/dist/ncp/frames/diff-frame.d.ts +32 -0
  82. package/dist/ncp/frames/diff-frame.d.ts.map +1 -0
  83. package/dist/ncp/frames/diff-frame.js +37 -0
  84. package/dist/ncp/frames/diff-frame.js.map +1 -0
  85. package/dist/ncp/frames/error-frame.d.ts +16 -0
  86. package/dist/ncp/frames/error-frame.d.ts.map +1 -0
  87. package/dist/ncp/frames/error-frame.js +13 -0
  88. package/dist/ncp/frames/error-frame.js.map +1 -0
  89. package/dist/ncp/frames/hello-frame.d.ts +21 -0
  90. package/dist/ncp/frames/hello-frame.d.ts.map +1 -0
  91. package/dist/ncp/frames/hello-frame.js +25 -0
  92. package/dist/ncp/frames/hello-frame.js.map +1 -0
  93. package/dist/ncp/frames/stream-frame.d.ts +16 -0
  94. package/dist/ncp/frames/stream-frame.d.ts.map +1 -0
  95. package/dist/ncp/frames/stream-frame.js +18 -0
  96. package/dist/ncp/frames/stream-frame.js.map +1 -0
  97. package/dist/ncp/frames.d.ts +94 -0
  98. package/dist/ncp/frames.d.ts.map +1 -0
  99. package/dist/ncp/frames.js +192 -0
  100. package/dist/ncp/frames.js.map +1 -0
  101. package/dist/ncp/handshake.d.ts +30 -0
  102. package/dist/ncp/handshake.d.ts.map +1 -0
  103. package/dist/ncp/handshake.js +80 -0
  104. package/dist/ncp/handshake.js.map +1 -0
  105. package/dist/ncp/index.d.ts +12 -0
  106. package/dist/ncp/index.d.ts.map +1 -0
  107. package/{src/ncp/index.ts → dist/ncp/index.js} +1 -0
  108. package/dist/ncp/index.js.map +1 -0
  109. package/dist/ncp/ncp-error-codes.d.ts +23 -0
  110. package/dist/ncp/ncp-error-codes.d.ts.map +1 -0
  111. package/dist/ncp/ncp-error-codes.js +34 -0
  112. package/dist/ncp/ncp-error-codes.js.map +1 -0
  113. package/dist/ncp/ncp-patch-format.d.ts +7 -0
  114. package/dist/ncp/ncp-patch-format.d.ts.map +1 -0
  115. package/dist/ncp/ncp-patch-format.js +13 -0
  116. package/dist/ncp/ncp-patch-format.js.map +1 -0
  117. package/dist/ncp/preamble.d.ts +47 -0
  118. package/dist/ncp/preamble.d.ts.map +1 -0
  119. package/dist/ncp/preamble.js +74 -0
  120. package/dist/ncp/preamble.js.map +1 -0
  121. package/dist/ncp/registry.d.ts +3 -0
  122. package/dist/ncp/registry.d.ts.map +1 -0
  123. package/dist/ncp/registry.js +13 -0
  124. package/dist/ncp/registry.js.map +1 -0
  125. package/dist/ncp/stream-manager.d.ts +57 -0
  126. package/dist/ncp/stream-manager.d.ts.map +1 -0
  127. package/dist/ncp/stream-manager.js +163 -0
  128. package/dist/ncp/stream-manager.js.map +1 -0
  129. package/dist/ndp/dns-txt.d.ts +35 -0
  130. package/dist/ndp/dns-txt.d.ts.map +1 -0
  131. package/dist/ndp/dns-txt.js +67 -0
  132. package/dist/ndp/dns-txt.js.map +1 -0
  133. package/dist/ndp/frames.d.ts +56 -0
  134. package/dist/ndp/frames.d.ts.map +1 -0
  135. package/dist/ndp/frames.js +87 -0
  136. package/dist/ndp/frames.js.map +1 -0
  137. package/dist/ndp/index.d.ts +6 -0
  138. package/dist/ndp/index.d.ts.map +1 -0
  139. package/{src/ndp/index.ts → dist/ndp/index.js} +1 -1
  140. package/dist/ndp/index.js.map +1 -0
  141. package/dist/ndp/ndp-registry.d.ts +13 -0
  142. package/dist/ndp/ndp-registry.d.ts.map +1 -0
  143. package/dist/ndp/ndp-registry.js +104 -0
  144. package/dist/ndp/ndp-registry.js.map +1 -0
  145. package/dist/ndp/registry.d.ts +3 -0
  146. package/dist/ndp/registry.d.ts.map +1 -0
  147. package/dist/ndp/registry.js +10 -0
  148. package/dist/ndp/registry.js.map +1 -0
  149. package/dist/ndp/validator.d.ts +18 -0
  150. package/dist/ndp/validator.d.ts.map +1 -0
  151. package/dist/ndp/validator.js +48 -0
  152. package/dist/ndp/validator.js.map +1 -0
  153. package/dist/nip/acme/client.d.ts +31 -0
  154. package/dist/nip/acme/client.d.ts.map +1 -0
  155. package/dist/nip/acme/client.js +136 -0
  156. package/dist/nip/acme/client.js.map +1 -0
  157. package/dist/nip/acme/index.d.ts +6 -0
  158. package/dist/nip/acme/index.d.ts.map +1 -0
  159. package/{src/nip/acme/index.ts → dist/nip/acme/index.js} +1 -1
  160. package/dist/nip/acme/index.js.map +1 -0
  161. package/dist/nip/acme/jws.d.ts +31 -0
  162. package/dist/nip/acme/jws.d.ts.map +1 -0
  163. package/dist/nip/acme/jws.js +76 -0
  164. package/dist/nip/acme/jws.js.map +1 -0
  165. package/dist/nip/acme/messages.d.ts +71 -0
  166. package/dist/nip/acme/messages.d.ts.map +1 -0
  167. package/dist/nip/acme/messages.js +4 -0
  168. package/dist/nip/acme/messages.js.map +1 -0
  169. package/dist/nip/acme/server.d.ts +41 -0
  170. package/dist/nip/acme/server.d.ts.map +1 -0
  171. package/dist/nip/acme/server.js +458 -0
  172. package/dist/nip/acme/server.js.map +1 -0
  173. package/dist/nip/acme/wire.d.ts +19 -0
  174. package/dist/nip/acme/wire.d.ts.map +1 -0
  175. package/dist/nip/acme/wire.js +21 -0
  176. package/dist/nip/acme/wire.js.map +1 -0
  177. package/dist/nip/assurance-level.d.ts +19 -0
  178. package/dist/nip/assurance-level.d.ts.map +1 -0
  179. package/dist/nip/assurance-level.js +38 -0
  180. package/dist/nip/assurance-level.js.map +1 -0
  181. package/dist/nip/cert-format.d.ts +5 -0
  182. package/dist/nip/cert-format.d.ts.map +1 -0
  183. package/dist/nip/cert-format.js +6 -0
  184. package/dist/nip/cert-format.js.map +1 -0
  185. package/dist/nip/error-codes.d.ts +25 -0
  186. package/dist/nip/error-codes.d.ts.map +1 -0
  187. package/{src/nip/error-codes.ts → dist/nip/error-codes.js} +19 -25
  188. package/dist/nip/error-codes.js.map +1 -0
  189. package/dist/nip/frames.d.ts +53 -0
  190. package/dist/nip/frames.d.ts.map +1 -0
  191. package/dist/nip/frames.js +106 -0
  192. package/dist/nip/frames.js.map +1 -0
  193. package/dist/nip/identity.d.ts +18 -0
  194. package/dist/nip/identity.d.ts.map +1 -0
  195. package/dist/nip/identity.js +94 -0
  196. package/dist/nip/identity.js.map +1 -0
  197. package/dist/nip/index.d.ts +11 -0
  198. package/dist/nip/index.d.ts.map +1 -0
  199. package/{src/nip/index.ts → dist/nip/index.js} +3 -2
  200. package/dist/nip/index.js.map +1 -0
  201. package/dist/nip/registry.d.ts +3 -0
  202. package/dist/nip/registry.d.ts.map +1 -0
  203. package/dist/nip/registry.js +10 -0
  204. package/dist/nip/registry.js.map +1 -0
  205. package/dist/nip/reputation-client.d.ts +116 -0
  206. package/dist/nip/reputation-client.d.ts.map +1 -0
  207. package/dist/nip/reputation-client.js +261 -0
  208. package/dist/nip/reputation-client.js.map +1 -0
  209. package/dist/nip/verifier.d.ts +23 -0
  210. package/dist/nip/verifier.d.ts.map +1 -0
  211. package/dist/nip/verifier.js +90 -0
  212. package/dist/nip/verifier.js.map +1 -0
  213. package/dist/nip/x509/builder.d.ts +35 -0
  214. package/dist/nip/x509/builder.d.ts.map +1 -0
  215. package/dist/nip/x509/builder.js +59 -0
  216. package/dist/nip/x509/builder.js.map +1 -0
  217. package/dist/nip/x509/index.d.ts +4 -0
  218. package/dist/nip/x509/index.d.ts.map +1 -0
  219. package/{src/nip/x509/index.ts → dist/nip/x509/index.js} +1 -1
  220. package/dist/nip/x509/index.js.map +1 -0
  221. package/dist/nip/x509/oids.d.ts +16 -0
  222. package/dist/nip/x509/oids.d.ts.map +1 -0
  223. package/{src/nip/x509/oids.ts → dist/nip/x509/oids.js} +5 -10
  224. package/dist/nip/x509/oids.js.map +1 -0
  225. package/dist/nip/x509/verifier.d.ts +26 -0
  226. package/dist/nip/x509/verifier.d.ts.map +1 -0
  227. package/dist/nip/x509/verifier.js +171 -0
  228. package/dist/nip/x509/verifier.js.map +1 -0
  229. package/dist/nop/client.d.ts +34 -0
  230. package/dist/nop/client.d.ts.map +1 -0
  231. package/dist/nop/client.js +90 -0
  232. package/dist/nop/client.js.map +1 -0
  233. package/dist/nop/frames.d.ts +65 -0
  234. package/dist/nop/frames.d.ts.map +1 -0
  235. package/dist/nop/frames.js +148 -0
  236. package/dist/nop/frames.js.map +1 -0
  237. package/dist/nop/index.d.ts +5 -0
  238. package/dist/nop/index.d.ts.map +1 -0
  239. package/{src/nop/index.ts → dist/nop/index.js} +1 -1
  240. package/dist/nop/index.js.map +1 -0
  241. package/dist/nop/models.d.ts +58 -0
  242. package/dist/nop/models.d.ts.map +1 -0
  243. package/dist/nop/models.js +50 -0
  244. package/dist/nop/models.js.map +1 -0
  245. package/dist/nop/nop-types.d.ts +136 -0
  246. package/dist/nop/nop-types.d.ts.map +1 -0
  247. package/dist/nop/nop-types.js +44 -0
  248. package/dist/nop/nop-types.js.map +1 -0
  249. package/dist/nop/registry.d.ts +3 -0
  250. package/dist/nop/registry.d.ts.map +1 -0
  251. package/dist/nop/registry.js +11 -0
  252. package/dist/nop/registry.js.map +1 -0
  253. package/dist/nwp/anchor-client.d.ts +109 -0
  254. package/dist/nwp/anchor-client.d.ts.map +1 -0
  255. package/dist/nwp/anchor-client.js +279 -0
  256. package/dist/nwp/anchor-client.js.map +1 -0
  257. package/dist/nwp/client.d.ts +28 -0
  258. package/dist/nwp/client.d.ts.map +1 -0
  259. package/dist/nwp/client.js +142 -0
  260. package/dist/nwp/client.js.map +1 -0
  261. package/dist/nwp/frames.d.ts +107 -0
  262. package/dist/nwp/frames.d.ts.map +1 -0
  263. package/dist/nwp/frames.js +198 -0
  264. package/dist/nwp/frames.js.map +1 -0
  265. package/dist/nwp/index.d.ts +6 -0
  266. package/dist/nwp/index.d.ts.map +1 -0
  267. package/{src/nwp/index.ts → dist/nwp/index.js} +3 -1
  268. package/dist/nwp/index.js.map +1 -0
  269. package/dist/nwp/manifest.d.ts +69 -0
  270. package/dist/nwp/manifest.d.ts.map +1 -0
  271. package/dist/nwp/manifest.js +4 -0
  272. package/dist/nwp/manifest.js.map +1 -0
  273. package/dist/nwp/registry.d.ts +3 -0
  274. package/dist/nwp/registry.d.ts.map +1 -0
  275. package/dist/nwp/registry.js +10 -0
  276. package/dist/nwp/registry.js.map +1 -0
  277. package/dist/setup.d.ts +10 -0
  278. package/dist/setup.d.ts.map +1 -0
  279. package/{src/setup.ts → dist/setup.js} +13 -16
  280. package/dist/setup.js.map +1 -0
  281. package/package.json +12 -1
  282. package/CONTRIBUTING.cn.md +0 -35
  283. package/CONTRIBUTING.md +0 -35
  284. package/nip-ca-server/Dockerfile +0 -27
  285. package/nip-ca-server/README.md +0 -45
  286. package/nip-ca-server/db/001_init.sql +0 -25
  287. package/nip-ca-server/docker-compose.yml +0 -29
  288. package/nip-ca-server/package.json +0 -23
  289. package/nip-ca-server/src/ca.ts +0 -155
  290. package/nip-ca-server/src/db.ts +0 -104
  291. package/nip-ca-server/src/index.ts +0 -157
  292. package/nip-ca-server/tsconfig.json +0 -13
  293. package/src/core/anchor-cache.ts +0 -129
  294. package/src/core/cache.ts +0 -93
  295. package/src/core/canonical-json.ts +0 -50
  296. package/src/core/codec.ts +0 -158
  297. package/src/core/codecs/ncp-codec.ts +0 -170
  298. package/src/core/crypto-provider.ts +0 -47
  299. package/src/core/exceptions.ts +0 -57
  300. package/src/core/frame-header.ts +0 -282
  301. package/src/core/frame-registry.ts +0 -91
  302. package/src/core/frames.ts +0 -184
  303. package/src/core/registry.ts +0 -28
  304. package/src/core/status-codes.ts +0 -47
  305. package/src/ncp/frames/anchor-frame.ts +0 -87
  306. package/src/ncp/frames/caps-frame.ts +0 -59
  307. package/src/ncp/frames/diff-frame.ts +0 -69
  308. package/src/ncp/frames/error-frame.ts +0 -26
  309. package/src/ncp/frames/hello-frame.ts +0 -50
  310. package/src/ncp/frames/stream-frame.ts +0 -35
  311. package/src/ncp/frames.ts +0 -251
  312. package/src/ncp/handshake.ts +0 -95
  313. package/src/ncp/ncp-error-codes.ts +0 -36
  314. package/src/ncp/ncp-patch-format.ts +0 -16
  315. package/src/ncp/preamble.ts +0 -79
  316. package/src/ncp/registry.ts +0 -15
  317. package/src/ncp/stream-manager.ts +0 -212
  318. package/src/ndp/dns-txt.ts +0 -86
  319. package/src/ndp/frames.ts +0 -124
  320. package/src/ndp/ndp-registry.ts +0 -116
  321. package/src/ndp/registry.ts +0 -12
  322. package/src/ndp/validator.ts +0 -64
  323. package/src/nip/acme/client.ts +0 -185
  324. package/src/nip/acme/jws.ts +0 -109
  325. package/src/nip/acme/messages.ts +0 -85
  326. package/src/nip/acme/server.ts +0 -480
  327. package/src/nip/acme/wire.ts +0 -24
  328. package/src/nip/assurance-level.ts +0 -40
  329. package/src/nip/cert-format.ts +0 -9
  330. package/src/nip/frames.ts +0 -138
  331. package/src/nip/identity.ts +0 -113
  332. package/src/nip/registry.ts +0 -12
  333. package/src/nip/verifier.ts +0 -122
  334. package/src/nip/x509/builder.ts +0 -91
  335. package/src/nip/x509/verifier.ts +0 -214
  336. package/src/nop/client.ts +0 -103
  337. package/src/nop/frames.ts +0 -181
  338. package/src/nop/models.ts +0 -79
  339. package/src/nop/nop-types.ts +0 -208
  340. package/src/nop/registry.ts +0 -13
  341. package/src/nwp/client.ts +0 -114
  342. package/src/nwp/frames.ts +0 -116
  343. package/src/nwp/registry.ts +0 -11
  344. package/tests/_rfc0002-keys.ts +0 -57
  345. package/tests/core/anchor-cache.test.ts +0 -242
  346. package/tests/core/codec.test.ts +0 -205
  347. package/tests/core/frame-registry.test.ts +0 -46
  348. package/tests/core.test.ts +0 -327
  349. package/tests/ncp/diff-binary-bitset.test.ts +0 -107
  350. package/tests/ncp/e2e-enc-reject.test.ts +0 -93
  351. package/tests/ncp/err-error-frame.test.ts +0 -152
  352. package/tests/ncp/frames.test.ts +0 -359
  353. package/tests/ncp/framing.test.ts +0 -233
  354. package/tests/ncp/hello-frame.test.ts +0 -122
  355. package/tests/ncp/inline-anchor.test.ts +0 -88
  356. package/tests/ncp/preamble.test.ts +0 -93
  357. package/tests/ncp/security.test.ts +0 -184
  358. package/tests/ncp/stream-window.test.ts +0 -167
  359. package/tests/ncp/stream.test.ts +0 -242
  360. package/tests/ncp/version-negotiation.test.ts +0 -123
  361. package/tests/ndp.test.ts +0 -377
  362. package/tests/nip-acme-agent01.test.ts +0 -192
  363. package/tests/nip-x509.test.ts +0 -280
  364. package/tests/nip.test.ts +0 -184
  365. package/tests/nop.test.ts +0 -344
  366. package/tests/nwp.test.ts +0 -237
  367. package/tsconfig.json +0 -20
  368. package/tsup.config.ts +0 -20
  369. package/vitest.config.ts +0 -10
@@ -1,280 +0,0 @@
1
- // Copyright 2026 INNO LOTUS PTY LTD
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- // TypeScript parallel of Java NipX509Tests / .NET NipX509Tests per NPS-RFC-0002 §4.
5
- // Covers the 5 verification scenarios documented in the .NET reference.
6
-
7
- import { describe, expect, it } from "vitest";
8
- import * as ed25519 from "@noble/ed25519";
9
- import { sha512 } from "@noble/hashes/sha512";
10
- import * as x509 from "@peculiar/x509";
11
-
12
- import { AssuranceLevel } from "../src/nip/assurance-level.js";
13
- import { V2_X509 } from "../src/nip/cert-format.js";
14
- import * as ec from "../src/nip/error-codes.js";
15
- import { IdentFrame } from "../src/nip/frames.js";
16
- import { NipIdentVerifier } from "../src/nip/verifier.js";
17
- import { issueLeaf, issueRoot } from "../src/nip/x509/builder.js";
18
- import { generateDualKeyPair, randomHexSerial, type DualKeyPair } from "./_rfc0002-keys.js";
19
-
20
- ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));
21
- x509.cryptoProvider.set(globalThis.crypto);
22
-
23
- describe("NipX509 — RFC-0002 §4 verifier scenarios", () => {
24
-
25
- it("registerX509 round-trip — dual-trust verifier accepts", async () => {
26
- const caNid = "urn:nps:ca:test";
27
- const agentNid = "urn:nps:agent:happy:1";
28
-
29
- const ca = await generateDualKeyPair();
30
- const agent = await generateDualKeyPair();
31
-
32
- const root = await issueRoot({
33
- caNid, caKeys: ca.webCrypto,
34
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
35
- serialNumber: "01",
36
- });
37
- const leaf = await issueLeaf({
38
- subjectNid: agentNid, subjectPublicKey: agent.webCrypto.publicKey,
39
- caKeys: ca.webCrypto, issuerNid: caNid, role: "agent",
40
- assuranceLevel: AssuranceLevel.ATTESTED,
41
- notBefore: minutesAgo(1), notAfter: daysFromNow(30),
42
- serialNumber: "02",
43
- });
44
-
45
- const frame = await buildV2Frame(agentNid, agent.pubRaw, ca.privRaw,
46
- AssuranceLevel.ATTESTED, leaf, root);
47
-
48
- const verifier = new NipIdentVerifier({
49
- trustedCaPublicKeys: { [caNid]: pubKeyHex(ca.pubRaw) },
50
- trustedX509Roots: [root],
51
- });
52
- const result = await verifier.verify(frame, caNid);
53
-
54
- expect(result.valid).toBe(true);
55
- expect(result.stepFailed).toBe(0);
56
- });
57
-
58
- it("leaf without EKU extension — verifier rejects with NIP-CERT-EKU-MISSING", async () => {
59
- const caNid = "urn:nps:ca:test";
60
- const agentNid = "urn:nps:agent:eku-stripped:1";
61
-
62
- const ca = await generateDualKeyPair();
63
- const agent = await generateDualKeyPair();
64
-
65
- const root = await issueRoot({
66
- caNid, caKeys: ca.webCrypto,
67
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
68
- serialNumber: "01",
69
- });
70
- const tampered = await buildLeafWithoutEku(
71
- agentNid, agent.webCrypto.publicKey, ca.webCrypto, caNid, "63");
72
-
73
- const frame = await buildV2Frame(agentNid, agent.pubRaw, ca.privRaw,
74
- null, tampered, root);
75
-
76
- const verifier = new NipIdentVerifier({
77
- trustedCaPublicKeys: { [caNid]: pubKeyHex(ca.pubRaw) },
78
- trustedX509Roots: [root],
79
- });
80
- const result = await verifier.verify(frame, caNid);
81
-
82
- expect(result.valid).toBe(false);
83
- expect(result.errorCode).toBe(ec.CERT_EKU_MISSING);
84
- expect(result.stepFailed).toBe(3);
85
- });
86
-
87
- it("leaf for different NID — verifier rejects with NIP-CERT-SUBJECT-NID-MISMATCH", async () => {
88
- const caNid = "urn:nps:ca:test";
89
- const victimNid = "urn:nps:agent:victim:1";
90
- const forgedNid = "urn:nps:agent:attacker:9";
91
-
92
- const ca = await generateDualKeyPair();
93
- const agent = await generateDualKeyPair();
94
-
95
- const root = await issueRoot({
96
- caNid, caKeys: ca.webCrypto,
97
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
98
- serialNumber: "01",
99
- });
100
- // Issue a leaf whose CN/SAN are the *forged* NID, but splice it into a
101
- // frame asserting the *victim* NID. The v1 Ed25519 sig still asserts victim.
102
- const forgedLeaf = await issueLeaf({
103
- subjectNid: forgedNid, subjectPublicKey: agent.webCrypto.publicKey,
104
- caKeys: ca.webCrypto, issuerNid: caNid, role: "agent",
105
- assuranceLevel: AssuranceLevel.ANONYMOUS,
106
- notBefore: minutesAgo(1), notAfter: daysFromNow(30),
107
- serialNumber: "4d",
108
- });
109
-
110
- const frame = await buildV2Frame(victimNid, agent.pubRaw, ca.privRaw,
111
- null, forgedLeaf, root);
112
-
113
- const verifier = new NipIdentVerifier({
114
- trustedCaPublicKeys: { [caNid]: pubKeyHex(ca.pubRaw) },
115
- trustedX509Roots: [root],
116
- });
117
- const result = await verifier.verify(frame, caNid);
118
-
119
- expect(result.valid).toBe(false);
120
- expect(result.errorCode).toBe(ec.CERT_SUBJECT_NID_MISMATCH);
121
- expect(result.stepFailed).toBe(3);
122
- });
123
-
124
- it("v1-only verifier ignores cert_chain and accepts v2 frames (Phase 1 backward compat)", async () => {
125
- const caNid = "urn:nps:ca:test";
126
- const agentNid = "urn:nps:agent:v1-compat:1";
127
-
128
- const ca = await generateDualKeyPair();
129
- const agent = await generateDualKeyPair();
130
-
131
- const root = await issueRoot({
132
- caNid, caKeys: ca.webCrypto,
133
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
134
- serialNumber: "01",
135
- });
136
- const leaf = await issueLeaf({
137
- subjectNid: agentNid, subjectPublicKey: agent.webCrypto.publicKey,
138
- caKeys: ca.webCrypto, issuerNid: caNid, role: "agent",
139
- assuranceLevel: AssuranceLevel.ANONYMOUS,
140
- notBefore: minutesAgo(1), notAfter: daysFromNow(30),
141
- serialNumber: "02",
142
- });
143
-
144
- const frame = await buildV2Frame(agentNid, agent.pubRaw, ca.privRaw,
145
- null, leaf, root);
146
-
147
- // Verifier WITHOUT trustedX509Roots — Step 3b is skipped entirely.
148
- const verifier = new NipIdentVerifier({
149
- trustedCaPublicKeys: { [caNid]: pubKeyHex(ca.pubRaw) },
150
- });
151
- const result = await verifier.verify(frame, caNid);
152
-
153
- expect(result.valid).toBe(true);
154
- expect(result.stepFailed).toBe(0);
155
- });
156
-
157
- it("v2 verifier with unrelated trust root rejects with NIP-CERT-FORMAT-INVALID", async () => {
158
- const caNid = "urn:nps:ca:test";
159
- const agentNid = "urn:nps:agent:wrong-trust:1";
160
-
161
- const ca = await generateDualKeyPair();
162
- const agent = await generateDualKeyPair();
163
-
164
- const root = await issueRoot({
165
- caNid, caKeys: ca.webCrypto,
166
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
167
- serialNumber: "01",
168
- });
169
- const leaf = await issueLeaf({
170
- subjectNid: agentNid, subjectPublicKey: agent.webCrypto.publicKey,
171
- caKeys: ca.webCrypto, issuerNid: caNid, role: "agent",
172
- assuranceLevel: AssuranceLevel.ANONYMOUS,
173
- notBefore: minutesAgo(1), notAfter: daysFromNow(30),
174
- serialNumber: "02",
175
- });
176
-
177
- const frame = await buildV2Frame(agentNid, agent.pubRaw, ca.privRaw,
178
- null, leaf, root);
179
-
180
- // Different unrelated CA root — chain won't anchor.
181
- const otherCa = await generateDualKeyPair();
182
- const otherRoot = await issueRoot({
183
- caNid: "urn:nps:ca:other", caKeys: otherCa.webCrypto,
184
- notBefore: minutesAgo(1), notAfter: daysFromNow(365),
185
- serialNumber: "01",
186
- });
187
-
188
- const verifier = new NipIdentVerifier({
189
- trustedCaPublicKeys: { [caNid]: pubKeyHex(ca.pubRaw) },
190
- trustedX509Roots: [otherRoot],
191
- });
192
- const result = await verifier.verify(frame, caNid);
193
-
194
- expect(result.valid).toBe(false);
195
- expect(result.errorCode).toBe(ec.CERT_FORMAT_INVALID);
196
- expect(result.stepFailed).toBe(3);
197
- });
198
- });
199
-
200
- // ── helpers ──────────────────────────────────────────────────────────────────
201
-
202
- /**
203
- * Build a v2 IdentFrame including a v1 Ed25519 CA signature over the canonical
204
- * unsigned dict (matches IdentFrame.unsignedDict + NipIdentVerifier signing path).
205
- */
206
- async function buildV2Frame(
207
- subjectNid: string,
208
- subjectPub: Uint8Array,
209
- caPriv: Uint8Array,
210
- level: AssuranceLevel | null,
211
- leaf: x509.X509Certificate,
212
- root: x509.X509Certificate,
213
- ): Promise<IdentFrame> {
214
- const pubKeyStr = pubKeyHex(subjectPub);
215
- const metadata = { issued_by: "test-ca" };
216
-
217
- const unsigned: Record<string, unknown> = {
218
- nid: subjectNid,
219
- pub_key: pubKeyStr,
220
- metadata,
221
- };
222
- if (level !== null) unsigned["assurance_level"] = level.wire;
223
-
224
- const canonical = JSON.stringify(unsigned, Object.keys(unsigned).sort());
225
- const sig = ed25519.sign(new TextEncoder().encode(canonical), caPriv);
226
- const sigWire = "ed25519:" + Buffer.from(sig).toString("base64");
227
-
228
- const chain = [
229
- b64uEncode(new Uint8Array(leaf.rawData)),
230
- b64uEncode(new Uint8Array(root.rawData)),
231
- ];
232
-
233
- return new IdentFrame(subjectNid, pubKeyStr, metadata, sigWire, {
234
- assuranceLevel: level,
235
- certFormat: V2_X509,
236
- certChain: chain,
237
- });
238
- }
239
-
240
- /** Issue a leaf cert with EKU extension deliberately omitted. */
241
- async function buildLeafWithoutEku(
242
- subjectNid: string,
243
- subjectPub: CryptoKey,
244
- caKeys: CryptoKeyPair,
245
- caNid: string,
246
- serial: string,
247
- ): Promise<x509.X509Certificate> {
248
- const escape = (v: string) => v.replace(/([",+;<>\\])/g, "\\$1");
249
- return x509.X509CertificateGenerator.create({
250
- serialNumber: serial,
251
- issuer: `CN=${escape(caNid)}`,
252
- subject: `CN=${escape(subjectNid)}`,
253
- notBefore: minutesAgo(1),
254
- notAfter: daysFromNow(30),
255
- publicKey: subjectPub,
256
- signingAlgorithm: { name: "Ed25519" },
257
- signingKey: caKeys.privateKey,
258
- extensions: [
259
- new x509.BasicConstraintsExtension(false, undefined, true),
260
- new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature, true),
261
- // ★ Deliberately NO ExtendedKeyUsage extension.
262
- new x509.SubjectAlternativeNameExtension([{ type: "url", value: subjectNid }], false),
263
- ],
264
- });
265
- }
266
-
267
- function pubKeyHex(raw: Uint8Array): string {
268
- return "ed25519:" + Buffer.from(raw).toString("hex");
269
- }
270
-
271
- function b64uEncode(bytes: Uint8Array): string {
272
- return Buffer.from(bytes).toString("base64").replace(/=+$/, "")
273
- .replace(/\+/g, "-").replace(/\//g, "_");
274
- }
275
-
276
- function minutesAgo(n: number): Date { return new Date(Date.now() - n * 60_000); }
277
- function daysFromNow(n: number): Date { return new Date(Date.now() + n * 24 * 3600_000); }
278
-
279
- // Touch the type so TS doesn't tree-shake the import in declaration emit.
280
- type _ = DualKeyPair;
package/tests/nip.test.ts DELETED
@@ -1,184 +0,0 @@
1
- // Copyright 2026 INNO LOTUS PTY LTD
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- import { describe, expect, it } from "vitest";
5
- import { mkdtempSync, rmSync } from "node:fs";
6
- import { tmpdir } from "node:os";
7
- import { join } from "node:path";
8
- import { NipIdentity } from "../src/nip/identity.js";
9
- import { IdentFrame, TrustFrame, RevokeFrame } from "../src/nip/frames.js";
10
- import { createFullRegistry } from "../src/setup.js";
11
- import { NpsFrameCodec } from "../src/core/index.js";
12
-
13
- // ── NipIdentity ───────────────────────────────────────────────────────────────
14
-
15
- describe("NipIdentity", () => {
16
- it("generate() creates distinct keys each time", () => {
17
- const a = NipIdentity.generate();
18
- const b = NipIdentity.generate();
19
- expect(Buffer.from(a.pubKey).toString("hex")).not.toBe(Buffer.from(b.pubKey).toString("hex"));
20
- });
21
-
22
- it("fromPrivateKey() derives consistent public key", () => {
23
- const id = NipIdentity.generate();
24
- const id2 = NipIdentity.fromPrivateKey(id["_privKey"]);
25
- expect(Buffer.from(id2.pubKey).toString("hex")).toBe(Buffer.from(id.pubKey).toString("hex"));
26
- });
27
-
28
- it("pubKeyString returns 'ed25519:<hex>'", () => {
29
- const id = NipIdentity.generate();
30
- expect(id.pubKeyString).toMatch(/^ed25519:[0-9a-f]{64}$/);
31
- });
32
-
33
- it("sign + verify roundtrip succeeds", () => {
34
- const id = NipIdentity.generate();
35
- const payload = { action: "announce", nid: "urn:nps:node:test:1", ts: "2026-01-01T00:00:00Z" };
36
- const sig = id.sign(payload);
37
- expect(sig).toMatch(/^ed25519:/);
38
- expect(id.verify(payload, sig)).toBe(true);
39
- });
40
-
41
- it("verify returns false for tampered payload", () => {
42
- const id = NipIdentity.generate();
43
- const payload = { foo: "bar" };
44
- const sig = id.sign(payload);
45
- expect(id.verify({ foo: "baz" }, sig)).toBe(false);
46
- });
47
-
48
- it("verify returns false for wrong prefix", () => {
49
- const id = NipIdentity.generate();
50
- const payload = { x: 1 };
51
- expect(id.verify(payload, "rsa:abc")).toBe(false);
52
- });
53
-
54
- it("verify returns false for corrupted base64", () => {
55
- const id = NipIdentity.generate();
56
- const payload = { x: 1 };
57
- expect(id.verify(payload, "ed25519:!!!")).toBe(false);
58
- });
59
-
60
- it("sign is canonical — key-order independent", () => {
61
- const id = NipIdentity.generate();
62
- const p1 = { b: 2, a: 1 };
63
- const p2 = { a: 1, b: 2 };
64
- const s1 = id.sign(p1);
65
- const s2 = id.sign(p2);
66
- expect(s1).toBe(s2);
67
- });
68
-
69
- it("save + load roundtrip", () => {
70
- const dir = mkdtempSync(join(tmpdir(), "nip-test-"));
71
- const path = join(dir, "key.json");
72
- try {
73
- const id = NipIdentity.generate();
74
- const pass = "test-passphrase-123";
75
- id.save(path, pass);
76
- const loaded = NipIdentity.load(path, pass);
77
- // Verify signatures from loaded key match original
78
- const payload = { hello: "world" };
79
- const sig = id.sign(payload);
80
- expect(loaded.verify(payload, sig)).toBe(true);
81
- expect(Buffer.from(loaded.pubKey).toString("hex")).toBe(
82
- Buffer.from(id.pubKey).toString("hex"),
83
- );
84
- } finally {
85
- rmSync(dir, { recursive: true });
86
- }
87
- });
88
-
89
- it("load with wrong passphrase throws", () => {
90
- const dir = mkdtempSync(join(tmpdir(), "nip-test-"));
91
- const path = join(dir, "key.json");
92
- try {
93
- NipIdentity.generate().save(path, "correct-pass");
94
- expect(() => NipIdentity.load(path, "wrong-pass")).toThrow();
95
- } finally {
96
- rmSync(dir, { recursive: true });
97
- }
98
- });
99
- });
100
-
101
- // ── IdentFrame ────────────────────────────────────────────────────────────────
102
-
103
- describe("IdentFrame", () => {
104
- const NID = "urn:nps:node:example.com:svc";
105
- const meta = { issuer: "urn:nps:ca:root", issuedAt: "2026-01-01T00:00:00Z", expiresAt: "2027-01-01T00:00:00Z" };
106
-
107
- it("toDict / fromDict roundtrip", () => {
108
- const f = new IdentFrame(NID, "ed25519:aabbcc", meta, "ed25519:sig");
109
- const back = IdentFrame.fromDict(f.toDict());
110
- expect(back.nid).toBe(NID);
111
- expect(back.pubKey).toBe("ed25519:aabbcc");
112
- expect(back.metadata.issuer).toBe("urn:nps:ca:root");
113
- expect(back.signature).toBe("ed25519:sig");
114
- });
115
-
116
- it("unsignedDict omits signature", () => {
117
- const f = new IdentFrame(NID, "ed25519:aabbcc", meta, "ed25519:sig");
118
- const d = f.unsignedDict();
119
- expect(d["signature"]).toBeUndefined();
120
- expect(d["pub_key"]).toBe("ed25519:aabbcc");
121
- });
122
-
123
- it("codec roundtrip (MsgPack)", () => {
124
- const registry = createFullRegistry();
125
- const codec = new NpsFrameCodec(registry);
126
- const f = new IdentFrame(NID, "ed25519:aabbcc", meta, "ed25519:sig");
127
- const back = codec.decode(codec.encode(f)) as IdentFrame;
128
- expect(back).toBeInstanceOf(IdentFrame);
129
- expect(back.nid).toBe(NID);
130
- });
131
- });
132
-
133
- // ── TrustFrame ────────────────────────────────────────────────────────────────
134
-
135
- describe("TrustFrame", () => {
136
- it("toDict / fromDict roundtrip", () => {
137
- const f = new TrustFrame(
138
- "urn:nps:node:issuer:1", "urn:nps:node:subject:1",
139
- ["nwp/query"], "2027-01-01T00:00:00Z", "ed25519:sig",
140
- );
141
- const back = TrustFrame.fromDict(f.toDict());
142
- expect(back.issuerNid).toBe("urn:nps:node:issuer:1");
143
- expect(back.subjectNid).toBe("urn:nps:node:subject:1");
144
- expect(back.scopes[0]).toBe("nwp/query");
145
- expect(back.expiresAt).toBe("2027-01-01T00:00:00Z");
146
- expect(back.signature).toBe("ed25519:sig");
147
- });
148
-
149
- it("codec roundtrip (MsgPack)", () => {
150
- const registry = createFullRegistry();
151
- const codec = new NpsFrameCodec(registry);
152
- const f = new TrustFrame("urn:nps:node:a:1", "urn:nps:node:b:1", ["nwp/query"], "2027-01-01T00:00:00Z", "ed25519:sig");
153
- const back = codec.decode(codec.encode(f)) as TrustFrame;
154
- expect(back).toBeInstanceOf(TrustFrame);
155
- });
156
- });
157
-
158
- // ── RevokeFrame ───────────────────────────────────────────────────────────────
159
-
160
- describe("RevokeFrame", () => {
161
- it("toDict / fromDict with all fields", () => {
162
- const f = new RevokeFrame("urn:nps:node:a:1", "compromised", "2026-06-01T00:00:00Z");
163
- const back = RevokeFrame.fromDict(f.toDict());
164
- expect(back.nid).toBe("urn:nps:node:a:1");
165
- expect(back.reason).toBe("compromised");
166
- expect(back.revokedAt).toBe("2026-06-01T00:00:00Z");
167
- });
168
-
169
- it("optional fields default to undefined", () => {
170
- const f = new RevokeFrame("urn:nps:node:a:1");
171
- const back = RevokeFrame.fromDict(f.toDict());
172
- expect(back.reason).toBeUndefined();
173
- expect(back.revokedAt).toBeUndefined();
174
- });
175
-
176
- it("codec roundtrip (MsgPack)", () => {
177
- const registry = createFullRegistry();
178
- const codec = new NpsFrameCodec(registry);
179
- const f = new RevokeFrame("urn:nps:node:a:1", "expired");
180
- const back = codec.decode(codec.encode(f)) as RevokeFrame;
181
- expect(back).toBeInstanceOf(RevokeFrame);
182
- expect(back.reason).toBe("expired");
183
- });
184
- });