@opentdf/sdk 0.1.0-beta.1718 → 0.2.0-beta.1941

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 (321) hide show
  1. package/README.md +45 -38
  2. package/dist/cjs/src/access.js +99 -62
  3. package/dist/cjs/src/auth/auth.js +5 -26
  4. package/dist/cjs/src/auth/oidc-clientcredentials-provider.js +1 -1
  5. package/dist/cjs/src/auth/oidc-externaljwt-provider.js +1 -1
  6. package/dist/cjs/src/auth/oidc-refreshtoken-provider.js +1 -1
  7. package/dist/cjs/src/auth/oidc.js +1 -1
  8. package/dist/cjs/src/auth/providers.js +1 -1
  9. package/dist/cjs/src/concurrency.js +3 -4
  10. package/dist/cjs/src/encodings/base64.js +4 -4
  11. package/dist/cjs/src/encodings/hex.js +5 -6
  12. package/dist/cjs/src/encodings/index.js +18 -8
  13. package/dist/cjs/src/errors.js +1 -1
  14. package/dist/cjs/src/index.js +28 -320
  15. package/dist/cjs/src/nanoclients.js +285 -0
  16. package/dist/cjs/src/nanoindex.js +47 -0
  17. package/dist/cjs/src/nanotdf/Client.js +35 -30
  18. package/dist/cjs/src/nanotdf/NanoTDF.js +1 -1
  19. package/dist/cjs/src/nanotdf/decrypt.js +2 -2
  20. package/dist/cjs/src/nanotdf/encrypt-dataset.js +2 -2
  21. package/dist/cjs/src/nanotdf/encrypt.js +2 -2
  22. package/dist/cjs/src/nanotdf/helpers/calculateByCurve.js +3 -4
  23. package/dist/cjs/src/nanotdf/helpers/getHkdfSalt.js +2 -2
  24. package/dist/cjs/src/nanotdf/models/Ciphers.js +3 -3
  25. package/dist/cjs/src/nanotdf/models/EcCurves.js +3 -3
  26. package/dist/cjs/src/nanotdf/models/Header.js +1 -1
  27. package/dist/cjs/src/nanotdf/models/Payload.js +1 -1
  28. package/dist/cjs/src/nanotdf/models/Policy/AbstractPolicy.js +1 -1
  29. package/dist/cjs/src/nanotdf/models/Policy/EmbeddedPolicy.js +1 -1
  30. package/dist/cjs/src/nanotdf/models/Policy/PolicyFactory.js +1 -1
  31. package/dist/cjs/src/nanotdf/models/ResourceLocator.js +1 -1
  32. package/dist/cjs/src/nanotdf/models/Signature.js +1 -1
  33. package/dist/cjs/src/nanotdf-crypto/ciphers.js +1 -1
  34. package/dist/cjs/src/nanotdf-crypto/decrypt.js +2 -2
  35. package/dist/cjs/src/nanotdf-crypto/digest.js +2 -2
  36. package/dist/cjs/src/nanotdf-crypto/ecdsaSignature.js +4 -5
  37. package/dist/cjs/src/nanotdf-crypto/encrypt.js +2 -2
  38. package/dist/cjs/src/nanotdf-crypto/exportCryptoKey.js +2 -2
  39. package/dist/cjs/src/nanotdf-crypto/generateKeyPair.js +2 -2
  40. package/dist/cjs/src/nanotdf-crypto/generateRandomNumber.js +2 -2
  41. package/dist/cjs/src/nanotdf-crypto/index.js +21 -13
  42. package/dist/cjs/src/nanotdf-crypto/keyAgreement.js +10 -8
  43. package/dist/cjs/src/nanotdf-crypto/pemPublicToCrypto.js +20 -11
  44. package/dist/cjs/src/opentdf.js +243 -0
  45. package/dist/cjs/src/policy/api.js +2 -3
  46. package/dist/cjs/src/policy/granter.js +3 -4
  47. package/dist/cjs/src/seekable.js +157 -0
  48. package/dist/cjs/src/tdf/AttributeObject.js +2 -4
  49. package/dist/cjs/src/tdf/Policy.js +3 -3
  50. package/dist/cjs/src/utils.js +13 -21
  51. package/dist/cjs/src/version.js +7 -3
  52. package/dist/cjs/tdf3/index.js +27 -16
  53. package/dist/cjs/tdf3/src/assertions.js +25 -11
  54. package/dist/cjs/tdf3/src/binary.js +1 -1
  55. package/dist/cjs/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
  56. package/dist/cjs/tdf3/src/ciphers/symmetric-cipher-base.js +1 -1
  57. package/dist/cjs/tdf3/src/client/DecoratedReadableStream.js +7 -74
  58. package/dist/cjs/tdf3/src/client/builders.js +26 -22
  59. package/dist/cjs/tdf3/src/client/index.js +91 -117
  60. package/dist/cjs/tdf3/src/client/validation.js +3 -3
  61. package/dist/cjs/tdf3/src/crypto/crypto-utils.js +1 -1
  62. package/dist/cjs/tdf3/src/crypto/index.js +18 -18
  63. package/dist/cjs/tdf3/src/index.js +22 -11
  64. package/dist/cjs/tdf3/src/models/attribute-set.js +1 -1
  65. package/dist/cjs/tdf3/src/models/encryption-information.js +3 -3
  66. package/dist/cjs/tdf3/src/models/index.js +1 -2
  67. package/dist/cjs/tdf3/src/models/key-access.js +67 -35
  68. package/dist/cjs/tdf3/src/models/policy.js +3 -3
  69. package/dist/cjs/tdf3/src/tdf.js +180 -395
  70. package/dist/cjs/tdf3/src/utils/buffer-crc32.js +2 -3
  71. package/dist/cjs/tdf3/src/utils/index.js +48 -38
  72. package/dist/cjs/tdf3/src/utils/keysplit.js +4 -5
  73. package/dist/cjs/tdf3/src/utils/unwrap.js +21 -0
  74. package/dist/cjs/tdf3/src/utils/zip-reader.js +4 -4
  75. package/dist/cjs/tdf3/src/utils/zip-writer.js +4 -4
  76. package/dist/types/src/access.d.ts +10 -4
  77. package/dist/types/src/access.d.ts.map +1 -1
  78. package/dist/types/src/auth/auth.d.ts +1 -28
  79. package/dist/types/src/auth/auth.d.ts.map +1 -1
  80. package/dist/types/src/auth/providers.d.ts.map +1 -1
  81. package/dist/types/src/index.d.ts +5 -136
  82. package/dist/types/src/index.d.ts.map +1 -1
  83. package/dist/types/src/nanoclients.d.ts +107 -0
  84. package/dist/types/src/nanoclients.d.ts.map +1 -0
  85. package/dist/types/src/nanoindex.d.ts +5 -0
  86. package/dist/types/src/nanoindex.d.ts.map +1 -0
  87. package/dist/types/src/nanotdf/Client.d.ts +1 -13
  88. package/dist/types/src/nanotdf/Client.d.ts.map +1 -1
  89. package/dist/types/src/nanotdf/NanoTDF.d.ts +1 -1
  90. package/dist/types/src/nanotdf/NanoTDF.d.ts.map +1 -1
  91. package/dist/types/src/nanotdf/encrypt-dataset.d.ts +1 -1
  92. package/dist/types/src/nanotdf/encrypt-dataset.d.ts.map +1 -1
  93. package/dist/types/src/nanotdf/encrypt.d.ts +1 -1
  94. package/dist/types/src/nanotdf/encrypt.d.ts.map +1 -1
  95. package/dist/types/src/nanotdf/enum/CipherEnum.d.ts +1 -1
  96. package/dist/types/src/nanotdf/enum/CipherEnum.d.ts.map +1 -1
  97. package/dist/types/src/nanotdf/enum/PolicyTypeEnum.d.ts +1 -1
  98. package/dist/types/src/nanotdf/enum/PolicyTypeEnum.d.ts.map +1 -1
  99. package/dist/types/src/nanotdf/helpers/getHkdfSalt.d.ts +1 -1
  100. package/dist/types/src/nanotdf/helpers/getHkdfSalt.d.ts.map +1 -1
  101. package/dist/types/src/nanotdf/models/DefaultParams.d.ts +1 -1
  102. package/dist/types/src/nanotdf/models/ResourceLocator.d.ts.map +1 -1
  103. package/dist/types/src/nanotdf-crypto/digest.d.ts +1 -1
  104. package/dist/types/src/nanotdf-crypto/digest.d.ts.map +1 -1
  105. package/dist/types/src/nanotdf-crypto/generateKeyPair.d.ts +1 -1
  106. package/dist/types/src/nanotdf-crypto/generateKeyPair.d.ts.map +1 -1
  107. package/dist/types/src/nanotdf-crypto/generateRandomNumber.d.ts +1 -1
  108. package/dist/types/src/nanotdf-crypto/generateRandomNumber.d.ts.map +1 -1
  109. package/dist/types/src/nanotdf-crypto/index.d.ts +2 -3
  110. package/dist/types/src/nanotdf-crypto/index.d.ts.map +1 -1
  111. package/dist/types/src/nanotdf-crypto/keyAgreement.d.ts.map +1 -1
  112. package/dist/types/src/opentdf.d.ts +106 -0
  113. package/dist/types/src/opentdf.d.ts.map +1 -0
  114. package/dist/types/src/seekable.d.ts +39 -0
  115. package/dist/types/src/seekable.d.ts.map +1 -0
  116. package/dist/types/src/tdf/AttributeObject.d.ts +0 -2
  117. package/dist/types/src/tdf/AttributeObject.d.ts.map +1 -1
  118. package/dist/types/src/tdf/NanoTDF/NanoTDF.d.ts +2 -2
  119. package/dist/types/src/tdf/NanoTDF/NanoTDF.d.ts.map +1 -1
  120. package/dist/types/src/tdf/Policy.d.ts +1 -1
  121. package/dist/types/src/tdf/Policy.d.ts.map +1 -1
  122. package/dist/types/src/tdf/PolicyObject.d.ts +1 -2
  123. package/dist/types/src/tdf/PolicyObject.d.ts.map +1 -1
  124. package/dist/types/src/tdf/TypedArray.d.ts +1 -2
  125. package/dist/types/src/tdf/TypedArray.d.ts.map +1 -1
  126. package/dist/types/src/utils.d.ts +1 -3
  127. package/dist/types/src/utils.d.ts.map +1 -1
  128. package/dist/types/src/version.d.ts +5 -1
  129. package/dist/types/src/version.d.ts.map +1 -1
  130. package/dist/types/tdf3/index.d.ts +5 -4
  131. package/dist/types/tdf3/index.d.ts.map +1 -1
  132. package/dist/types/tdf3/src/assertions.d.ts +3 -3
  133. package/dist/types/tdf3/src/assertions.d.ts.map +1 -1
  134. package/dist/types/tdf3/src/client/DecoratedReadableStream.d.ts +2 -15
  135. package/dist/types/tdf3/src/client/DecoratedReadableStream.d.ts.map +1 -1
  136. package/dist/types/tdf3/src/client/builders.d.ts +43 -42
  137. package/dist/types/tdf3/src/client/builders.d.ts.map +1 -1
  138. package/dist/types/tdf3/src/client/index.d.ts +12 -17
  139. package/dist/types/tdf3/src/client/index.d.ts.map +1 -1
  140. package/dist/types/tdf3/src/client/validation.d.ts +3 -3
  141. package/dist/types/tdf3/src/client/validation.d.ts.map +1 -1
  142. package/dist/types/tdf3/src/crypto/crypto-utils.d.ts.map +1 -1
  143. package/dist/types/tdf3/src/index.d.ts +1 -1
  144. package/dist/types/tdf3/src/index.d.ts.map +1 -1
  145. package/dist/types/tdf3/src/models/index.d.ts +0 -1
  146. package/dist/types/tdf3/src/models/index.d.ts.map +1 -1
  147. package/dist/types/tdf3/src/models/key-access.d.ts +63 -15
  148. package/dist/types/tdf3/src/models/key-access.d.ts.map +1 -1
  149. package/dist/types/tdf3/src/models/manifest.d.ts +2 -0
  150. package/dist/types/tdf3/src/models/manifest.d.ts.map +1 -1
  151. package/dist/types/tdf3/src/models/policy.d.ts +0 -1
  152. package/dist/types/tdf3/src/models/policy.d.ts.map +1 -1
  153. package/dist/types/tdf3/src/tdf.d.ts +24 -37
  154. package/dist/types/tdf3/src/tdf.d.ts.map +1 -1
  155. package/dist/types/tdf3/src/utils/index.d.ts +0 -4
  156. package/dist/types/tdf3/src/utils/index.d.ts.map +1 -1
  157. package/dist/types/tdf3/src/utils/unwrap.d.ts +2 -0
  158. package/dist/types/tdf3/src/utils/unwrap.d.ts.map +1 -0
  159. package/dist/types/tdf3/src/utils/zip-reader.d.ts +1 -1
  160. package/dist/types/tdf3/src/utils/zip-reader.d.ts.map +1 -1
  161. package/dist/types/tdf3/src/utils/zip-writer.d.ts +2 -2
  162. package/dist/web/src/access.js +93 -58
  163. package/dist/web/src/auth/auth.js +1 -21
  164. package/dist/web/src/auth/oidc-clientcredentials-provider.js +1 -1
  165. package/dist/web/src/auth/oidc-externaljwt-provider.js +1 -1
  166. package/dist/web/src/auth/oidc-refreshtoken-provider.js +1 -1
  167. package/dist/web/src/auth/oidc.js +1 -1
  168. package/dist/web/src/auth/providers.js +1 -1
  169. package/dist/web/src/concurrency.js +1 -1
  170. package/dist/web/src/encodings/base64.js +1 -1
  171. package/dist/web/src/encodings/hex.js +1 -1
  172. package/dist/web/src/errors.js +1 -1
  173. package/dist/web/src/index.js +6 -312
  174. package/dist/web/src/nanoclients.js +280 -0
  175. package/dist/web/src/nanoindex.js +5 -0
  176. package/dist/web/src/nanotdf/Client.js +18 -23
  177. package/dist/web/src/nanotdf/NanoTDF.js +1 -1
  178. package/dist/web/src/nanotdf/encrypt-dataset.js +1 -1
  179. package/dist/web/src/nanotdf/encrypt.js +1 -1
  180. package/dist/web/src/nanotdf/models/Ciphers.js +1 -1
  181. package/dist/web/src/nanotdf/models/EcCurves.js +1 -1
  182. package/dist/web/src/nanotdf/models/Header.js +1 -1
  183. package/dist/web/src/nanotdf/models/Payload.js +1 -1
  184. package/dist/web/src/nanotdf/models/Policy/AbstractPolicy.js +1 -1
  185. package/dist/web/src/nanotdf/models/Policy/EmbeddedPolicy.js +1 -1
  186. package/dist/web/src/nanotdf/models/Policy/PolicyFactory.js +1 -1
  187. package/dist/web/src/nanotdf/models/ResourceLocator.js +1 -1
  188. package/dist/web/src/nanotdf/models/Signature.js +1 -1
  189. package/dist/web/src/nanotdf-crypto/ciphers.js +1 -1
  190. package/dist/web/src/nanotdf-crypto/ecdsaSignature.js +1 -1
  191. package/dist/web/src/nanotdf-crypto/generateKeyPair.js +2 -2
  192. package/dist/web/src/nanotdf-crypto/generateRandomNumber.js +2 -2
  193. package/dist/web/src/nanotdf-crypto/index.js +3 -4
  194. package/dist/web/src/nanotdf-crypto/keyAgreement.js +9 -6
  195. package/dist/web/src/nanotdf-crypto/pemPublicToCrypto.js +1 -1
  196. package/dist/web/src/opentdf.js +234 -0
  197. package/dist/web/src/policy/api.js +1 -1
  198. package/dist/web/src/policy/granter.js +1 -1
  199. package/dist/web/src/seekable.js +148 -0
  200. package/dist/web/src/tdf/AttributeObject.js +1 -2
  201. package/dist/web/src/tdf/Policy.js +2 -4
  202. package/dist/web/src/utils.js +3 -10
  203. package/dist/web/src/version.js +6 -2
  204. package/dist/web/tdf3/index.js +5 -4
  205. package/dist/web/tdf3/src/assertions.js +21 -6
  206. package/dist/web/tdf3/src/binary.js +1 -1
  207. package/dist/web/tdf3/src/ciphers/aes-gcm-cipher.js +1 -1
  208. package/dist/web/tdf3/src/ciphers/symmetric-cipher-base.js +1 -1
  209. package/dist/web/tdf3/src/client/DecoratedReadableStream.js +4 -68
  210. package/dist/web/tdf3/src/client/builders.js +26 -22
  211. package/dist/web/tdf3/src/client/index.js +74 -105
  212. package/dist/web/tdf3/src/client/validation.js +1 -1
  213. package/dist/web/tdf3/src/crypto/crypto-utils.js +1 -1
  214. package/dist/web/tdf3/src/crypto/index.js +1 -1
  215. package/dist/web/tdf3/src/index.js +2 -2
  216. package/dist/web/tdf3/src/models/attribute-set.js +1 -1
  217. package/dist/web/tdf3/src/models/encryption-information.js +3 -3
  218. package/dist/web/tdf3/src/models/index.js +1 -2
  219. package/dist/web/tdf3/src/models/key-access.js +47 -24
  220. package/dist/web/tdf3/src/models/policy.js +1 -1
  221. package/dist/web/tdf3/src/tdf.js +153 -371
  222. package/dist/web/tdf3/src/utils/buffer-crc32.js +1 -1
  223. package/dist/web/tdf3/src/utils/index.js +19 -14
  224. package/dist/web/tdf3/src/utils/keysplit.js +1 -1
  225. package/dist/web/tdf3/src/utils/unwrap.js +18 -0
  226. package/dist/web/tdf3/src/utils/zip-reader.js +1 -1
  227. package/dist/web/tdf3/src/utils/zip-writer.js +1 -1
  228. package/package.json +45 -45
  229. package/src/access.ts +111 -54
  230. package/src/auth/auth.ts +1 -31
  231. package/src/index.ts +5 -440
  232. package/src/nanoclients.ts +405 -0
  233. package/src/nanoindex.ts +4 -0
  234. package/src/nanotdf/Client.ts +18 -25
  235. package/src/nanotdf/NanoTDF.ts +1 -1
  236. package/src/nanotdf/encrypt-dataset.ts +1 -1
  237. package/src/nanotdf/encrypt.ts +1 -1
  238. package/src/nanotdf/helpers/getHkdfSalt.ts +1 -1
  239. package/src/nanotdf-crypto/digest.ts +1 -1
  240. package/src/nanotdf-crypto/generateKeyPair.ts +1 -1
  241. package/src/nanotdf-crypto/generateRandomNumber.ts +1 -1
  242. package/src/nanotdf-crypto/index.ts +2 -3
  243. package/src/nanotdf-crypto/keyAgreement.ts +14 -7
  244. package/src/opentdf.ts +441 -0
  245. package/src/seekable.ts +180 -0
  246. package/src/tdf/AttributeObject.ts +0 -3
  247. package/src/tdf/Policy.ts +1 -2
  248. package/src/tdf/PolicyObject.ts +1 -2
  249. package/src/tdf/TypedArray.ts +1 -3
  250. package/src/utils.ts +3 -11
  251. package/src/version.ts +6 -1
  252. package/tdf3/index.ts +15 -10
  253. package/tdf3/src/assertions.ts +33 -8
  254. package/tdf3/src/client/DecoratedReadableStream.ts +3 -80
  255. package/tdf3/src/client/builders.ts +44 -28
  256. package/tdf3/src/client/index.ts +109 -165
  257. package/tdf3/src/index.ts +1 -1
  258. package/tdf3/src/models/encryption-information.ts +2 -2
  259. package/tdf3/src/models/index.ts +0 -1
  260. package/tdf3/src/models/key-access.ts +120 -38
  261. package/tdf3/src/models/manifest.ts +3 -0
  262. package/tdf3/src/models/policy.ts +0 -1
  263. package/tdf3/src/tdf.ts +266 -522
  264. package/tdf3/src/utils/index.ts +19 -18
  265. package/tdf3/src/utils/unwrap.ts +17 -0
  266. package/tdf3/src/utils/zip-reader.ts +1 -1
  267. package/dist/cjs/src/auth/Eas.js +0 -60
  268. package/dist/cjs/src/nanotdf-crypto/importRawKey.js +0 -18
  269. package/dist/cjs/src/tdf/Crypto.js +0 -47
  270. package/dist/cjs/src/tdf/EntityObject.js +0 -3
  271. package/dist/cjs/src/tdf/index.js +0 -35
  272. package/dist/cjs/tdf3/src/models/upsert-response.js +0 -3
  273. package/dist/cjs/tdf3/src/templates/default.html.js +0 -98
  274. package/dist/cjs/tdf3/src/templates/escaper.js +0 -15
  275. package/dist/cjs/tdf3/src/templates/index.js +0 -12
  276. package/dist/cjs/tdf3/src/utils/chunkers.js +0 -106
  277. package/dist/cjs/tdf3/src/version.js +0 -6
  278. package/dist/types/src/auth/Eas.d.ts +0 -34
  279. package/dist/types/src/auth/Eas.d.ts.map +0 -1
  280. package/dist/types/src/nanotdf-crypto/importRawKey.d.ts +0 -13
  281. package/dist/types/src/nanotdf-crypto/importRawKey.d.ts.map +0 -1
  282. package/dist/types/src/tdf/Crypto.d.ts +0 -37
  283. package/dist/types/src/tdf/Crypto.d.ts.map +0 -1
  284. package/dist/types/src/tdf/EntityObject.d.ts +0 -18
  285. package/dist/types/src/tdf/EntityObject.d.ts.map +0 -1
  286. package/dist/types/src/tdf/index.d.ts +0 -7
  287. package/dist/types/src/tdf/index.d.ts.map +0 -1
  288. package/dist/types/tdf3/src/models/upsert-response.d.ts +0 -16
  289. package/dist/types/tdf3/src/models/upsert-response.d.ts.map +0 -1
  290. package/dist/types/tdf3/src/templates/default.html.d.ts +0 -8
  291. package/dist/types/tdf3/src/templates/default.html.d.ts.map +0 -1
  292. package/dist/types/tdf3/src/templates/escaper.d.ts +0 -6
  293. package/dist/types/tdf3/src/templates/escaper.d.ts.map +0 -1
  294. package/dist/types/tdf3/src/templates/index.d.ts +0 -3
  295. package/dist/types/tdf3/src/templates/index.d.ts.map +0 -1
  296. package/dist/types/tdf3/src/utils/chunkers.d.ts +0 -29
  297. package/dist/types/tdf3/src/utils/chunkers.d.ts.map +0 -1
  298. package/dist/types/tdf3/src/version.d.ts +0 -3
  299. package/dist/types/tdf3/src/version.d.ts.map +0 -1
  300. package/dist/web/src/auth/Eas.js +0 -55
  301. package/dist/web/src/nanotdf-crypto/importRawKey.js +0 -15
  302. package/dist/web/src/tdf/Crypto.js +0 -44
  303. package/dist/web/src/tdf/EntityObject.js +0 -2
  304. package/dist/web/src/tdf/index.js +0 -4
  305. package/dist/web/tdf3/src/models/upsert-response.js +0 -2
  306. package/dist/web/tdf3/src/templates/default.html.js +0 -96
  307. package/dist/web/tdf3/src/templates/escaper.js +0 -10
  308. package/dist/web/tdf3/src/templates/index.js +0 -3
  309. package/dist/web/tdf3/src/utils/chunkers.js +0 -96
  310. package/dist/web/tdf3/src/version.js +0 -3
  311. package/src/auth/Eas.ts +0 -79
  312. package/src/nanotdf-crypto/importRawKey.ts +0 -19
  313. package/src/tdf/Crypto.ts +0 -42
  314. package/src/tdf/EntityObject.ts +0 -18
  315. package/src/tdf/index.ts +0 -6
  316. package/tdf3/src/models/upsert-response.ts +0 -17
  317. package/tdf3/src/templates/default.html.ts +0 -105
  318. package/tdf3/src/templates/escaper.ts +0 -10
  319. package/tdf3/src/templates/index.ts +0 -2
  320. package/tdf3/src/utils/chunkers.ts +0 -118
  321. package/tdf3/src/version.ts +0 -2
