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

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 (365) hide show
  1. package/CHANGELOG.cn.md +115 -0
  2. package/CHANGELOG.md +124 -0
  3. package/README.cn.md +3 -1
  4. package/README.md +3 -1
  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 +81 -0
  54. package/dist/core/frames.d.ts.map +1 -0
  55. package/dist/core/frames.js +154 -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 +22 -0
  258. package/dist/nwp/client.d.ts.map +1 -0
  259. package/dist/nwp/client.js +101 -0
  260. package/dist/nwp/client.js.map +1 -0
  261. package/dist/nwp/frames.d.ts +46 -0
  262. package/dist/nwp/frames.d.ts.map +1 -0
  263. package/dist/nwp/frames.js +81 -0
  264. package/dist/nwp/frames.js.map +1 -0
  265. package/dist/nwp/index.d.ts +5 -0
  266. package/dist/nwp/index.d.ts.map +1 -0
  267. package/{src/nwp/index.ts → dist/nwp/index.js} +2 -1
  268. package/dist/nwp/index.js.map +1 -0
  269. package/dist/nwp/registry.d.ts +3 -0
  270. package/dist/nwp/registry.d.ts.map +1 -0
  271. package/dist/nwp/registry.js +9 -0
  272. package/dist/nwp/registry.js.map +1 -0
  273. package/dist/setup.d.ts +10 -0
  274. package/dist/setup.d.ts.map +1 -0
  275. package/{src/setup.ts → dist/setup.js} +13 -16
  276. package/dist/setup.js.map +1 -0
  277. package/package.json +12 -1
  278. package/CONTRIBUTING.cn.md +0 -35
  279. package/CONTRIBUTING.md +0 -35
  280. package/nip-ca-server/Dockerfile +0 -27
  281. package/nip-ca-server/README.md +0 -45
  282. package/nip-ca-server/db/001_init.sql +0 -25
  283. package/nip-ca-server/docker-compose.yml +0 -29
  284. package/nip-ca-server/package.json +0 -23
  285. package/nip-ca-server/src/ca.ts +0 -155
  286. package/nip-ca-server/src/db.ts +0 -104
  287. package/nip-ca-server/src/index.ts +0 -157
  288. package/nip-ca-server/tsconfig.json +0 -13
  289. package/src/core/anchor-cache.ts +0 -129
  290. package/src/core/cache.ts +0 -93
  291. package/src/core/canonical-json.ts +0 -50
  292. package/src/core/codec.ts +0 -158
  293. package/src/core/codecs/ncp-codec.ts +0 -170
  294. package/src/core/crypto-provider.ts +0 -47
  295. package/src/core/exceptions.ts +0 -57
  296. package/src/core/frame-header.ts +0 -282
  297. package/src/core/frame-registry.ts +0 -91
  298. package/src/core/frames.ts +0 -184
  299. package/src/core/registry.ts +0 -28
  300. package/src/core/status-codes.ts +0 -47
  301. package/src/ncp/frames/anchor-frame.ts +0 -87
  302. package/src/ncp/frames/caps-frame.ts +0 -59
  303. package/src/ncp/frames/diff-frame.ts +0 -69
  304. package/src/ncp/frames/error-frame.ts +0 -26
  305. package/src/ncp/frames/hello-frame.ts +0 -50
  306. package/src/ncp/frames/stream-frame.ts +0 -35
  307. package/src/ncp/frames.ts +0 -251
  308. package/src/ncp/handshake.ts +0 -95
  309. package/src/ncp/ncp-error-codes.ts +0 -36
  310. package/src/ncp/ncp-patch-format.ts +0 -16
  311. package/src/ncp/preamble.ts +0 -79
  312. package/src/ncp/registry.ts +0 -15
  313. package/src/ncp/stream-manager.ts +0 -212
  314. package/src/ndp/dns-txt.ts +0 -86
  315. package/src/ndp/frames.ts +0 -124
  316. package/src/ndp/ndp-registry.ts +0 -116
  317. package/src/ndp/registry.ts +0 -12
  318. package/src/ndp/validator.ts +0 -64
  319. package/src/nip/acme/client.ts +0 -185
  320. package/src/nip/acme/jws.ts +0 -109
  321. package/src/nip/acme/messages.ts +0 -85
  322. package/src/nip/acme/server.ts +0 -480
  323. package/src/nip/acme/wire.ts +0 -24
  324. package/src/nip/assurance-level.ts +0 -40
  325. package/src/nip/cert-format.ts +0 -9
  326. package/src/nip/frames.ts +0 -138
  327. package/src/nip/identity.ts +0 -113
  328. package/src/nip/registry.ts +0 -12
  329. package/src/nip/verifier.ts +0 -122
  330. package/src/nip/x509/builder.ts +0 -91
  331. package/src/nip/x509/verifier.ts +0 -214
  332. package/src/nop/client.ts +0 -103
  333. package/src/nop/frames.ts +0 -181
  334. package/src/nop/models.ts +0 -79
  335. package/src/nop/nop-types.ts +0 -208
  336. package/src/nop/registry.ts +0 -13
  337. package/src/nwp/client.ts +0 -114
  338. package/src/nwp/frames.ts +0 -116
  339. package/src/nwp/registry.ts +0 -11
  340. package/tests/_rfc0002-keys.ts +0 -57
  341. package/tests/core/anchor-cache.test.ts +0 -242
  342. package/tests/core/codec.test.ts +0 -205
  343. package/tests/core/frame-registry.test.ts +0 -46
  344. package/tests/core.test.ts +0 -327
  345. package/tests/ncp/diff-binary-bitset.test.ts +0 -107
  346. package/tests/ncp/e2e-enc-reject.test.ts +0 -93
  347. package/tests/ncp/err-error-frame.test.ts +0 -152
  348. package/tests/ncp/frames.test.ts +0 -359
  349. package/tests/ncp/framing.test.ts +0 -233
  350. package/tests/ncp/hello-frame.test.ts +0 -122
  351. package/tests/ncp/inline-anchor.test.ts +0 -88
  352. package/tests/ncp/preamble.test.ts +0 -93
  353. package/tests/ncp/security.test.ts +0 -184
  354. package/tests/ncp/stream-window.test.ts +0 -167
  355. package/tests/ncp/stream.test.ts +0 -242
  356. package/tests/ncp/version-negotiation.test.ts +0 -123
  357. package/tests/ndp.test.ts +0 -377
  358. package/tests/nip-acme-agent01.test.ts +0 -192
  359. package/tests/nip-x509.test.ts +0 -280
  360. package/tests/nip.test.ts +0 -184
  361. package/tests/nop.test.ts +0 -344
  362. package/tests/nwp.test.ts +0 -237
  363. package/tsconfig.json +0 -20
  364. package/tsup.config.ts +0 -20
  365. 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
- });