package/tdf3/src/tdf.ts CHANGED
@@ -1,71 +1,59 @@
1
- import axios, { AxiosError } from 'axios';
2
- import { unsigned } from './utils/buffer-crc32.js';
3
1
  import { exportSPKI, importX509 } from 'jose';
4
- import { DecoratedReadableStream } from './client/DecoratedReadableStream.js';
5
- import { EntityObject } from '../../src/tdf/index.js';
6
- import { pemToCryptoPublicKey, validateSecureUrl } from '../../src/utils.js';
7
- import { DecryptParams } from './client/builders.js';
8
- import { AssertionConfig, AssertionKey, AssertionVerificationKeys } from './assertions.js';
9
- import * as assertions from './assertions.js';
10
2
 
11
3
  import {
12
- AttributeSet,
13
- isRemote as isRemoteKeyAccess,
14
- KeyAccessType,
15
- KeyInfo,
16
- Manifest,
17
- Policy,
18
- Remote as KeyAccessRemote,
19
- SplitKey,
20
- UpsertResponse,
21
- Wrapped as KeyAccessWrapped,
22
- KeyAccess,
23
- KeyAccessObject,
24
- SplitType,
25
- } from './models/index.js';
26
- import { base64 } from '../../src/encodings/index.js';
27
- import {
28
- type Chunker,
29
- ZipReader,
30
- ZipWriter,
31
- base64ToBuffer,
32
- isAppIdProviderCheck,
33
- keyMerge,
34
- buffToString,
35
- concatUint8,
36
- } from './utils/index.js';
37
- import { Binary } from './binary.js';
38
- import { KasPublicKeyAlgorithm, KasPublicKeyInfo, OriginAllowList } from '../../src/access.js';
4
+ KasPublicKeyAlgorithm,
5
+ KasPublicKeyInfo,
6
+ OriginAllowList,
7
+ fetchKasPubKey as fetchKasPubKeyV2,
8
+ fetchWrappedKey,
9
+ publicKeyAlgorithmToJwa,
10
+ } from '../../src/access.js';
11
+ import { type AuthProvider, reqSignature } from '../../src/auth/auth.js';
12
+ import { allPool, anyPool } from '../../src/concurrency.js';
13
+ import { base64, hex } from '../../src/encodings/index.js';
39
14
  import {
40
15
  ConfigurationError,
41
16
  DecryptError,
42
17
  InvalidFileError,
43
18
  IntegrityError,
44
19
  NetworkError,
45
- PermissionDeniedError,
46
- ServiceError,
47
- TdfError,
48
- UnauthenticatedError,
49
20
  UnsafeUrlError,
50
21
  UnsupportedFeatureError as UnsupportedError,
51
22
  } from '../../src/errors.js';
52
- import { htmlWrapperTemplate } from './templates/index.js';
53
-
54
- // configurable
55
- // TODO: remove dependencies from ciphers so that we can open-source instead of relying on other Virtru libs
56
- import { AesGcmCipher } from './ciphers/index.js';
23
+ import { generateKeyPair } from '../../src/nanotdf-crypto/generateKeyPair.js';
24
+ import { keyAgreement } from '../../src/nanotdf-crypto/keyAgreement.js';
25
+ import { pemPublicToCrypto } from '../../src/nanotdf-crypto/pemPublicToCrypto.js';
26
+ import { type Chunker } from '../../src/seekable.js';
27
+ import { PolicyObject } from '../../src/tdf/PolicyObject.js';
28
+ import { tdfSpecVersion } from '../../src/version.js';
29
+ import { AssertionConfig, AssertionKey, AssertionVerificationKeys } from './assertions.js';
30
+ import * as assertions from './assertions.js';
31
+ import { Binary } from './binary.js';
32
+ import { AesGcmCipher } from './ciphers/aes-gcm-cipher.js';
33
+ import { SymmetricCipher } from './ciphers/symmetric-cipher-base.js';
34
+ import { DecryptParams } from './client/builders.js';
35
+ import { DecoratedReadableStream } from './client/DecoratedReadableStream.js';
36
+ import {
37
+ AnyKeyPair,
38
+ PemKeyPair,
39
+ type CryptoService,
40
+ type DecryptResult,
41
+ } from './crypto/declarations.js';
57
42
  import {
58
- type AuthProvider,
59
- AppIdAuthProvider,
60
- HttpRequest,
61
- type HttpMethod,
62
- reqSignature,
63
- } from '../../src/auth/auth.js';
64
- import PolicyObject from '../../src/tdf/PolicyObject.js';
65
- import { type CryptoService, type DecryptResult } from './crypto/declarations.js';
43
+ ECWrapped,
44
+ KeyAccessType,
45
+ KeyInfo,
46
+ Manifest,
47
+ Policy,
48
+ SplitKey,
49
+ Wrapped,
50
+ KeyAccess,
51
+ KeyAccessObject,
52
+ SplitType,
53
+ } from './models/index.js';
54
+ import { unsigned } from './utils/buffer-crc32.js';
55
+ import { ZipReader, ZipWriter, keyMerge, concatUint8 } from './utils/index.js';
66
56
  import { CentralDirectory } from './utils/zip-reader.js';
67
- import { SymmetricCipher } from './ciphers/symmetric-cipher-base.js';
68
- import { allPool, anyPool } from '../../src/concurrency.js';
69
57
 
70
58
  // TODO: input validation on manifest JSON
71
59
  const DEFAULT_SEGMENT_SIZE = 1024 * 1024;
@@ -92,20 +80,19 @@ export type Metadata = {
92
80
  };
93
81
 
94
82
  export type BuildKeyAccess = {
95
- attributeSet?: AttributeSet;
96
83
  type: KeyAccessType;
84
+ alg?: KasPublicKeyAlgorithm;
97
85
  url?: string;
98
86
  kid?: string;
99
87
  publicKey: string;
100
- attributeUrl?: string;
101
88
  metadata?: Metadata;
102
89
  sid?: string;
103
90
  };
104
91
 
105
92
  type Segment = {
106
93
  hash: string;
107
- segmentSize: number | undefined;
108
- encryptedSegmentSize: number | undefined;
94
+ segmentSize?: number;
95
+ encryptedSegmentSize?: number;
109
96
  };
110
97
 
111
98
  type EntryInfo = {
@@ -115,20 +102,37 @@ type EntryInfo = {
115
102
  fileByteCount?: number;
116
103
  };
117
104
 
105
+ type Mailbox<T> = Promise<T> & {
106
+ set: (value: T) => void;
107
+ reject: (error: Error) => void;
108
+ };
109
+
110
+ function mailbox<T>(): Mailbox<T> {
111
+ let set: (value: T) => void;
112
+ let reject: (error: Error) => void;
113
+
114
+ const promise = new Promise<T>((resolve, rejectFn) => {
115
+ set = resolve;
116
+ reject = rejectFn;
117
+ }) as Mailbox<T>;
118
+
119
+ promise.set = set!;
120
+ promise.reject = reject!;
121
+
122
+ return promise;
123
+ }
124
+
118
125
  type Chunk = {
119
126
  hash: string;
127
+ plainSegmentSize?: number;
120
128
  encryptedOffset: number;
121
129
  encryptedSegmentSize?: number;
122
- decryptedChunk?: null | DecryptResult;
123
- promise: Promise<unknown>;
124
- _resolve?: (value: unknown) => void;
125
- _reject?: (value: unknown) => void;
130
+ decryptedChunk: Mailbox<DecryptResult>;
126
131
  };
127
132
 
128
133
  export type IntegrityAlgorithm = 'GMAC' | 'HS256';
129
134
 
130
135
  export type EncryptConfiguration = {
131
- allowedKases?: string[];
132
136
  allowList?: OriginAllowList;
133
137
  cryptoService: CryptoService;
134
138
  dpopKeys: CryptoKeyPair;
@@ -139,9 +143,7 @@ export type EncryptConfiguration = {
139
143
  contentStream: ReadableStream<Uint8Array>;
140
144
  mimeType?: string;
141
145
  policy: Policy;
142
- entity?: EntityObject;
143
- attributeSet?: AttributeSet;
144
- authProvider?: AuthProvider | AppIdAuthProvider;
146
+ authProvider?: AuthProvider;
145
147
  byteLimit: number;
146
148
  progressHandler?: (bytesProcessed: number) => void;
147
149
  keyForEncryption: KeyInfo;
@@ -152,9 +154,8 @@ export type EncryptConfiguration = {
152
154
  export type DecryptConfiguration = {
153
155
  allowedKases?: string[];
154
156
  allowList?: OriginAllowList;
155
- authProvider: AuthProvider | AppIdAuthProvider;
157
+ authProvider: AuthProvider;
156
158
  cryptoService: CryptoService;
157
- entity?: EntityObject;
158
159
 
159
160
  dpopKeys: CryptoKeyPair;
160
161
 
@@ -165,13 +166,13 @@ export type DecryptConfiguration = {
165
166
  assertionVerificationKeys?: AssertionVerificationKeys;
166
167
  noVerifyAssertions?: boolean;
167
168
  concurrencyLimit?: number;
169
+ wrappingKeyAlgorithm?: KasPublicKeyAlgorithm;
168
170
  };
169
171
 
170
172
  export type UpsertConfiguration = {
171
173
  allowedKases?: string[];
172
174
  allowList?: OriginAllowList;
173
- authProvider: AuthProvider | AppIdAuthProvider;
174
- entity?: EntityObject;
175
+ authProvider: AuthProvider;
175
176
 
176
177
  privateKey: CryptoKey;
177
178
 
@@ -186,12 +187,6 @@ export type RewrapRequest = {
186
187
 
187
188
  export type KasPublicKeyFormat = 'pkcs8' | 'jwks';
188
189
 
189
- type KasPublicKeyParams = {
190
- algorithm?: KasPublicKeyAlgorithm;
191
- fmt?: KasPublicKeyFormat;
192
- v?: '1' | '2';
193
- };
194
-
195
190
  export type RewrapResponse = {
196
191
  entityWrappedKey: string;
197
192
  sessionPublicKey: string;
@@ -205,148 +200,20 @@ export async function fetchKasPublicKey(
205
200
  kas: string,
206
201
  algorithm?: KasPublicKeyAlgorithm
207
202
  ): Promise<KasPublicKeyInfo> {
208
- if (!kas) {
209
- throw new ConfigurationError('KAS definition not found');
210
- }
211
- // Logs insecure KAS. Secure is enforced in constructor
212
- validateSecureUrl(kas);
213
- const infoStatic = { url: kas, algorithm: algorithm || 'rsa:2048' };
214
- const params: KasPublicKeyParams = {};
215
- if (algorithm) {
216
- params.algorithm = algorithm;
217
- }
218
- const v2Url = `${kas}/v2/kas_public_key`;
219
- try {
220
- const response: { data: string | KasPublicKeyInfo } = await axios.get(v2Url, {
221
- params: {
222
- ...params,
223
- v: '2',
224
- },
225
- });
226
- const publicKey =
227
- typeof response.data === 'string'
228
- ? await extractPemFromKeyString(response.data)
229
- : response.data.publicKey;
230
- return {
231
- publicKey,
232
- key: pemToCryptoPublicKey(publicKey),
233
- ...infoStatic,
234
- ...(typeof response.data !== 'string' && response.data.kid && { kid: response.data.kid }),
235
- };
236
- } catch (cause) {
237
- const status = cause?.response?.status;
238
- switch (status) {
239
- case 400:
240
- case 404:
241
- // KAS does not yet implement v2, maybe
242
- break;
243
- case 401:
244
- throw new UnauthenticatedError(`[${v2Url}] requires auth`, cause);
245
- case 403:
246
- throw new PermissionDeniedError(`[${v2Url}] permission denied`, cause);
247
- default:
248
- if (status && status >= 400 && status < 500) {
249
- throw new ConfigurationError(
250
- `[${v2Url}] request error [${status}] [${cause.name}] [${cause.message}]`,
251
- cause
252
- );
253
- }
254
- throw new NetworkError(
255
- `[${v2Url}] error [${status}] [${cause.name}] [${cause.message}]`,
256
- cause
257
- );
258
- }
259
- }
260
- // Retry with v1 params
261
- const v1Url = `${kas}/kas_public_key`;
262
- try {
263
- const response: { data: string | KasPublicKeyInfo } = await axios.get(v1Url, {
264
- params,
265
- });
266
- const publicKey =
267
- typeof response.data === 'string'
268
- ? await extractPemFromKeyString(response.data)
269
- : response.data.publicKey;
270
- // future proof: allow v2 response even if not specified.
271
- return {
272
- publicKey,
273
- key: pemToCryptoPublicKey(publicKey),
274
- ...infoStatic,
275
- ...(typeof response.data !== 'string' && response.data.kid && { kid: response.data.kid }),
276
- };
277
- } catch (cause) {
278
- const status = cause?.response?.status;
279
- switch (status) {
280
- case 401:
281
- throw new UnauthenticatedError(`[${v1Url}] requires auth`, cause);
282
- case 403:
283
- throw new PermissionDeniedError(`[${v1Url}] permission denied`, cause);
284
- default:
285
- if (status && status >= 400 && status < 500) {
286
- throw new ConfigurationError(
287
- `[${v2Url}] request error [${status}] [${cause.name}] [${cause.message}]`,
288
- cause
289
- );
290
- }
291
- throw new NetworkError(
292
- `[${v1Url}] error [${status}] [${cause.name}] [${cause.message}]`,
293
- cause
294
- );
295
- }
296
- }
203
+ return fetchKasPubKeyV2(kas, algorithm || 'rsa:2048');
297
204
  }
298
- /**
299
- *
300
- * @param payload The TDF content to encode in HTML
301
- * @param manifest A copy of the manifest
302
- * @param transferUrl reader web-service start page
303
- * @return utf-8 encoded HTML data
304
- */
305
- export function wrapHtml(
306
- payload: Uint8Array,
307
- manifest: Manifest | string,
308
- transferUrl: string
309
- ): Uint8Array {
310
- const { origin } = new URL(transferUrl);
311
- const exportManifest: string = typeof manifest === 'string' ? manifest : JSON.stringify(manifest);
312
-
313
- const fullHtmlString = htmlWrapperTemplate({
314
- transferUrl,
315
- transferBaseUrl: origin,
316
- manifest: base64.encode(exportManifest),
317
- payload: buffToString(payload, 'base64'),
318
- });
319
205
 
320
- return new TextEncoder().encode(fullHtmlString);
321
- }
322
-
323
- export function unwrapHtml(htmlPayload: ArrayBuffer | Uint8Array | Binary | string) {
324
- let html;
325
- if (htmlPayload instanceof ArrayBuffer || ArrayBuffer.isView(htmlPayload)) {
326
- html = new TextDecoder().decode(htmlPayload);
327
- } else {
328
- html = htmlPayload.toString();
329
- }
330
- const payloadRe = /<input id=['"]?data-input['"]?[^>]*?value=['"]?([a-zA-Z0-9+/=]+)['"]?/;
331
- const reResult = payloadRe.exec(html);
332
- if (reResult === null) {
333
- throw new InvalidFileError('Payload is missing');
334
- }
335
- const base64Payload = reResult[1];
336
- try {
337
- return base64ToBuffer(base64Payload);
338
- } catch (e) {
339
- throw new InvalidFileError('There was a problem extracting the TDF3 payload', e);
340
- }
341
- }
342
-
343
- export async function extractPemFromKeyString(keyString: string): Promise<string> {
206
+ export async function extractPemFromKeyString(
207
+ keyString: string,
208
+ alg: KasPublicKeyAlgorithm
209
+ ): Promise<string> {
344
210
  let pem: string = keyString;
345
211
 
346
212
  // Skip the public key extraction if we find that the KAS url provides a
347
213
  // PEM-encoded key instead of certificate
348
214
  if (keyString.includes('CERTIFICATE')) {
349
- const cert = await importX509(keyString, 'RS256', { extractable: true });
215
+ const a = publicKeyAlgorithmToJwa(alg);
216
+ const cert = await importX509(keyString, a, { extractable: true });
350
217
  pem = await exportSPKI(cert);
351
218
  }
352
219
 
@@ -360,7 +227,6 @@ export async function extractPemFromKeyString(keyString: string): Promise<string
360
227
  * is missing it throws an error.
361
228
  * @param {Object} options
362
229
  * @param {String} options.type - enum representing how the object key is treated
363
- * @param {String} options.attributeUrl - URL of the attribute to use for pubKey and kasUrl. Omit to use default.
364
230
  * @param {String} options.url - directly set the KAS URL
365
231
  * @param {String} options.publicKey - directly set the (KAS) public key
366
232
  * @param {String?} options.kid - Key identifier of KAS public key
@@ -368,56 +234,40 @@ export async function extractPemFromKeyString(keyString: string): Promise<string
368
234
  * @return {KeyAccess}- the key access object loaded
369
235
  */
370
236
  export async function buildKeyAccess({
371
- attributeSet,
372
237
  type,
373
238
  url,
374
239
  publicKey,
375
240
  kid,
376
- attributeUrl,
377
241
  metadata,
378
242
  sid = '',
243
+ alg = 'rsa:2048',
379
244
  }: BuildKeyAccess): Promise<KeyAccess> {
380
- /** Internal function to keep it DRY */
381
- function createKeyAccess(
382
- type: KeyAccessType,
383
- kasUrl: string,
384
- kasKeyIdentifier: string | undefined,
385
- pubKey: string,
386
- metadata?: Metadata
387
- ) {
388
- switch (type) {
389
- case 'wrapped':
390
- return new KeyAccessWrapped(kasUrl, kasKeyIdentifier, pubKey, metadata, sid);
391
- case 'remote':
392
- return new KeyAccessRemote(kasUrl, kasKeyIdentifier, pubKey, metadata, sid);
393
- default:
394
- throw new ConfigurationError(`buildKeyAccess: Key access type ${type} is unknown`);
395
- }
396
- }
397
-
398
- // If an attributeUrl is provided try to load with that first.
399
- if (attributeUrl && attributeSet) {
400
- const attr = attributeSet.get(attributeUrl);
401
- if (attr && attr.kasUrl && attr.pubKey) {
402
- return createKeyAccess(type, attr.kasUrl, attr.kid, attr.pubKey, metadata);
403
- }
404
- }
405
-
406
245
  // if url and pulicKey are specified load the key access object with them
407
- if (url && publicKey) {
408
- return createKeyAccess(type, url, kid, await extractPemFromKeyString(publicKey), metadata);
246
+ if (!url && !publicKey) {
247
+ throw new ConfigurationError('TDF.buildKeyAccess: No source for kasUrl or pubKey');
248
+ } else if (!url) {
249
+ throw new ConfigurationError('TDF.buildKeyAccess: No kasUrl');
250
+ } else if (!publicKey) {
251
+ throw new ConfigurationError('TDF.buildKeyAccess: No kas public key');
409
252
  }
410
253
 
411
- // Assume the default attribute is the source for kasUrl and pubKey
412
- const defaultAttr = attributeSet?.getDefault();
413
- if (defaultAttr) {
414
- const { pubKey, kasUrl } = defaultAttr;
415
- if (pubKey && kasUrl) {
416
- return createKeyAccess(type, kasUrl, kid, await extractPemFromKeyString(pubKey), metadata);
417
- }
254
+ let pubKey: string;
255
+ try {
256
+ pubKey = await extractPemFromKeyString(publicKey, alg);
257
+ } catch (e) {
258
+ throw new ConfigurationError(
259
+ `TDF.buildKeyAccess: Invalid public key [${publicKey}], caused by [${e}]`,
260
+ e
261
+ );
262
+ }
263
+ switch (type) {
264
+ case 'wrapped':
265
+ return new Wrapped(url, kid, pubKey, metadata, sid);
266
+ case 'ec-wrapped':
267
+ return new ECWrapped(url, kid, pubKey, metadata, sid);
268
+ default:
269
+ throw new ConfigurationError(`buildKeyAccess: Key access type [${type}] is unsupported`);
418
270
  }
419
- // All failed. Raise an error.
420
- throw new ConfigurationError('TDF.buildKeyAccess: No source for kasUrl or pubKey');
421
271
  }
422
272
 
423
273
  export function validatePolicyObject(policy: Policy): void {
@@ -446,7 +296,6 @@ async function _generateManifest(
446
296
  url: '0.payload',
447
297
  protocol: 'zip',
448
298
  isEncrypted: true,
449
- schemaVersion: '3.0.0',
450
299
  ...(mimeType && { mimeType }),
451
300
  };
452
301
 
@@ -457,137 +306,39 @@ async function _generateManifest(
457
306
  // generate the manifest first, then insert integrity information into it
458
307
  encryptionInformation: encryptionInformationStr,
459
308
  assertions: assertions,
309
+ schemaVersion: tdfSpecVersion,
460
310
  };
461
311
  }
462
312
 
463
313
  async function getSignature(
464
- unwrappedKeyBinary: Binary,
465
- payloadBinary: Binary,
466
- algorithmType: IntegrityAlgorithm,
467
- cryptoService: CryptoService
468
- ) {
314
+ unwrappedKey: Uint8Array,
315
+ content: Uint8Array,
316
+ algorithmType: IntegrityAlgorithm
317
+ ): Promise<Uint8Array> {
469
318
  switch (algorithmType.toUpperCase()) {
470
319
  case 'GMAC':
471
320
  // use the auth tag baked into the encrypted payload
472
- return buffToString(Uint8Array.from(payloadBinary.asByteArray()).slice(-16), 'hex');
473
- case 'HS256':
321
+ return content.slice(-16);
322
+ case 'HS256': {
474
323
  // simple hmac is the default
475
- return await cryptoService.hmac(
476
- buffToString(new Uint8Array(unwrappedKeyBinary.asArrayBuffer()), 'hex'),
477
- buffToString(new Uint8Array(payloadBinary.asArrayBuffer()), 'utf-8')
324
+ const cryptoKey = await crypto.subtle.importKey(
325
+ 'raw',
326
+ unwrappedKey,
327
+ {
328
+ name: 'HMAC',
329
+ hash: { name: 'SHA-256' },
330
+ },
331
+ true,
332
+ ['sign', 'verify']
478
333
  );
334
+ const signature = await crypto.subtle.sign('HMAC', cryptoKey, content);
335
+ return new Uint8Array(signature);
336
+ }
479
337
  default:
480
338
  throw new ConfigurationError(`Unsupported signature alg [${algorithmType}]`);
481
339
  }
482
340
  }
483
341
 
484
- function buildRequest(method: HttpMethod, url: string, body?: unknown): HttpRequest {
485
- return {
486
- headers: {},
487
- method: method,
488
- url: url,
489
- body,
490
- };
491
- }
492
-
493
- export async function upsert({
494
- allowedKases,
495
- allowList,
496
- authProvider,
497
- entity,
498
- privateKey,
499
- unsavedManifest,
500
- ignoreType,
501
- }: UpsertConfiguration): Promise<UpsertResponse> {
502
- const allowed = (() => {
503
- if (allowList) {
504
- return allowList;
505
- }
506
- if (!allowedKases) {
507
- throw new ConfigurationError('Upsert cannot be done without allowlist');
508
- }
509
- return new OriginAllowList(allowedKases);
510
- })();
511
- const { keyAccess, policy } = unsavedManifest.encryptionInformation;
512
- const isAppIdProvider = authProvider && isAppIdProviderCheck(authProvider);
513
- if (authProvider === undefined) {
514
- throw new ConfigurationError('Upsert cannot be done without auth provider');
515
- }
516
- return Promise.all(
517
- keyAccess.map(async (keyAccessObject) => {
518
- // We only care about remote key access objects for the policy sync portion
519
- const isRemote = isRemoteKeyAccess(keyAccessObject);
520
- if (!ignoreType && !isRemote) {
521
- return;
522
- }
523
-
524
- if (!allowed.allows(keyAccessObject.url)) {
525
- throw new UnsafeUrlError(`Unexpected KAS url: [${keyAccessObject.url}]`);
526
- }
527
-
528
- const url = `${keyAccessObject.url}/${isAppIdProvider ? '' : 'v2/'}upsert`;
529
-
530
- //TODO I dont' think we need a body at all for KAS requests
531
- // Do we need ANY of this if it's already embedded in the EO in the Bearer OIDC token?
532
- const body: Record<string, unknown> = {
533
- keyAccess: keyAccessObject,
534
- policy: unsavedManifest.encryptionInformation.policy,
535
- entity: isAppIdProviderCheck(authProvider) ? entity : undefined,
536
- authToken: undefined,
537
- clientPayloadSignature: undefined,
538
- };
539
-
540
- if (isAppIdProviderCheck(authProvider)) {
541
- body.authToken = await reqSignature({}, privateKey);
542
- } else {
543
- body.clientPayloadSignature = await reqSignature(body, privateKey);
544
- }
545
- const httpReq = await authProvider.withCreds(buildRequest('POST', url, body));
546
-
547
- try {
548
- const response = await axios.post(httpReq.url, httpReq.body, {
549
- headers: httpReq.headers,
550
- });
551
-
552
- // Remove additional properties which were needed to sync, but not that we want to save to
553
- // the manifest
554
- delete keyAccessObject.wrappedKey;
555
- delete keyAccessObject.encryptedMetadata;
556
- delete keyAccessObject.policyBinding;
557
-
558
- if (isRemote) {
559
- // Decode the policy and extract only the required info to save -- the uuid
560
- const decodedPolicy = JSON.parse(base64.decode(policy));
561
- unsavedManifest.encryptionInformation.policy = base64.encode(
562
- JSON.stringify({ uuid: decodedPolicy.uuid })
563
- );
564
- }
565
- return response.data;
566
- } catch (e) {
567
- if (e.response) {
568
- if (e.response.status >= 500) {
569
- throw new ServiceError('upsert failure', e);
570
- } else if (e.response.status === 403) {
571
- throw new PermissionDeniedError('upsert failure', e);
572
- } else if (e.response.status === 401) {
573
- throw new UnauthenticatedError('upsert auth failure', e);
574
- } else if (e.response.status === 400) {
575
- throw new ConfigurationError('upsert bad request; likely a configuration error', e);
576
- } else {
577
- throw new NetworkError('upsert server error', e);
578
- }
579
- } else if (e.request) {
580
- throw new NetworkError('upsert request failure', e);
581
- }
582
- throw new TdfError(
583
- `Unable to perform upsert operation on the KAS: [${e.name}: ${e.message}], response: [${e?.response?.body}]`,
584
- e
585
- );
586
- }
587
- })
588
- );
589
- }
590
-
591
342
  export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedReadableStream> {
592
343
  if (!cfg.authProvider) {
593
344
  throw new ConfigurationError('No authorization middleware defined');
@@ -616,7 +367,7 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
616
367
  let bytesProcessed = 0;
617
368
  let crcCounter = 0;
618
369
  let fileByteCount = 0;
619
- let aggregateHash = '';
370
+ const segmentHashList: Uint8Array[] = [];
620
371
 
621
372
  const zipWriter = new ZipWriter();
622
373
  const manifest = await _generateManifest(
@@ -630,17 +381,6 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
630
381
  // Set in encrypt; should never be reached.
631
382
  throw new ConfigurationError('internal: please use "loadTDFStream" first to load a manifest.');
632
383
  }
633
- const pkKeyLike = cfg.dpopKeys.privateKey;
634
-
635
- // For all remote key access objects, sync its policy
636
- const upsertResponse = await upsert({
637
- allowedKases: cfg.allowList ? undefined : cfg.allowedKases,
638
- allowList: cfg.allowList,
639
- authProvider: cfg.authProvider,
640
- entity: cfg.entity,
641
- privateKey: pkKeyLike,
642
- unsavedManifest: manifest,
643
- });
644
384
 
645
385
  // determine default segment size by writing empty buffer
646
386
  const { segmentSizeDefault } = cfg;
@@ -720,14 +460,16 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
720
460
  fileByteCount = 0;
721
461
 
722
462
  // hash the concat of all hashes
723
- const payloadSigStr = await getSignature(
724
- cfg.keyForEncryption.unwrappedKeyBinary,
725
- Binary.fromString(aggregateHash),
726
- cfg.integrityAlgorithm,
727
- cfg.cryptoService
463
+ const aggregateHash = await concatenateUint8Array(segmentHashList);
464
+
465
+ const payloadSig = await getSignature(
466
+ new Uint8Array(cfg.keyForEncryption.unwrappedKeyBinary.asArrayBuffer()),
467
+ aggregateHash,
468
+ cfg.integrityAlgorithm
728
469
  );
729
- manifest.encryptionInformation.integrityInformation.rootSignature.sig =
730
- base64.encode(payloadSigStr);
470
+
471
+ const rootSig = base64.encodeArrayBuffer(payloadSig);
472
+ manifest.encryptionInformation.integrityInformation.rootSignature.sig = rootSig;
731
473
  manifest.encryptionInformation.integrityInformation.rootSignature.alg =
732
474
  cfg.integrityAlgorithm;
733
475
 
@@ -803,12 +545,6 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
803
545
  const plaintextStream = new DecoratedReadableStream(underlingSource);
804
546
  plaintextStream.manifest = manifest;
805
547
 
806
- if (upsertResponse) {
807
- plaintextStream.upsertResponse = upsertResponse;
808
- plaintextStream.tdfSize = totalByteCount;
809
- plaintextStream.algorithm = manifest.encryptionInformation.method.algorithm;
810
- }
811
-
812
548
  return plaintextStream;
813
549
 
814
550
  // nested helper fn's
@@ -839,18 +575,16 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
839
575
  cfg.keyForEncryption.unwrappedKeyBinary
840
576
  );
841
577
  const payloadBuffer = new Uint8Array(encryptedResult.payload.asByteArray());
842
- const payloadSigStr = await getSignature(
843
- cfg.keyForEncryption.unwrappedKeyBinary,
844
- encryptedResult.payload,
845
- cfg.segmentIntegrityAlgorithm,
846
- cfg.cryptoService
578
+ const payloadSig = await getSignature(
579
+ new Uint8Array(cfg.keyForEncryption.unwrappedKeyBinary.asArrayBuffer()),
580
+ new Uint8Array(encryptedResult.payload.asArrayBuffer()),
581
+ cfg.segmentIntegrityAlgorithm
847
582
  );
848
583
 
849
- // combined string of all hashes for root signature
850
- aggregateHash += payloadSigStr;
584
+ segmentHashList.push(new Uint8Array(payloadSig));
851
585
 
852
586
  segmentInfos.push({
853
- hash: base64.encode(payloadSigStr),
587
+ hash: base64.encodeArrayBuffer(payloadSig),
854
588
  segmentSize: chunk.length === segmentSizeDefault ? undefined : chunk.length,
855
589
  encryptedSegmentSize:
856
590
  payloadBuffer.length === encryptedSegmentSizeDefault ? undefined : payloadBuffer.length,
@@ -917,31 +651,39 @@ async function unwrapKey({
917
651
  authProvider,
918
652
  dpopKeys,
919
653
  concurrencyLimit,
920
- entity,
921
654
  cryptoService,
655
+ wrappingKeyAlgorithm,
922
656
  }: {
923
657
  manifest: Manifest;
924
658
  allowedKases: OriginAllowList;
925
- authProvider: AuthProvider | AppIdAuthProvider;
659
+ authProvider: AuthProvider;
926
660
  concurrencyLimit?: number;
927
661
  dpopKeys: CryptoKeyPair;
928
- entity: EntityObject | undefined;
929
662
  cryptoService: CryptoService;
663
+ wrappingKeyAlgorithm?: KasPublicKeyAlgorithm;
930
664
  }) {
931
665
  if (authProvider === undefined) {
932
666
  throw new ConfigurationError(
933
- 'upsert requires auth provider; must be configured in client constructor'
667
+ 'rewrap requires auth provider; must be configured in client constructor'
934
668
  );
935
669
  }
936
670
  const { keyAccess } = manifest.encryptionInformation;
937
671
  const splitPotentials = splitLookupTableFactory(keyAccess, allowedKases);
938
- const isAppIdProvider = authProvider && isAppIdProviderCheck(authProvider);
939
672
 
940
673
  async function tryKasRewrap(keySplitInfo: KeyAccessObject): Promise<RewrapResponseData> {
941
- const url = `${keySplitInfo.url}/${isAppIdProvider ? '' : 'v2/'}rewrap`;
942
- const ephemeralEncryptionKeys = await cryptoService.cryptoToPemPair(
943
- await cryptoService.generateKeyPair()
944
- );
674
+ const url = `${keySplitInfo.url}/v2/rewrap`;
675
+ let ephemeralEncryptionKeysRaw: AnyKeyPair;
676
+ let ephemeralEncryptionKeys: PemKeyPair;
677
+ if (wrappingKeyAlgorithm === 'ec:secp256r1') {
678
+ ephemeralEncryptionKeysRaw = await generateKeyPair();
679
+ ephemeralEncryptionKeys = await cryptoService.cryptoToPemPair(ephemeralEncryptionKeysRaw);
680
+ } else if (wrappingKeyAlgorithm === 'rsa:2048' || !wrappingKeyAlgorithm) {
681
+ ephemeralEncryptionKeysRaw = await cryptoService.generateKeyPair();
682
+ ephemeralEncryptionKeys = await cryptoService.cryptoToPemPair(ephemeralEncryptionKeysRaw);
683
+ } else {
684
+ throw new ConfigurationError(`Unsupported wrapping key algorithm [${wrappingKeyAlgorithm}]`);
685
+ }
686
+
945
687
  const clientPublicKey = ephemeralEncryptionKeys.publicKey;
946
688
 
947
689
  const requestBodyStr = JSON.stringify({
@@ -952,33 +694,33 @@ async function unwrapKey({
952
694
  });
953
695
 
954
696
  const jwtPayload = { requestBody: requestBodyStr };
955
- const signedRequestToken = await reqSignature(
956
- isAppIdProvider ? {} : jwtPayload,
957
- dpopKeys.privateKey
697
+ const signedRequestToken = await reqSignature(jwtPayload, dpopKeys.privateKey);
698
+
699
+ const { entityWrappedKey, metadata, sessionPublicKey } = await fetchWrappedKey(
700
+ url,
701
+ { signedRequestToken },
702
+ authProvider,
703
+ '0.0.1'
958
704
  );
959
705
 
960
- let requestBody;
961
- if (isAppIdProvider) {
962
- requestBody = {
963
- keyAccess: keySplitInfo,
964
- policy: manifest.encryptionInformation.policy,
965
- entity: {
966
- ...entity,
967
- publicKey: clientPublicKey,
968
- },
969
- authToken: signedRequestToken,
970
- };
971
- } else {
972
- requestBody = {
973
- signedRequestToken,
706
+ if (wrappingKeyAlgorithm === 'ec:secp256r1') {
707
+ const serverEphemeralKey: CryptoKey = await pemPublicToCrypto(sessionPublicKey);
708
+ const ekr = ephemeralEncryptionKeysRaw as CryptoKeyPair;
709
+ const kek = await keyAgreement(ekr.privateKey, serverEphemeralKey, {
710
+ hkdfSalt: new TextEncoder().encode('salt'),
711
+ hkdfHash: 'SHA-256',
712
+ });
713
+ const wrappedKeyAndNonce = base64.decodeArrayBuffer(entityWrappedKey);
714
+ const iv = wrappedKeyAndNonce.slice(0, 12);
715
+ const wrappedKey = wrappedKeyAndNonce.slice(12);
716
+
717
+ const dek = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, kek, wrappedKey);
718
+
719
+ return {
720
+ key: new Uint8Array(dek),
721
+ metadata,
974
722
  };
975
723
  }
976
-
977
- const httpReq = await authProvider.withCreds(buildRequest('POST', url, requestBody));
978
- const {
979
- data: { entityWrappedKey, metadata },
980
- } = await axios.post(httpReq.url, httpReq.body, { headers: httpReq.headers });
981
-
982
724
  const key = Binary.fromString(base64.decode(entityWrappedKey));
983
725
  const decryptedKeyBinary = await cryptoService.decryptWithPrivateKey(
984
726
  key,
@@ -1010,7 +752,7 @@ async function unwrapKey({
1010
752
  try {
1011
753
  return await tryKasRewrap(keySplitInfo);
1012
754
  } catch (e) {
1013
- throw handleRewrapError(e as Error | AxiosError);
755
+ throw handleRewrapError(e as Error);
1014
756
  }
1015
757
  };
1016
758
  }
@@ -1035,31 +777,11 @@ async function unwrapKey({
1035
777
  }
1036
778
  }
1037
779
 
1038
- function handleRewrapError(error: Error | AxiosError) {
1039
- if (axios.isAxiosError(error)) {
1040
- if (error.response?.status && error.response?.status >= 500) {
1041
- return new ServiceError('rewrap failure', error);
1042
- } else if (error.response?.status === 403) {
1043
- return new PermissionDeniedError('rewrap failure', error);
1044
- } else if (error.response?.status === 401) {
1045
- return new UnauthenticatedError('rewrap auth failure', error);
1046
- } else if (error.response?.status === 400) {
1047
- return new InvalidFileError(
1048
- 'rewrap bad request; could indicate an invalid policy binding or a configuration error',
1049
- error
1050
- );
1051
- } else {
1052
- return new NetworkError('rewrap server error', error);
1053
- }
1054
- } else {
1055
- if (error.name === 'InvalidAccessError' || error.name === 'OperationError') {
1056
- return new DecryptError('unable to unwrap key from kas', error);
1057
- }
1058
- return new InvalidFileError(
1059
- `Unable to decrypt the response from KAS: [${error.name}: ${error.message}]`,
1060
- error
1061
- );
780
+ function handleRewrapError(error: Error) {
781
+ if (error.name === 'InvalidAccessError' || error.name === 'OperationError') {
782
+ return new DecryptError('unable to unwrap key from kas', error);
1062
783
  }
784
+ return error;
1063
785
  }
1064
786
 
1065
787
  async function decryptChunk(
@@ -1068,17 +790,22 @@ async function decryptChunk(
1068
790
  hash: string,
1069
791
  cipher: SymmetricCipher,
1070
792
  segmentIntegrityAlgorithm: IntegrityAlgorithm,
1071
- cryptoService: CryptoService
793
+ isLegacyTDF: boolean
1072
794
  ): Promise<DecryptResult> {
1073
795
  if (segmentIntegrityAlgorithm !== 'GMAC' && segmentIntegrityAlgorithm !== 'HS256') {
796
+ throw new UnsupportedError(`Unsupported integrity alg [${segmentIntegrityAlgorithm}]`);
1074
797
  }
1075
- const segmentHashStr = await getSignature(
1076
- reconstructedKeyBinary,
1077
- Binary.fromArrayBuffer(encryptedChunk.buffer),
1078
- segmentIntegrityAlgorithm,
1079
- cryptoService
798
+ const segmentSig = await getSignature(
799
+ new Uint8Array(reconstructedKeyBinary.asArrayBuffer()),
800
+ encryptedChunk,
801
+ segmentIntegrityAlgorithm
1080
802
  );
1081
- if (hash !== btoa(segmentHashStr)) {
803
+
804
+ const segmentHash = isLegacyTDF
805
+ ? base64.encode(hex.encodeArrayBuffer(segmentSig))
806
+ : base64.encodeArrayBuffer(segmentSig);
807
+
808
+ if (hash !== segmentHash) {
1082
809
  throw new IntegrityError('Failed integrity check on segment hash');
1083
810
  }
1084
811
  return await cipher.decrypt(encryptedChunk, reconstructedKeyBinary);
@@ -1091,7 +818,8 @@ async function updateChunkQueue(
1091
818
  reconstructedKeyBinary: Binary,
1092
819
  cipher: SymmetricCipher,
1093
820
  segmentIntegrityAlgorithm: IntegrityAlgorithm,
1094
- cryptoService: CryptoService
821
+ cryptoService: CryptoService,
822
+ isLegacyTDF: boolean
1095
823
  ) {
1096
824
  const chunksInOneDownload = 500;
1097
825
  let requests = [];
@@ -1132,6 +860,7 @@ async function updateChunkQueue(
1132
860
  slice,
1133
861
  cipher,
1134
862
  segmentIntegrityAlgorithm,
863
+ isLegacyTDF,
1135
864
  });
1136
865
  }
1137
866
  })()
@@ -1144,8 +873,8 @@ export async function sliceAndDecrypt({
1144
873
  reconstructedKeyBinary,
1145
874
  slice,
1146
875
  cipher,
1147
- cryptoService,
1148
876
  segmentIntegrityAlgorithm,
877
+ isLegacyTDF,
1149
878
  }: {
1150
879
  buffer: Uint8Array;
1151
880
  reconstructedKeyBinary: Binary;
@@ -1153,9 +882,10 @@ export async function sliceAndDecrypt({
1153
882
  cipher: SymmetricCipher;
1154
883
  cryptoService: CryptoService;
1155
884
  segmentIntegrityAlgorithm: IntegrityAlgorithm;
885
+ isLegacyTDF: boolean;
1156
886
  }) {
1157
887
  for (const index in slice) {
1158
- const { encryptedOffset, encryptedSegmentSize, _resolve, _reject } = slice[index];
888
+ const { encryptedOffset, encryptedSegmentSize, plainSegmentSize } = slice[index];
1159
889
 
1160
890
  const offset =
1161
891
  slice[0].encryptedOffset === 0 ? encryptedOffset : encryptedOffset % slice[0].encryptedOffset;
@@ -1163,6 +893,10 @@ export async function sliceAndDecrypt({
1163
893
  buffer.slice(offset, offset + (encryptedSegmentSize as number))
1164
894
  );
1165
895
 
896
+ if (encryptedChunk.length !== encryptedSegmentSize) {
897
+ throw new DecryptError('Failed to fetch entire segment');
898
+ }
899
+
1166
900
  try {
1167
901
  const result = await decryptChunk(
1168
902
  encryptedChunk,
@@ -1170,18 +904,16 @@ export async function sliceAndDecrypt({
1170
904
  slice[index]['hash'],
1171
905
  cipher,
1172
906
  segmentIntegrityAlgorithm,
1173
- cryptoService
907
+ isLegacyTDF
1174
908
  );
1175
- slice[index].decryptedChunk = result;
1176
- if (_resolve) {
1177
- _resolve(null);
909
+ if (plainSegmentSize && result.payload.length() !== plainSegmentSize) {
910
+ throw new DecryptError(
911
+ `incorrect segment size: found [${result.payload.length()}], expected [${plainSegmentSize}]`
912
+ );
1178
913
  }
914
+ slice[index].decryptedChunk.set(result);
1179
915
  } catch (e) {
1180
- if (_reject) {
1181
- _reject(e);
1182
- } else {
1183
- throw e;
1184
- }
916
+ slice[index].decryptedChunk.reject(e);
1185
917
  }
1186
918
  }
1187
919
  }
@@ -1204,6 +936,7 @@ export async function readStream(cfg: DecryptConfiguration) {
1204
936
  encryptedSegmentSizeDefault: defaultSegmentSize,
1205
937
  rootSignature,
1206
938
  segmentHashAlg,
939
+ segmentSizeDefault,
1207
940
  segments,
1208
941
  } = manifest.encryptionInformation.integrityInformation;
1209
942
  const { metadata, reconstructedKeyBinary } = await unwrapKey({
@@ -1211,32 +944,34 @@ export async function readStream(cfg: DecryptConfiguration) {
1211
944
  authProvider: cfg.authProvider,
1212
945
  allowedKases: allowList,
1213
946
  dpopKeys: cfg.dpopKeys,
1214
- entity: cfg.entity,
1215
947
  cryptoService: cfg.cryptoService,
1216
948
  });
1217
949
  // async function unwrapKey(manifest: Manifest, allowedKases: string[], authProvider: AuthProvider | AppIdAuthProvider, publicKey: string, privateKey: string, entity: EntityObject) {
1218
950
  const keyForDecryption = await cfg.keyMiddleware(reconstructedKeyBinary);
1219
951
  const encryptedSegmentSizeDefault = defaultSegmentSize || DEFAULT_SEGMENT_SIZE;
1220
952
 
1221
- // check the combined string of hashes
1222
- const aggregateHash = segments.map(({ hash }) => base64.decode(hash)).join('');
953
+ // check if the TDF is a legacy TDF
954
+ const specVersion = manifest.schemaVersion || manifest.tdf_spec_version;
955
+ const isLegacyTDF = !specVersion || specVersion.startsWith('3.');
956
+
957
+ // Decode each hash and store it in an array of Uint8Array
958
+ const segmentHashList = segments.map(
959
+ ({ hash }) => new Uint8Array(base64.decodeArrayBuffer(hash))
960
+ );
961
+
962
+ // Concatenate all segment hashes into a single Uint8Array
963
+ const aggregateHash = await concatenateUint8Array(segmentHashList);
964
+
1223
965
  const integrityAlgorithm = rootSignature.alg;
1224
966
  if (integrityAlgorithm !== 'GMAC' && integrityAlgorithm !== 'HS256') {
1225
967
  throw new UnsupportedError(`Unsupported integrity alg [${integrityAlgorithm}]`);
1226
968
  }
1227
- const payloadSigStr = await getSignature(
1228
- keyForDecryption,
1229
- Binary.fromString(aggregateHash),
1230
- integrityAlgorithm,
1231
- cfg.cryptoService
1232
- );
1233
969
 
1234
- if (
1235
- manifest.encryptionInformation.integrityInformation.rootSignature.sig !==
1236
- base64.encode(payloadSigStr)
1237
- ) {
1238
- throw new IntegrityError('Failed integrity check on root signature');
1239
- }
970
+ const payloadSig = await getSignature(
971
+ new Uint8Array(keyForDecryption.asArrayBuffer()),
972
+ aggregateHash,
973
+ integrityAlgorithm
974
+ );
1240
975
 
1241
976
  if (!cfg.noVerifyAssertions) {
1242
977
  for (const assertion of manifest.assertions || []) {
@@ -1252,31 +987,40 @@ export async function readStream(cfg: DecryptConfiguration) {
1252
987
  assertionKey = foundKey;
1253
988
  }
1254
989
  }
1255
- await assertions.verify(assertion, aggregateHash, assertionKey);
990
+ await assertions.verify(assertion, aggregateHash, assertionKey, isLegacyTDF);
1256
991
  }
1257
992
  }
1258
993
 
994
+ const rootSig = isLegacyTDF
995
+ ? base64.encode(hex.encodeArrayBuffer(payloadSig))
996
+ : base64.encodeArrayBuffer(payloadSig);
997
+
998
+ if (manifest.encryptionInformation.integrityInformation.rootSignature.sig !== rootSig) {
999
+ throw new IntegrityError('Failed integrity check on root signature');
1000
+ }
1001
+
1259
1002
  let mapOfRequestsOffset = 0;
1260
1003
  const chunkMap = new Map(
1261
- segments.map(({ hash, encryptedSegmentSize = encryptedSegmentSizeDefault }) => {
1262
- const result = (() => {
1263
- let _resolve, _reject;
1264
- const chunk: Chunk = {
1265
- hash,
1266
- encryptedOffset: mapOfRequestsOffset,
1267
- encryptedSegmentSize,
1268
- promise: new Promise((resolve, reject) => {
1269
- _resolve = resolve;
1270
- _reject = reject;
1271
- }),
1272
- };
1273
- chunk._resolve = _resolve;
1274
- chunk._reject = _reject;
1275
- return chunk;
1276
- })();
1277
- mapOfRequestsOffset += encryptedSegmentSize || encryptedSegmentSizeDefault;
1278
- return [hash, result];
1279
- })
1004
+ segments.map(
1005
+ ({
1006
+ hash,
1007
+ encryptedSegmentSize = encryptedSegmentSizeDefault,
1008
+ segmentSize = segmentSizeDefault,
1009
+ }) => {
1010
+ const result = (() => {
1011
+ const chunk: Chunk = {
1012
+ hash,
1013
+ encryptedOffset: mapOfRequestsOffset,
1014
+ encryptedSegmentSize,
1015
+ decryptedChunk: mailbox<DecryptResult>(),
1016
+ plainSegmentSize: segmentSize,
1017
+ };
1018
+ return chunk;
1019
+ })();
1020
+ mapOfRequestsOffset += encryptedSegmentSize;
1021
+ return [hash, result];
1022
+ }
1023
+ )
1280
1024
  );
1281
1025
 
1282
1026
  const cipher = new AesGcmCipher(cfg.cryptoService);
@@ -1293,7 +1037,8 @@ export async function readStream(cfg: DecryptConfiguration) {
1293
1037
  keyForDecryption,
1294
1038
  cipher,
1295
1039
  segmentIntegrityAlg,
1296
- cfg.cryptoService
1040
+ cfg.cryptoService,
1041
+ isLegacyTDF
1297
1042
  );
1298
1043
 
1299
1044
  let progress = 0;
@@ -1305,16 +1050,11 @@ export async function readStream(cfg: DecryptConfiguration) {
1305
1050
  }
1306
1051
 
1307
1052
  const [hash, chunk] = chunkMap.entries().next().value;
1308
- if (!chunk.decryptedChunk) {
1309
- await chunk.promise;
1310
- }
1311
- const decryptedSegment = chunk.decryptedChunk;
1053
+ const decryptedSegment = await chunk.decryptedChunk;
1312
1054
 
1313
1055
  controller.enqueue(new Uint8Array(decryptedSegment.payload.asByteArray()));
1314
1056
  progress += chunk.encryptedSegmentSize;
1315
1057
  cfg.progressHandler?.(progress);
1316
-
1317
- chunk.decryptedChunk = null;
1318
1058
  chunkMap.delete(hash);
1319
1059
  },
1320
1060
  ...(cfg.fileStreamServiceWorker && { fileStreamServiceWorker: cfg.fileStreamServiceWorker }),
@@ -1323,8 +1063,12 @@ export async function readStream(cfg: DecryptConfiguration) {
1323
1063
  const outputStream = new DecoratedReadableStream(underlyingSource);
1324
1064
 
1325
1065
  outputStream.manifest = manifest;
1326
- outputStream.emit('manifest', manifest);
1327
1066
  outputStream.metadata = metadata;
1328
- outputStream.emit('rewrap', metadata);
1329
1067
  return outputStream;
1330
1068
  }
1069
+
1070
+ async function concatenateUint8Array(uint8arrays: Uint8Array[]): Promise<Uint8Array> {
1071
+ const blob = new Blob(uint8arrays);
1072
+ const buffer = await blob.arrayBuffer();
1073
+ return new Uint8Array(buffer);
1074
+ }