@opentdf/sdk 0.1.0-beta.1701

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 (566) hide show
  1. package/README.md +52 -0
  2. package/dist/cjs/package.json +3 -0
  3. package/dist/cjs/src/access.js +155 -0
  4. package/dist/cjs/src/auth/Eas.js +60 -0
  5. package/dist/cjs/src/auth/auth.js +79 -0
  6. package/dist/cjs/src/auth/oidc-clientcredentials-provider.js +26 -0
  7. package/dist/cjs/src/auth/oidc-externaljwt-provider.js +33 -0
  8. package/dist/cjs/src/auth/oidc-refreshtoken-provider.js +34 -0
  9. package/dist/cjs/src/auth/oidc.js +222 -0
  10. package/dist/cjs/src/auth/providers.js +143 -0
  11. package/dist/cjs/src/encodings/base64.js +154 -0
  12. package/dist/cjs/src/encodings/hex.js +70 -0
  13. package/dist/cjs/src/encodings/index.js +29 -0
  14. package/dist/cjs/src/errors.js +138 -0
  15. package/dist/cjs/src/index.js +344 -0
  16. package/dist/cjs/src/nanotdf/Client.js +296 -0
  17. package/dist/cjs/src/nanotdf/NanoTDF.js +94 -0
  18. package/dist/cjs/src/nanotdf/browser-entry.js +19 -0
  19. package/dist/cjs/src/nanotdf/constants.js +5 -0
  20. package/dist/cjs/src/nanotdf/decrypt.js +17 -0
  21. package/dist/cjs/src/nanotdf/encrypt-dataset.js +38 -0
  22. package/dist/cjs/src/nanotdf/encrypt.js +132 -0
  23. package/dist/cjs/src/nanotdf/enum/CipherEnum.js +13 -0
  24. package/dist/cjs/src/nanotdf/enum/CurveNameEnum.js +15 -0
  25. package/dist/cjs/src/nanotdf/enum/EncodingEnum.js +8 -0
  26. package/dist/cjs/src/nanotdf/enum/PolicyTypeEnum.js +11 -0
  27. package/dist/cjs/src/nanotdf/enum/ProtocolEnum.js +10 -0
  28. package/dist/cjs/src/nanotdf/enum/ResourceLocatorIdentifierEnum.js +11 -0
  29. package/dist/cjs/src/nanotdf/helpers/calculateByCurve.js +29 -0
  30. package/dist/cjs/src/nanotdf/helpers/getHkdfSalt.js +11 -0
  31. package/dist/cjs/src/nanotdf/index.js +25 -0
  32. package/dist/cjs/src/nanotdf/interfaces/PolicyInterface.js +3 -0
  33. package/dist/cjs/src/nanotdf/models/Ciphers.js +61 -0
  34. package/dist/cjs/src/nanotdf/models/DefaultParams.js +27 -0
  35. package/dist/cjs/src/nanotdf/models/EcCurves.js +39 -0
  36. package/dist/cjs/src/nanotdf/models/Header.js +255 -0
  37. package/dist/cjs/src/nanotdf/models/Payload.js +158 -0
  38. package/dist/cjs/src/nanotdf/models/Policy/AbstractPolicy.js +73 -0
  39. package/dist/cjs/src/nanotdf/models/Policy/EmbeddedPolicy.js +82 -0
  40. package/dist/cjs/src/nanotdf/models/Policy/PolicyFactory.js +38 -0
  41. package/dist/cjs/src/nanotdf/models/Policy/RemotePolicy.js +62 -0
  42. package/dist/cjs/src/nanotdf/models/ResourceLocator.js +211 -0
  43. package/dist/cjs/src/nanotdf/models/Signature.js +77 -0
  44. package/dist/cjs/src/nanotdf-crypto/ciphers.js +17 -0
  45. package/dist/cjs/src/nanotdf-crypto/decrypt.js +24 -0
  46. package/dist/cjs/src/nanotdf-crypto/digest.js +7 -0
  47. package/dist/cjs/src/nanotdf-crypto/ecdsaSignature.js +83 -0
  48. package/dist/cjs/src/nanotdf-crypto/encrypt.js +24 -0
  49. package/dist/cjs/src/nanotdf-crypto/enums.js +52 -0
  50. package/dist/cjs/src/nanotdf-crypto/exportCryptoKey.js +20 -0
  51. package/dist/cjs/src/nanotdf-crypto/generateKeyPair.js +13 -0
  52. package/dist/cjs/src/nanotdf-crypto/generateRandomNumber.js +12 -0
  53. package/dist/cjs/src/nanotdf-crypto/importRawKey.js +18 -0
  54. package/dist/cjs/src/nanotdf-crypto/index.js +52 -0
  55. package/dist/cjs/src/nanotdf-crypto/keyAgreement.js +91 -0
  56. package/dist/cjs/src/nanotdf-crypto/pemPublicToCrypto.js +225 -0
  57. package/dist/cjs/src/policy/api.js +58 -0
  58. package/dist/cjs/src/policy/attributes.js +3 -0
  59. package/dist/cjs/src/policy/granter.js +146 -0
  60. package/dist/cjs/src/tdf/AttributeObject.js +15 -0
  61. package/dist/cjs/src/tdf/AttributeObjectJwt.js +3 -0
  62. package/dist/cjs/src/tdf/Crypto.js +47 -0
  63. package/dist/cjs/src/tdf/EntityObject.js +3 -0
  64. package/dist/cjs/src/tdf/NanoTDF/NanoTDF.js +38 -0
  65. package/dist/cjs/src/tdf/Policy.js +50 -0
  66. package/dist/cjs/src/tdf/PolicyObject.js +3 -0
  67. package/dist/cjs/src/tdf/TypedArray.js +3 -0
  68. package/dist/cjs/src/tdf/index.js +35 -0
  69. package/dist/cjs/src/types/index.js +3 -0
  70. package/dist/cjs/src/utils.js +147 -0
  71. package/dist/cjs/src/version.js +12 -0
  72. package/dist/cjs/tdf3/index.js +57 -0
  73. package/dist/cjs/tdf3/src/assertions.js +118 -0
  74. package/dist/cjs/tdf3/src/binary.js +153 -0
  75. package/dist/cjs/tdf3/src/ciphers/aes-gcm-cipher.js +56 -0
  76. package/dist/cjs/tdf3/src/ciphers/algorithms.js +8 -0
  77. package/dist/cjs/tdf3/src/ciphers/index.js +8 -0
  78. package/dist/cjs/tdf3/src/ciphers/symmetric-cipher-base.js +22 -0
  79. package/dist/cjs/tdf3/src/client/DecoratedReadableStream.js +116 -0
  80. package/dist/cjs/tdf3/src/client/builders.js +561 -0
  81. package/dist/cjs/tdf3/src/client/index.js +460 -0
  82. package/dist/cjs/tdf3/src/client/validation.js +63 -0
  83. package/dist/cjs/tdf3/src/crypto/crypto-utils.js +116 -0
  84. package/dist/cjs/tdf3/src/crypto/declarations.js +8 -0
  85. package/dist/cjs/tdf3/src/crypto/index.js +315 -0
  86. package/dist/cjs/tdf3/src/index.js +34 -0
  87. package/dist/cjs/tdf3/src/models/attribute-set.js +122 -0
  88. package/dist/cjs/tdf3/src/models/encryption-information.js +90 -0
  89. package/dist/cjs/tdf3/src/models/index.js +25 -0
  90. package/dist/cjs/tdf3/src/models/key-access.js +103 -0
  91. package/dist/cjs/tdf3/src/models/manifest.js +3 -0
  92. package/dist/cjs/tdf3/src/models/payload.js +3 -0
  93. package/dist/cjs/tdf3/src/models/policy.js +24 -0
  94. package/dist/cjs/tdf3/src/models/upsert-response.js +3 -0
  95. package/dist/cjs/tdf3/src/tdf.js +907 -0
  96. package/dist/cjs/tdf3/src/templates/default.html.js +98 -0
  97. package/dist/cjs/tdf3/src/templates/escaper.js +15 -0
  98. package/dist/cjs/tdf3/src/templates/index.js +12 -0
  99. package/dist/cjs/tdf3/src/utils/buffer-crc32.js +48 -0
  100. package/dist/cjs/tdf3/src/utils/chunkers.js +106 -0
  101. package/dist/cjs/tdf3/src/utils/index.js +296 -0
  102. package/dist/cjs/tdf3/src/utils/keysplit.js +61 -0
  103. package/dist/cjs/tdf3/src/utils/zip-reader.js +253 -0
  104. package/dist/cjs/tdf3/src/utils/zip-writer.js +308 -0
  105. package/dist/cjs/tdf3/src/version.js +6 -0
  106. package/dist/types/src/access.d.ts +47 -0
  107. package/dist/types/src/access.d.ts.map +1 -0
  108. package/dist/types/src/auth/Eas.d.ts +34 -0
  109. package/dist/types/src/auth/Eas.d.ts.map +1 -0
  110. package/dist/types/src/auth/auth.d.ts +86 -0
  111. package/dist/types/src/auth/auth.d.ts.map +1 -0
  112. package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts +9 -0
  113. package/dist/types/src/auth/oidc-clientcredentials-provider.d.ts.map +1 -0
  114. package/dist/types/src/auth/oidc-externaljwt-provider.d.ts +10 -0
  115. package/dist/types/src/auth/oidc-externaljwt-provider.d.ts.map +1 -0
  116. package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts +10 -0
  117. package/dist/types/src/auth/oidc-refreshtoken-provider.d.ts.map +1 -0
  118. package/dist/types/src/auth/oidc.d.ts +104 -0
  119. package/dist/types/src/auth/oidc.d.ts.map +1 -0
  120. package/dist/types/src/auth/providers.d.ts +67 -0
  121. package/dist/types/src/auth/providers.d.ts.map +1 -0
  122. package/dist/types/src/encodings/base64.d.ts +18 -0
  123. package/dist/types/src/encodings/base64.d.ts.map +1 -0
  124. package/dist/types/src/encodings/hex.d.ts +5 -0
  125. package/dist/types/src/encodings/hex.d.ts.map +1 -0
  126. package/dist/types/src/encodings/index.d.ts +3 -0
  127. package/dist/types/src/encodings/index.d.ts.map +1 -0
  128. package/dist/types/src/errors.d.ts +72 -0
  129. package/dist/types/src/errors.d.ts.map +1 -0
  130. package/dist/types/src/index.d.ts +138 -0
  131. package/dist/types/src/index.d.ts.map +1 -0
  132. package/dist/types/src/nanotdf/Client.d.ts +95 -0
  133. package/dist/types/src/nanotdf/Client.d.ts.map +1 -0
  134. package/dist/types/src/nanotdf/NanoTDF.d.ts +25 -0
  135. package/dist/types/src/nanotdf/NanoTDF.d.ts.map +1 -0
  136. package/dist/types/src/nanotdf/browser-entry.d.ts +17 -0
  137. package/dist/types/src/nanotdf/browser-entry.d.ts.map +1 -0
  138. package/dist/types/src/nanotdf/constants.d.ts +2 -0
  139. package/dist/types/src/nanotdf/constants.d.ts.map +1 -0
  140. package/dist/types/src/nanotdf/decrypt.d.ts +9 -0
  141. package/dist/types/src/nanotdf/decrypt.d.ts.map +1 -0
  142. package/dist/types/src/nanotdf/encrypt-dataset.d.ts +12 -0
  143. package/dist/types/src/nanotdf/encrypt-dataset.d.ts.map +1 -0
  144. package/dist/types/src/nanotdf/encrypt.d.ts +14 -0
  145. package/dist/types/src/nanotdf/encrypt.d.ts.map +1 -0
  146. package/dist/types/src/nanotdf/enum/CipherEnum.d.ts +10 -0
  147. package/dist/types/src/nanotdf/enum/CipherEnum.d.ts.map +1 -0
  148. package/dist/types/src/nanotdf/enum/CurveNameEnum.d.ts +12 -0
  149. package/dist/types/src/nanotdf/enum/CurveNameEnum.d.ts.map +1 -0
  150. package/dist/types/src/nanotdf/enum/EncodingEnum.d.ts +5 -0
  151. package/dist/types/src/nanotdf/enum/EncodingEnum.d.ts.map +1 -0
  152. package/dist/types/src/nanotdf/enum/PolicyTypeEnum.d.ts +8 -0
  153. package/dist/types/src/nanotdf/enum/PolicyTypeEnum.d.ts.map +1 -0
  154. package/dist/types/src/nanotdf/enum/ProtocolEnum.d.ts +7 -0
  155. package/dist/types/src/nanotdf/enum/ProtocolEnum.d.ts.map +1 -0
  156. package/dist/types/src/nanotdf/enum/ResourceLocatorIdentifierEnum.d.ts +8 -0
  157. package/dist/types/src/nanotdf/enum/ResourceLocatorIdentifierEnum.d.ts.map +1 -0
  158. package/dist/types/src/nanotdf/helpers/calculateByCurve.d.ts +20 -0
  159. package/dist/types/src/nanotdf/helpers/calculateByCurve.d.ts.map +1 -0
  160. package/dist/types/src/nanotdf/helpers/getHkdfSalt.d.ts +9 -0
  161. package/dist/types/src/nanotdf/helpers/getHkdfSalt.d.ts.map +1 -0
  162. package/dist/types/src/nanotdf/index.d.ts +9 -0
  163. package/dist/types/src/nanotdf/index.d.ts.map +1 -0
  164. package/dist/types/src/nanotdf/interfaces/PolicyInterface.d.ts +17 -0
  165. package/dist/types/src/nanotdf/interfaces/PolicyInterface.d.ts.map +1 -0
  166. package/dist/types/src/nanotdf/models/Ciphers.d.ts +14 -0
  167. package/dist/types/src/nanotdf/models/Ciphers.d.ts.map +1 -0
  168. package/dist/types/src/nanotdf/models/DefaultParams.d.ts +21 -0
  169. package/dist/types/src/nanotdf/models/DefaultParams.d.ts.map +1 -0
  170. package/dist/types/src/nanotdf/models/EcCurves.d.ts +15 -0
  171. package/dist/types/src/nanotdf/models/EcCurves.d.ts.map +1 -0
  172. package/dist/types/src/nanotdf/models/Header.d.ts +73 -0
  173. package/dist/types/src/nanotdf/models/Header.d.ts.map +1 -0
  174. package/dist/types/src/nanotdf/models/Payload.d.ts +47 -0
  175. package/dist/types/src/nanotdf/models/Payload.d.ts.map +1 -0
  176. package/dist/types/src/nanotdf/models/Policy/AbstractPolicy.d.ts +52 -0
  177. package/dist/types/src/nanotdf/models/Policy/AbstractPolicy.d.ts.map +1 -0
  178. package/dist/types/src/nanotdf/models/Policy/EmbeddedPolicy.d.ts +35 -0
  179. package/dist/types/src/nanotdf/models/Policy/EmbeddedPolicy.d.ts.map +1 -0
  180. package/dist/types/src/nanotdf/models/Policy/PolicyFactory.d.ts +11 -0
  181. package/dist/types/src/nanotdf/models/Policy/PolicyFactory.d.ts.map +1 -0
  182. package/dist/types/src/nanotdf/models/Policy/RemotePolicy.d.ts +31 -0
  183. package/dist/types/src/nanotdf/models/Policy/RemotePolicy.d.ts.map +1 -0
  184. package/dist/types/src/nanotdf/models/ResourceLocator.d.ts +65 -0
  185. package/dist/types/src/nanotdf/models/ResourceLocator.d.ts.map +1 -0
  186. package/dist/types/src/nanotdf/models/Signature.d.ts +33 -0
  187. package/dist/types/src/nanotdf/models/Signature.d.ts.map +1 -0
  188. package/dist/types/src/nanotdf-crypto/ciphers.d.ts +8 -0
  189. package/dist/types/src/nanotdf-crypto/ciphers.d.ts.map +1 -0
  190. package/dist/types/src/nanotdf-crypto/decrypt.d.ts +14 -0
  191. package/dist/types/src/nanotdf-crypto/decrypt.d.ts.map +1 -0
  192. package/dist/types/src/nanotdf-crypto/digest.d.ts +3 -0
  193. package/dist/types/src/nanotdf-crypto/digest.d.ts.map +1 -0
  194. package/dist/types/src/nanotdf-crypto/ecdsaSignature.d.ts +35 -0
  195. package/dist/types/src/nanotdf-crypto/ecdsaSignature.d.ts.map +1 -0
  196. package/dist/types/src/nanotdf-crypto/encrypt.d.ts +14 -0
  197. package/dist/types/src/nanotdf-crypto/encrypt.d.ts.map +1 -0
  198. package/dist/types/src/nanotdf-crypto/enums.d.ts +42 -0
  199. package/dist/types/src/nanotdf-crypto/enums.d.ts.map +1 -0
  200. package/dist/types/src/nanotdf-crypto/exportCryptoKey.d.ts +7 -0
  201. package/dist/types/src/nanotdf-crypto/exportCryptoKey.d.ts.map +1 -0
  202. package/dist/types/src/nanotdf-crypto/generateKeyPair.d.ts +10 -0
  203. package/dist/types/src/nanotdf-crypto/generateKeyPair.d.ts.map +1 -0
  204. package/dist/types/src/nanotdf-crypto/generateRandomNumber.d.ts +5 -0
  205. package/dist/types/src/nanotdf-crypto/generateRandomNumber.d.ts.map +1 -0
  206. package/dist/types/src/nanotdf-crypto/importRawKey.d.ts +13 -0
  207. package/dist/types/src/nanotdf-crypto/importRawKey.d.ts.map +1 -0
  208. package/dist/types/src/nanotdf-crypto/index.d.ts +12 -0
  209. package/dist/types/src/nanotdf-crypto/index.d.ts.map +1 -0
  210. package/dist/types/src/nanotdf-crypto/keyAgreement.d.ts +28 -0
  211. package/dist/types/src/nanotdf-crypto/keyAgreement.d.ts.map +1 -0
  212. package/dist/types/src/nanotdf-crypto/pemPublicToCrypto.d.ts +28 -0
  213. package/dist/types/src/nanotdf-crypto/pemPublicToCrypto.d.ts.map +1 -0
  214. package/dist/types/src/policy/api.d.ts +4 -0
  215. package/dist/types/src/policy/api.d.ts.map +1 -0
  216. package/dist/types/src/policy/attributes.d.ts +95 -0
  217. package/dist/types/src/policy/attributes.d.ts.map +1 -0
  218. package/dist/types/src/policy/granter.d.ts +23 -0
  219. package/dist/types/src/policy/granter.d.ts.map +1 -0
  220. package/dist/types/src/tdf/AttributeObject.d.ts +13 -0
  221. package/dist/types/src/tdf/AttributeObject.d.ts.map +1 -0
  222. package/dist/types/src/tdf/AttributeObjectJwt.d.ts +4 -0
  223. package/dist/types/src/tdf/AttributeObjectJwt.d.ts.map +1 -0
  224. package/dist/types/src/tdf/Crypto.d.ts +37 -0
  225. package/dist/types/src/tdf/Crypto.d.ts.map +1 -0
  226. package/dist/types/src/tdf/EntityObject.d.ts +18 -0
  227. package/dist/types/src/tdf/EntityObject.d.ts.map +1 -0
  228. package/dist/types/src/tdf/NanoTDF/NanoTDF.d.ts +99 -0
  229. package/dist/types/src/tdf/NanoTDF/NanoTDF.d.ts.map +1 -0
  230. package/dist/types/src/tdf/Policy.d.ts +28 -0
  231. package/dist/types/src/tdf/Policy.d.ts.map +1 -0
  232. package/dist/types/src/tdf/PolicyObject.d.ts +11 -0
  233. package/dist/types/src/tdf/PolicyObject.d.ts.map +1 -0
  234. package/dist/types/src/tdf/TypedArray.d.ts +3 -0
  235. package/dist/types/src/tdf/TypedArray.d.ts.map +1 -0
  236. package/dist/types/src/tdf/index.d.ts +7 -0
  237. package/dist/types/src/tdf/index.d.ts.map +1 -0
  238. package/dist/types/src/types/index.d.ts +45 -0
  239. package/dist/types/src/types/index.d.ts.map +1 -0
  240. package/dist/types/src/utils.d.ts +45 -0
  241. package/dist/types/src/utils.d.ts.map +1 -0
  242. package/dist/types/src/version.d.ts +9 -0
  243. package/dist/types/src/version.d.ts.map +1 -0
  244. package/dist/types/tdf3/index.d.ts +16 -0
  245. package/dist/types/tdf3/index.d.ts.map +1 -0
  246. package/dist/types/tdf3/src/assertions.d.ts +63 -0
  247. package/dist/types/tdf3/src/assertions.d.ts.map +1 -0
  248. package/dist/types/tdf3/src/binary.d.ts +38 -0
  249. package/dist/types/tdf3/src/binary.d.ts.map +1 -0
  250. package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts +18 -0
  251. package/dist/types/tdf3/src/ciphers/aes-gcm-cipher.d.ts.map +1 -0
  252. package/dist/types/tdf3/src/ciphers/algorithms.d.ts +4 -0
  253. package/dist/types/tdf3/src/ciphers/algorithms.d.ts.map +1 -0
  254. package/dist/types/tdf3/src/ciphers/index.d.ts +3 -0
  255. package/dist/types/tdf3/src/ciphers/index.d.ts.map +1 -0
  256. package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts +14 -0
  257. package/dist/types/tdf3/src/ciphers/symmetric-cipher-base.d.ts.map +1 -0
  258. package/dist/types/tdf3/src/client/DecoratedReadableStream.d.ts +53 -0
  259. package/dist/types/tdf3/src/client/DecoratedReadableStream.d.ts.map +1 -0
  260. package/dist/types/tdf3/src/client/builders.d.ts +436 -0
  261. package/dist/types/tdf3/src/client/builders.d.ts.map +1 -0
  262. package/dist/types/tdf3/src/client/index.d.ts +139 -0
  263. package/dist/types/tdf3/src/client/index.d.ts.map +1 -0
  264. package/dist/types/tdf3/src/client/validation.d.ts +8 -0
  265. package/dist/types/tdf3/src/client/validation.d.ts.map +1 -0
  266. package/dist/types/tdf3/src/crypto/crypto-utils.d.ts +34 -0
  267. package/dist/types/tdf3/src/crypto/crypto-utils.d.ts.map +1 -0
  268. package/dist/types/tdf3/src/crypto/declarations.d.ts +60 -0
  269. package/dist/types/tdf3/src/crypto/declarations.d.ts.map +1 -0
  270. package/dist/types/tdf3/src/crypto/index.d.ts +103 -0
  271. package/dist/types/tdf3/src/crypto/index.d.ts.map +1 -0
  272. package/dist/types/tdf3/src/index.d.ts +5 -0
  273. package/dist/types/tdf3/src/index.d.ts.map +1 -0
  274. package/dist/types/tdf3/src/models/attribute-set.d.ts +65 -0
  275. package/dist/types/tdf3/src/models/attribute-set.d.ts.map +1 -0
  276. package/dist/types/tdf3/src/models/encryption-information.d.ts +49 -0
  277. package/dist/types/tdf3/src/models/encryption-information.d.ts.map +1 -0
  278. package/dist/types/tdf3/src/models/index.d.ts +9 -0
  279. package/dist/types/tdf3/src/models/index.d.ts.map +1 -0
  280. package/dist/types/tdf3/src/models/key-access.d.ts +42 -0
  281. package/dist/types/tdf3/src/models/key-access.d.ts.map +1 -0
  282. package/dist/types/tdf3/src/models/manifest.d.ts +9 -0
  283. package/dist/types/tdf3/src/models/manifest.d.ts.map +1 -0
  284. package/dist/types/tdf3/src/models/payload.d.ts +7 -0
  285. package/dist/types/tdf3/src/models/payload.d.ts.map +1 -0
  286. package/dist/types/tdf3/src/models/policy.d.ts +13 -0
  287. package/dist/types/tdf3/src/models/policy.d.ts.map +1 -0
  288. package/dist/types/tdf3/src/models/upsert-response.d.ts +16 -0
  289. package/dist/types/tdf3/src/models/upsert-response.d.ts.map +1 -0
  290. package/dist/types/tdf3/src/tdf.d.ts +152 -0
  291. package/dist/types/tdf3/src/tdf.d.ts.map +1 -0
  292. package/dist/types/tdf3/src/templates/default.html.d.ts +8 -0
  293. package/dist/types/tdf3/src/templates/default.html.d.ts.map +1 -0
  294. package/dist/types/tdf3/src/templates/escaper.d.ts +6 -0
  295. package/dist/types/tdf3/src/templates/escaper.d.ts.map +1 -0
  296. package/dist/types/tdf3/src/templates/index.d.ts +3 -0
  297. package/dist/types/tdf3/src/templates/index.d.ts.map +1 -0
  298. package/dist/types/tdf3/src/utils/buffer-crc32.d.ts +2 -0
  299. package/dist/types/tdf3/src/utils/buffer-crc32.d.ts.map +1 -0
  300. package/dist/types/tdf3/src/utils/chunkers.d.ts +29 -0
  301. package/dist/types/tdf3/src/utils/chunkers.d.ts.map +1 -0
  302. package/dist/types/tdf3/src/utils/index.d.ts +36 -0
  303. package/dist/types/tdf3/src/utils/index.d.ts.map +1 -0
  304. package/dist/types/tdf3/src/utils/keysplit.d.ts +19 -0
  305. package/dist/types/tdf3/src/utils/keysplit.d.ts.map +1 -0
  306. package/dist/types/tdf3/src/utils/zip-reader.d.ts +63 -0
  307. package/dist/types/tdf3/src/utils/zip-reader.d.ts.map +1 -0
  308. package/dist/types/tdf3/src/utils/zip-writer.d.ts +35 -0
  309. package/dist/types/tdf3/src/utils/zip-writer.d.ts.map +1 -0
  310. package/dist/types/tdf3/src/version.d.ts +3 -0
  311. package/dist/types/tdf3/src/version.d.ts.map +1 -0
  312. package/dist/web/package.json +3 -0
  313. package/dist/web/src/access.js +147 -0
  314. package/dist/web/src/auth/Eas.js +55 -0
  315. package/dist/web/src/auth/auth.js +71 -0
  316. package/dist/web/src/auth/oidc-clientcredentials-provider.js +22 -0
  317. package/dist/web/src/auth/oidc-externaljwt-provider.js +29 -0
  318. package/dist/web/src/auth/oidc-refreshtoken-provider.js +30 -0
  319. package/dist/web/src/auth/oidc.js +215 -0
  320. package/dist/web/src/auth/providers.js +119 -0
  321. package/dist/web/src/encodings/base64.js +147 -0
  322. package/dist/web/src/encodings/hex.js +63 -0
  323. package/dist/web/src/encodings/index.js +3 -0
  324. package/dist/web/src/errors.js +123 -0
  325. package/dist/web/src/index.js +313 -0
  326. package/dist/web/src/nanotdf/Client.js +268 -0
  327. package/dist/web/src/nanotdf/NanoTDF.js +89 -0
  328. package/dist/web/src/nanotdf/browser-entry.js +14 -0
  329. package/dist/web/src/nanotdf/constants.js +2 -0
  330. package/dist/web/src/nanotdf/decrypt.js +14 -0
  331. package/dist/web/src/nanotdf/encrypt-dataset.js +32 -0
  332. package/dist/web/src/nanotdf/encrypt.js +126 -0
  333. package/dist/web/src/nanotdf/enum/CipherEnum.js +11 -0
  334. package/dist/web/src/nanotdf/enum/CurveNameEnum.js +13 -0
  335. package/dist/web/src/nanotdf/enum/EncodingEnum.js +6 -0
  336. package/dist/web/src/nanotdf/enum/PolicyTypeEnum.js +9 -0
  337. package/dist/web/src/nanotdf/enum/ProtocolEnum.js +8 -0
  338. package/dist/web/src/nanotdf/enum/ResourceLocatorIdentifierEnum.js +9 -0
  339. package/dist/web/src/nanotdf/helpers/calculateByCurve.js +24 -0
  340. package/dist/web/src/nanotdf/helpers/getHkdfSalt.js +8 -0
  341. package/dist/web/src/nanotdf/index.js +11 -0
  342. package/dist/web/src/nanotdf/interfaces/PolicyInterface.js +2 -0
  343. package/dist/web/src/nanotdf/models/Ciphers.js +54 -0
  344. package/dist/web/src/nanotdf/models/DefaultParams.js +22 -0
  345. package/dist/web/src/nanotdf/models/EcCurves.js +32 -0
  346. package/dist/web/src/nanotdf/models/Header.js +250 -0
  347. package/dist/web/src/nanotdf/models/Payload.js +156 -0
  348. package/dist/web/src/nanotdf/models/Policy/AbstractPolicy.js +71 -0
  349. package/dist/web/src/nanotdf/models/Policy/EmbeddedPolicy.js +77 -0
  350. package/dist/web/src/nanotdf/models/Policy/PolicyFactory.js +33 -0
  351. package/dist/web/src/nanotdf/models/Policy/RemotePolicy.js +57 -0
  352. package/dist/web/src/nanotdf/models/ResourceLocator.js +206 -0
  353. package/dist/web/src/nanotdf/models/Signature.js +74 -0
  354. package/dist/web/src/nanotdf-crypto/ciphers.js +14 -0
  355. package/dist/web/src/nanotdf-crypto/decrypt.js +21 -0
  356. package/dist/web/src/nanotdf-crypto/digest.js +4 -0
  357. package/dist/web/src/nanotdf-crypto/ecdsaSignature.js +77 -0
  358. package/dist/web/src/nanotdf-crypto/encrypt.js +21 -0
  359. package/dist/web/src/nanotdf-crypto/enums.js +49 -0
  360. package/dist/web/src/nanotdf-crypto/exportCryptoKey.js +17 -0
  361. package/dist/web/src/nanotdf-crypto/generateKeyPair.js +10 -0
  362. package/dist/web/src/nanotdf-crypto/generateRandomNumber.js +9 -0
  363. package/dist/web/src/nanotdf-crypto/importRawKey.js +15 -0
  364. package/dist/web/src/nanotdf-crypto/index.js +12 -0
  365. package/dist/web/src/nanotdf-crypto/keyAgreement.js +87 -0
  366. package/dist/web/src/nanotdf-crypto/pemPublicToCrypto.js +197 -0
  367. package/dist/web/src/policy/api.js +54 -0
  368. package/dist/web/src/policy/attributes.js +2 -0
  369. package/dist/web/src/policy/granter.js +141 -0
  370. package/dist/web/src/tdf/AttributeObject.js +11 -0
  371. package/dist/web/src/tdf/AttributeObjectJwt.js +2 -0
  372. package/dist/web/src/tdf/Crypto.js +44 -0
  373. package/dist/web/src/tdf/EntityObject.js +2 -0
  374. package/dist/web/src/tdf/NanoTDF/NanoTDF.js +35 -0
  375. package/dist/web/src/tdf/Policy.js +48 -0
  376. package/dist/web/src/tdf/PolicyObject.js +2 -0
  377. package/dist/web/src/tdf/TypedArray.js +2 -0
  378. package/dist/web/src/tdf/index.js +4 -0
  379. package/dist/web/src/types/index.js +2 -0
  380. package/dist/web/src/utils.js +133 -0
  381. package/dist/web/src/version.js +9 -0
  382. package/dist/web/tdf3/index.js +13 -0
  383. package/dist/web/tdf3/src/assertions.js +111 -0
  384. package/dist/web/tdf3/src/binary.js +149 -0
  385. package/dist/web/tdf3/src/ciphers/aes-gcm-cipher.js +52 -0
  386. package/dist/web/tdf3/src/ciphers/algorithms.js +5 -0
  387. package/dist/web/tdf3/src/ciphers/index.js +3 -0
  388. package/dist/web/tdf3/src/ciphers/symmetric-cipher-base.js +18 -0
  389. package/dist/web/tdf3/src/client/DecoratedReadableStream.js +107 -0
  390. package/dist/web/tdf3/src/client/builders.js +557 -0
  391. package/dist/web/tdf3/src/client/index.js +423 -0
  392. package/dist/web/tdf3/src/client/validation.js +58 -0
  393. package/dist/web/tdf3/src/crypto/crypto-utils.js +107 -0
  394. package/dist/web/tdf3/src/crypto/declarations.js +5 -0
  395. package/dist/web/tdf3/src/crypto/index.js +296 -0
  396. package/dist/web/tdf3/src/index.js +5 -0
  397. package/dist/web/tdf3/src/models/attribute-set.js +118 -0
  398. package/dist/web/tdf3/src/models/encryption-information.js +86 -0
  399. package/dist/web/tdf3/src/models/index.js +9 -0
  400. package/dist/web/tdf3/src/models/key-access.js +74 -0
  401. package/dist/web/tdf3/src/models/manifest.js +2 -0
  402. package/dist/web/tdf3/src/models/payload.js +2 -0
  403. package/dist/web/tdf3/src/models/policy.js +20 -0
  404. package/dist/web/tdf3/src/models/upsert-response.js +2 -0
  405. package/dist/web/tdf3/src/tdf.js +866 -0
  406. package/dist/web/tdf3/src/templates/default.html.js +96 -0
  407. package/dist/web/tdf3/src/templates/escaper.js +10 -0
  408. package/dist/web/tdf3/src/templates/index.js +3 -0
  409. package/dist/web/tdf3/src/utils/buffer-crc32.js +44 -0
  410. package/dist/web/tdf3/src/utils/chunkers.js +96 -0
  411. package/dist/web/tdf3/src/utils/index.js +248 -0
  412. package/dist/web/tdf3/src/utils/keysplit.js +55 -0
  413. package/dist/web/tdf3/src/utils/zip-reader.js +247 -0
  414. package/dist/web/tdf3/src/utils/zip-writer.js +302 -0
  415. package/dist/web/tdf3/src/version.js +3 -0
  416. package/package.json +126 -0
  417. package/src/access.ts +198 -0
  418. package/src/auth/Eas.ts +79 -0
  419. package/src/auth/auth.ts +141 -0
  420. package/src/auth/oidc-clientcredentials-provider.ts +32 -0
  421. package/src/auth/oidc-externaljwt-provider.ts +41 -0
  422. package/src/auth/oidc-refreshtoken-provider.ts +41 -0
  423. package/src/auth/oidc.ts +307 -0
  424. package/src/auth/providers.ts +139 -0
  425. package/src/encodings/base64.ts +160 -0
  426. package/src/encodings/hex.ts +69 -0
  427. package/src/encodings/index.ts +2 -0
  428. package/src/errors.ts +113 -0
  429. package/src/index.ts +441 -0
  430. package/src/nanotdf/Client.ts +349 -0
  431. package/src/nanotdf/NanoTDF.ts +121 -0
  432. package/src/nanotdf/browser-entry.ts +20 -0
  433. package/src/nanotdf/constants.ts +1 -0
  434. package/src/nanotdf/decrypt.ts +19 -0
  435. package/src/nanotdf/encrypt-dataset.ts +52 -0
  436. package/src/nanotdf/encrypt.ts +197 -0
  437. package/src/nanotdf/enum/CipherEnum.ts +10 -0
  438. package/src/nanotdf/enum/CurveNameEnum.ts +12 -0
  439. package/src/nanotdf/enum/EncodingEnum.ts +5 -0
  440. package/src/nanotdf/enum/PolicyTypeEnum.ts +8 -0
  441. package/src/nanotdf/enum/ProtocolEnum.ts +7 -0
  442. package/src/nanotdf/enum/ResourceLocatorIdentifierEnum.ts +8 -0
  443. package/src/nanotdf/helpers/calculateByCurve.ts +26 -0
  444. package/src/nanotdf/helpers/getHkdfSalt.ts +15 -0
  445. package/src/nanotdf/index.ts +10 -0
  446. package/src/nanotdf/interfaces/PolicyInterface.ts +27 -0
  447. package/src/nanotdf/models/Ciphers.ts +67 -0
  448. package/src/nanotdf/models/DefaultParams.ts +24 -0
  449. package/src/nanotdf/models/EcCurves.ts +40 -0
  450. package/src/nanotdf/models/Header.ts +322 -0
  451. package/src/nanotdf/models/Payload.ts +196 -0
  452. package/src/nanotdf/models/Policy/AbstractPolicy.ts +90 -0
  453. package/src/nanotdf/models/Policy/EmbeddedPolicy.ts +101 -0
  454. package/src/nanotdf/models/Policy/PolicyFactory.ts +48 -0
  455. package/src/nanotdf/models/Policy/RemotePolicy.ts +74 -0
  456. package/src/nanotdf/models/ResourceLocator.ts +212 -0
  457. package/src/nanotdf/models/Signature.ts +85 -0
  458. package/src/nanotdf-crypto/ciphers.ts +13 -0
  459. package/src/nanotdf-crypto/decrypt.ts +30 -0
  460. package/src/nanotdf-crypto/digest.ts +8 -0
  461. package/src/nanotdf-crypto/ecdsaSignature.ts +109 -0
  462. package/src/nanotdf-crypto/encrypt.ts +30 -0
  463. package/src/nanotdf-crypto/enums.ts +47 -0
  464. package/src/nanotdf-crypto/exportCryptoKey.ts +17 -0
  465. package/src/nanotdf-crypto/generateKeyPair.ts +19 -0
  466. package/src/nanotdf-crypto/generateRandomNumber.ts +8 -0
  467. package/src/nanotdf-crypto/importRawKey.ts +19 -0
  468. package/src/nanotdf-crypto/index.ts +11 -0
  469. package/src/nanotdf-crypto/keyAgreement.ts +139 -0
  470. package/src/nanotdf-crypto/pemPublicToCrypto.ts +232 -0
  471. package/src/package-lock.json +6 -0
  472. package/src/package.json +3 -0
  473. package/src/platform/authorization/authorization_connect.d.ts +44 -0
  474. package/src/platform/authorization/authorization_connect.js +44 -0
  475. package/src/platform/authorization/authorization_pb.d.ts +707 -0
  476. package/src/platform/authorization/authorization_pb.js +372 -0
  477. package/src/platform/common/common_pb.d.ts +129 -0
  478. package/src/platform/common/common_pb.js +58 -0
  479. package/src/platform/entityresolution/entity_resolution_connect.d.ts +35 -0
  480. package/src/platform/entityresolution/entity_resolution_connect.js +35 -0
  481. package/src/platform/entityresolution/entity_resolution_pb.d.ts +242 -0
  482. package/src/platform/entityresolution/entity_resolution_pb.js +139 -0
  483. package/src/platform/kas/kas_connect.d.ts +59 -0
  484. package/src/platform/kas/kas_connect.js +59 -0
  485. package/src/platform/kas/kas_pb.d.ts +200 -0
  486. package/src/platform/kas/kas_pb.js +84 -0
  487. package/src/platform/policy/attributes/attributes_connect.d.ts +168 -0
  488. package/src/platform/policy/attributes/attributes_connect.js +168 -0
  489. package/src/platform/policy/attributes/attributes_pb.d.ts +929 -0
  490. package/src/platform/policy/attributes/attributes_pb.js +363 -0
  491. package/src/platform/policy/kasregistry/key_access_server_registry_connect.d.ts +62 -0
  492. package/src/platform/policy/kasregistry/key_access_server_registry_connect.js +62 -0
  493. package/src/platform/policy/kasregistry/key_access_server_registry_pb.d.ts +283 -0
  494. package/src/platform/policy/kasregistry/key_access_server_registry_pb.js +113 -0
  495. package/src/platform/policy/namespaces/namespaces_connect.d.ts +62 -0
  496. package/src/platform/policy/namespaces/namespaces_connect.js +62 -0
  497. package/src/platform/policy/namespaces/namespaces_pb.d.ts +270 -0
  498. package/src/platform/policy/namespaces/namespaces_pb.js +110 -0
  499. package/src/platform/policy/objects_pb.d.ts +725 -0
  500. package/src/platform/policy/objects_pb.js +288 -0
  501. package/src/platform/policy/resourcemapping/resource_mapping_connect.d.ts +259 -0
  502. package/src/platform/policy/resourcemapping/resource_mapping_connect.js +259 -0
  503. package/src/platform/policy/resourcemapping/resource_mapping_pb.d.ts +314 -0
  504. package/src/platform/policy/resourcemapping/resource_mapping_pb.js +142 -0
  505. package/src/platform/policy/selectors_pb.d.ts +269 -0
  506. package/src/platform/policy/selectors_pb.js +110 -0
  507. package/src/platform/policy/subjectmapping/subject_mapping_connect.d.ts +118 -0
  508. package/src/platform/policy/subjectmapping/subject_mapping_connect.js +118 -0
  509. package/src/platform/policy/subjectmapping/subject_mapping_pb.d.ts +672 -0
  510. package/src/platform/policy/subjectmapping/subject_mapping_pb.js +260 -0
  511. package/src/platform/wellknownconfiguration/wellknown_configuration_connect.d.ts +26 -0
  512. package/src/platform/wellknownconfiguration/wellknown_configuration_connect.js +26 -0
  513. package/src/platform/wellknownconfiguration/wellknown_configuration_pb.d.ts +75 -0
  514. package/src/platform/wellknownconfiguration/wellknown_configuration_pb.js +35 -0
  515. package/src/policy/api.ts +61 -0
  516. package/src/policy/attributes.ts +117 -0
  517. package/src/policy/granter.ts +181 -0
  518. package/src/tdf/AttributeObject.ts +27 -0
  519. package/src/tdf/AttributeObjectJwt.ts +3 -0
  520. package/src/tdf/Crypto.ts +42 -0
  521. package/src/tdf/EntityObject.ts +18 -0
  522. package/src/tdf/NanoTDF/NanoTDF.ts +120 -0
  523. package/src/tdf/Policy.ts +51 -0
  524. package/src/tdf/PolicyObject.ts +12 -0
  525. package/src/tdf/TypedArray.ts +12 -0
  526. package/src/tdf/index.ts +6 -0
  527. package/src/types/index.ts +55 -0
  528. package/src/utils.ts +149 -0
  529. package/src/version.ts +9 -0
  530. package/tdf3/index.ts +91 -0
  531. package/tdf3/package-lock.json +6 -0
  532. package/tdf3/package.json +3 -0
  533. package/tdf3/src/assertions.ts +191 -0
  534. package/tdf3/src/binary.ts +195 -0
  535. package/tdf3/src/ciphers/aes-gcm-cipher.ts +76 -0
  536. package/tdf3/src/ciphers/algorithms.ts +9 -0
  537. package/tdf3/src/ciphers/index.ts +2 -0
  538. package/tdf3/src/ciphers/symmetric-cipher-base.ts +38 -0
  539. package/tdf3/src/client/DecoratedReadableStream.ts +148 -0
  540. package/tdf3/src/client/builders.ts +701 -0
  541. package/tdf3/src/client/index.ts +637 -0
  542. package/tdf3/src/client/validation.ts +79 -0
  543. package/tdf3/src/crypto/crypto-utils.ts +119 -0
  544. package/tdf3/src/crypto/declarations.ts +89 -0
  545. package/tdf3/src/crypto/index.ts +394 -0
  546. package/tdf3/src/index.ts +4 -0
  547. package/tdf3/src/models/attribute-set.ts +142 -0
  548. package/tdf3/src/models/encryption-information.ts +172 -0
  549. package/tdf3/src/models/index.ts +8 -0
  550. package/tdf3/src/models/key-access.ts +128 -0
  551. package/tdf3/src/models/manifest.ts +9 -0
  552. package/tdf3/src/models/payload.ts +6 -0
  553. package/tdf3/src/models/policy.ts +35 -0
  554. package/tdf3/src/models/upsert-response.ts +17 -0
  555. package/tdf3/src/tdf.ts +1351 -0
  556. package/tdf3/src/templates/default.html.ts +105 -0
  557. package/tdf3/src/templates/escaper.ts +10 -0
  558. package/tdf3/src/templates/index.ts +2 -0
  559. package/tdf3/src/utils/buffer-crc32.ts +46 -0
  560. package/tdf3/src/utils/chunkers.ts +118 -0
  561. package/tdf3/src/utils/index.ts +309 -0
  562. package/tdf3/src/utils/keysplit.ts +63 -0
  563. package/tdf3/src/utils/zip-reader.ts +341 -0
  564. package/tdf3/src/utils/zip-writer.ts +375 -0
  565. package/tdf3/src/version.ts +2 -0
  566. package/tdf3/types.d.ts +14 -0
@@ -0,0 +1,1351 @@
1
+ import axios, { AxiosError } from 'axios';
2
+ import { unsigned } from './utils/buffer-crc32.js';
3
+ 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
+
11
+ 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';
39
+ import {
40
+ ConfigurationError,
41
+ DecryptError,
42
+ InvalidFileError,
43
+ IntegrityError,
44
+ NetworkError,
45
+ PermissionDeniedError,
46
+ ServiceError,
47
+ TdfError,
48
+ UnauthenticatedError,
49
+ UnsafeUrlError,
50
+ UnsupportedFeatureError as UnsupportedError,
51
+ } 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';
57
+ 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';
66
+ import { CentralDirectory } from './utils/zip-reader.js';
67
+ import { SymmetricCipher } from './ciphers/symmetric-cipher-base.js';
68
+
69
+ // TODO: input validation on manifest JSON
70
+ const DEFAULT_SEGMENT_SIZE = 1024 * 1024;
71
+
72
+ /**
73
+ * Configuration for TDF3
74
+ */
75
+ export type EncryptionOptions = {
76
+ /**
77
+ * Defaults to `split`, the currently only implmented key wrap algorithm.
78
+ */
79
+ type?: SplitType;
80
+ // Defaults to AES-256-GCM for the encryption.
81
+ cipher?: string;
82
+ };
83
+
84
+ type KeyMiddleware = DecryptParams['keyMiddleware'];
85
+
86
+ export type Metadata = {
87
+ connectOptions?: {
88
+ testUrl: string;
89
+ };
90
+ policyObject?: PolicyObject;
91
+ };
92
+
93
+ export type BuildKeyAccess = {
94
+ attributeSet?: AttributeSet;
95
+ type: KeyAccessType;
96
+ url?: string;
97
+ kid?: string;
98
+ publicKey: string;
99
+ attributeUrl?: string;
100
+ metadata?: Metadata;
101
+ sid?: string;
102
+ };
103
+
104
+ type Segment = {
105
+ hash: string;
106
+ segmentSize: number | undefined;
107
+ encryptedSegmentSize: number | undefined;
108
+ };
109
+
110
+ type EntryInfo = {
111
+ filename: string;
112
+ offset?: number;
113
+ crcCounter?: number;
114
+ fileByteCount?: number;
115
+ };
116
+
117
+ type Chunk = {
118
+ hash: string;
119
+ encryptedOffset: number;
120
+ encryptedSegmentSize?: number;
121
+ decryptedChunk?: null | DecryptResult;
122
+ promise: Promise<unknown>;
123
+ _resolve?: (value: unknown) => void;
124
+ _reject?: (value: unknown) => void;
125
+ };
126
+
127
+ export type IntegrityAlgorithm = 'GMAC' | 'HS256';
128
+
129
+ export type EncryptConfiguration = {
130
+ allowedKases?: string[];
131
+ allowList?: OriginAllowList;
132
+ cryptoService: CryptoService;
133
+ dpopKeys: CryptoKeyPair;
134
+ encryptionInformation: SplitKey;
135
+ segmentSizeDefault: number;
136
+ integrityAlgorithm: IntegrityAlgorithm;
137
+ segmentIntegrityAlgorithm: IntegrityAlgorithm;
138
+ contentStream: ReadableStream<Uint8Array>;
139
+ mimeType?: string;
140
+ policy: Policy;
141
+ entity?: EntityObject;
142
+ attributeSet?: AttributeSet;
143
+ authProvider?: AuthProvider | AppIdAuthProvider;
144
+ byteLimit: number;
145
+ progressHandler?: (bytesProcessed: number) => void;
146
+ keyForEncryption: KeyInfo;
147
+ keyForManifest: KeyInfo;
148
+ assertionConfigs?: AssertionConfig[];
149
+ };
150
+
151
+ export type DecryptConfiguration = {
152
+ allowedKases?: string[];
153
+ allowList?: OriginAllowList;
154
+ authProvider: AuthProvider | AppIdAuthProvider;
155
+ cryptoService: CryptoService;
156
+ entity?: EntityObject;
157
+
158
+ dpopKeys: CryptoKeyPair;
159
+
160
+ chunker: Chunker;
161
+ keyMiddleware: KeyMiddleware;
162
+ progressHandler?: (bytesProcessed: number) => void;
163
+ fileStreamServiceWorker?: string;
164
+ assertionVerificationKeys?: AssertionVerificationKeys;
165
+ noVerifyAssertions?: boolean;
166
+ };
167
+
168
+ export type UpsertConfiguration = {
169
+ allowedKases?: string[];
170
+ allowList?: OriginAllowList;
171
+ authProvider: AuthProvider | AppIdAuthProvider;
172
+ entity?: EntityObject;
173
+
174
+ privateKey: CryptoKey;
175
+
176
+ unsavedManifest: Manifest;
177
+ // if true skips the key access type check when syncing
178
+ ignoreType?: boolean;
179
+ };
180
+
181
+ export type RewrapRequest = {
182
+ signedRequestToken: string;
183
+ };
184
+
185
+ export type KasPublicKeyFormat = 'pkcs8' | 'jwks';
186
+
187
+ type KasPublicKeyParams = {
188
+ algorithm?: KasPublicKeyAlgorithm;
189
+ fmt?: KasPublicKeyFormat;
190
+ v?: '1' | '2';
191
+ };
192
+
193
+ export type RewrapResponse = {
194
+ entityWrappedKey: string;
195
+ sessionPublicKey: string;
196
+ };
197
+
198
+ /**
199
+ * If we have KAS url but not public key we can fetch it from KAS, fetching
200
+ * the value from `${kas}/kas_public_key`.
201
+ */
202
+ export async function fetchKasPublicKey(
203
+ kas: string,
204
+ algorithm?: KasPublicKeyAlgorithm
205
+ ): Promise<KasPublicKeyInfo> {
206
+ if (!kas) {
207
+ throw new ConfigurationError('KAS definition not found');
208
+ }
209
+ // Logs insecure KAS. Secure is enforced in constructor
210
+ validateSecureUrl(kas);
211
+ const infoStatic = { url: kas, algorithm: algorithm || 'rsa:2048' };
212
+ const params: KasPublicKeyParams = {};
213
+ if (algorithm) {
214
+ params.algorithm = algorithm;
215
+ }
216
+ const v2Url = `${kas}/v2/kas_public_key`;
217
+ try {
218
+ const response: { data: string | KasPublicKeyInfo } = await axios.get(v2Url, {
219
+ params: {
220
+ ...params,
221
+ v: '2',
222
+ },
223
+ });
224
+ const publicKey =
225
+ typeof response.data === 'string'
226
+ ? await extractPemFromKeyString(response.data)
227
+ : response.data.publicKey;
228
+ return {
229
+ publicKey,
230
+ key: pemToCryptoPublicKey(publicKey),
231
+ ...infoStatic,
232
+ ...(typeof response.data !== 'string' && response.data.kid && { kid: response.data.kid }),
233
+ };
234
+ } catch (cause) {
235
+ const status = cause?.response?.status;
236
+ switch (status) {
237
+ case 400:
238
+ case 404:
239
+ // KAS does not yet implement v2, maybe
240
+ break;
241
+ case 401:
242
+ throw new UnauthenticatedError(`[${v2Url}] requires auth`, cause);
243
+ case 403:
244
+ throw new PermissionDeniedError(`[${v2Url}] permission denied`, cause);
245
+ default:
246
+ if (status && status >= 400 && status < 500) {
247
+ throw new ConfigurationError(
248
+ `[${v2Url}] request error [${status}] [${cause.name}] [${cause.message}]`,
249
+ cause
250
+ );
251
+ }
252
+ throw new NetworkError(
253
+ `[${v2Url}] error [${status}] [${cause.name}] [${cause.message}]`,
254
+ cause
255
+ );
256
+ }
257
+ }
258
+ // Retry with v1 params
259
+ const v1Url = `${kas}/kas_public_key`;
260
+ try {
261
+ const response: { data: string | KasPublicKeyInfo } = await axios.get(v1Url, {
262
+ params,
263
+ });
264
+ const publicKey =
265
+ typeof response.data === 'string'
266
+ ? await extractPemFromKeyString(response.data)
267
+ : response.data.publicKey;
268
+ // future proof: allow v2 response even if not specified.
269
+ return {
270
+ publicKey,
271
+ key: pemToCryptoPublicKey(publicKey),
272
+ ...infoStatic,
273
+ ...(typeof response.data !== 'string' && response.data.kid && { kid: response.data.kid }),
274
+ };
275
+ } catch (cause) {
276
+ const status = cause?.response?.status;
277
+ switch (status) {
278
+ case 401:
279
+ throw new UnauthenticatedError(`[${v1Url}] requires auth`, cause);
280
+ case 403:
281
+ throw new PermissionDeniedError(`[${v1Url}] permission denied`, cause);
282
+ default:
283
+ if (status && status >= 400 && status < 500) {
284
+ throw new ConfigurationError(
285
+ `[${v2Url}] request error [${status}] [${cause.name}] [${cause.message}]`,
286
+ cause
287
+ );
288
+ }
289
+ throw new NetworkError(
290
+ `[${v1Url}] error [${status}] [${cause.name}] [${cause.message}]`,
291
+ cause
292
+ );
293
+ }
294
+ }
295
+ }
296
+ /**
297
+ *
298
+ * @param payload The TDF content to encode in HTML
299
+ * @param manifest A copy of the manifest
300
+ * @param transferUrl reader web-service start page
301
+ * @return utf-8 encoded HTML data
302
+ */
303
+ export function wrapHtml(
304
+ payload: Uint8Array,
305
+ manifest: Manifest | string,
306
+ transferUrl: string
307
+ ): Uint8Array {
308
+ const { origin } = new URL(transferUrl);
309
+ const exportManifest: string = typeof manifest === 'string' ? manifest : JSON.stringify(manifest);
310
+
311
+ const fullHtmlString = htmlWrapperTemplate({
312
+ transferUrl,
313
+ transferBaseUrl: origin,
314
+ manifest: base64.encode(exportManifest),
315
+ payload: buffToString(payload, 'base64'),
316
+ });
317
+
318
+ return new TextEncoder().encode(fullHtmlString);
319
+ }
320
+
321
+ export function unwrapHtml(htmlPayload: ArrayBuffer | Uint8Array | Binary | string) {
322
+ let html;
323
+ if (htmlPayload instanceof ArrayBuffer || ArrayBuffer.isView(htmlPayload)) {
324
+ html = new TextDecoder().decode(htmlPayload);
325
+ } else {
326
+ html = htmlPayload.toString();
327
+ }
328
+ const payloadRe = /<input id=['"]?data-input['"]?[^>]*?value=['"]?([a-zA-Z0-9+/=]+)['"]?/;
329
+ const reResult = payloadRe.exec(html);
330
+ if (reResult === null) {
331
+ throw new InvalidFileError('Payload is missing');
332
+ }
333
+ const base64Payload = reResult[1];
334
+ try {
335
+ return base64ToBuffer(base64Payload);
336
+ } catch (e) {
337
+ throw new InvalidFileError('There was a problem extracting the TDF3 payload', e);
338
+ }
339
+ }
340
+
341
+ export async function extractPemFromKeyString(keyString: string): Promise<string> {
342
+ let pem: string = keyString;
343
+
344
+ // Skip the public key extraction if we find that the KAS url provides a
345
+ // PEM-encoded key instead of certificate
346
+ if (keyString.includes('CERTIFICATE')) {
347
+ const cert = await importX509(keyString, 'RS256', { extractable: true });
348
+ pem = await exportSPKI(cert);
349
+ }
350
+
351
+ return pem;
352
+ }
353
+
354
+ /**
355
+ * Build a key access object and add it to the list. Can specify either
356
+ * a (url, publicKey) pair (legacy, deprecated) or an attribute URL (future).
357
+ * If all are missing then it attempts to use the default attribute. If that
358
+ * is missing it throws an error.
359
+ * @param {Object} options
360
+ * @param {String} options.type - enum representing how the object key is treated
361
+ * @param {String} options.attributeUrl - URL of the attribute to use for pubKey and kasUrl. Omit to use default.
362
+ * @param {String} options.url - directly set the KAS URL
363
+ * @param {String} options.publicKey - directly set the (KAS) public key
364
+ * @param {String?} options.kid - Key identifier of KAS public key
365
+ * @param {String? Object?} options.metadata - Metadata. Appears to be dead code.
366
+ * @return {KeyAccess}- the key access object loaded
367
+ */
368
+ export async function buildKeyAccess({
369
+ attributeSet,
370
+ type,
371
+ url,
372
+ publicKey,
373
+ kid,
374
+ attributeUrl,
375
+ metadata,
376
+ sid = '',
377
+ }: BuildKeyAccess): Promise<KeyAccess> {
378
+ /** Internal function to keep it DRY */
379
+ function createKeyAccess(
380
+ type: KeyAccessType,
381
+ kasUrl: string,
382
+ kasKeyIdentifier: string | undefined,
383
+ pubKey: string,
384
+ metadata?: Metadata
385
+ ) {
386
+ switch (type) {
387
+ case 'wrapped':
388
+ return new KeyAccessWrapped(kasUrl, kasKeyIdentifier, pubKey, metadata, sid);
389
+ case 'remote':
390
+ return new KeyAccessRemote(kasUrl, kasKeyIdentifier, pubKey, metadata, sid);
391
+ default:
392
+ throw new ConfigurationError(`buildKeyAccess: Key access type ${type} is unknown`);
393
+ }
394
+ }
395
+
396
+ // If an attributeUrl is provided try to load with that first.
397
+ if (attributeUrl && attributeSet) {
398
+ const attr = attributeSet.get(attributeUrl);
399
+ if (attr && attr.kasUrl && attr.pubKey) {
400
+ return createKeyAccess(type, attr.kasUrl, attr.kid, attr.pubKey, metadata);
401
+ }
402
+ }
403
+
404
+ // if url and pulicKey are specified load the key access object with them
405
+ if (url && publicKey) {
406
+ return createKeyAccess(type, url, kid, await extractPemFromKeyString(publicKey), metadata);
407
+ }
408
+
409
+ // Assume the default attribute is the source for kasUrl and pubKey
410
+ const defaultAttr = attributeSet?.getDefault();
411
+ if (defaultAttr) {
412
+ const { pubKey, kasUrl } = defaultAttr;
413
+ if (pubKey && kasUrl) {
414
+ return createKeyAccess(type, kasUrl, kid, await extractPemFromKeyString(pubKey), metadata);
415
+ }
416
+ }
417
+ // All failed. Raise an error.
418
+ throw new ConfigurationError('TDF.buildKeyAccess: No source for kasUrl or pubKey');
419
+ }
420
+
421
+ export function validatePolicyObject(policy: Policy): void {
422
+ const missingFields: string[] = [];
423
+
424
+ if (!policy.uuid) missingFields.push('uuid');
425
+ if (!policy.body) missingFields.push('body', 'body.dissem');
426
+ if (policy.body && !policy.body.dissem) missingFields.push('body.dissem');
427
+
428
+ if (missingFields.length) {
429
+ throw new ConfigurationError(
430
+ `The given policy object requires the following properties: ${missingFields}`
431
+ );
432
+ }
433
+ }
434
+
435
+ async function _generateManifest(
436
+ keyInfo: KeyInfo,
437
+ encryptionInformation: SplitKey,
438
+ policy: Policy,
439
+ mimeType: string | undefined
440
+ ): Promise<Manifest> {
441
+ // (maybe) Fields are quoted to avoid renaming
442
+ const payload = {
443
+ type: 'reference',
444
+ url: '0.payload',
445
+ protocol: 'zip',
446
+ isEncrypted: true,
447
+ schemaVersion: '3.0.0',
448
+ ...(mimeType && { mimeType }),
449
+ };
450
+
451
+ const encryptionInformationStr = await encryptionInformation.write(policy, keyInfo);
452
+ const assertions: assertions.Assertion[] = [];
453
+ return {
454
+ payload,
455
+ // generate the manifest first, then insert integrity information into it
456
+ encryptionInformation: encryptionInformationStr,
457
+ assertions: assertions,
458
+ };
459
+ }
460
+
461
+ async function getSignature(
462
+ unwrappedKeyBinary: Binary,
463
+ payloadBinary: Binary,
464
+ algorithmType: IntegrityAlgorithm,
465
+ cryptoService: CryptoService
466
+ ) {
467
+ switch (algorithmType.toUpperCase()) {
468
+ case 'GMAC':
469
+ // use the auth tag baked into the encrypted payload
470
+ return buffToString(Uint8Array.from(payloadBinary.asByteArray()).slice(-16), 'hex');
471
+ case 'HS256':
472
+ // simple hmac is the default
473
+ return await cryptoService.hmac(
474
+ buffToString(new Uint8Array(unwrappedKeyBinary.asArrayBuffer()), 'hex'),
475
+ buffToString(new Uint8Array(payloadBinary.asArrayBuffer()), 'utf-8')
476
+ );
477
+ default:
478
+ throw new ConfigurationError(`Unsupported signature alg [${algorithmType}]`);
479
+ }
480
+ }
481
+
482
+ function buildRequest(method: HttpMethod, url: string, body?: unknown): HttpRequest {
483
+ return {
484
+ headers: {},
485
+ method: method,
486
+ url: url,
487
+ body,
488
+ };
489
+ }
490
+
491
+ export async function upsert({
492
+ allowedKases,
493
+ allowList,
494
+ authProvider,
495
+ entity,
496
+ privateKey,
497
+ unsavedManifest,
498
+ ignoreType,
499
+ }: UpsertConfiguration): Promise<UpsertResponse> {
500
+ const allowed = (() => {
501
+ if (allowList) {
502
+ return allowList;
503
+ }
504
+ if (!allowedKases) {
505
+ throw new ConfigurationError('Upsert cannot be done without allowlist');
506
+ }
507
+ return new OriginAllowList(allowedKases);
508
+ })();
509
+ const { keyAccess, policy } = unsavedManifest.encryptionInformation;
510
+ const isAppIdProvider = authProvider && isAppIdProviderCheck(authProvider);
511
+ if (authProvider === undefined) {
512
+ throw new ConfigurationError('Upsert cannot be done without auth provider');
513
+ }
514
+ return Promise.all(
515
+ keyAccess.map(async (keyAccessObject) => {
516
+ // We only care about remote key access objects for the policy sync portion
517
+ const isRemote = isRemoteKeyAccess(keyAccessObject);
518
+ if (!ignoreType && !isRemote) {
519
+ return;
520
+ }
521
+
522
+ if (!allowed.allows(keyAccessObject.url)) {
523
+ throw new UnsafeUrlError(`Unexpected KAS url: [${keyAccessObject.url}]`);
524
+ }
525
+
526
+ const url = `${keyAccessObject.url}/${isAppIdProvider ? '' : 'v2/'}upsert`;
527
+
528
+ //TODO I dont' think we need a body at all for KAS requests
529
+ // Do we need ANY of this if it's already embedded in the EO in the Bearer OIDC token?
530
+ const body: Record<string, unknown> = {
531
+ keyAccess: keyAccessObject,
532
+ policy: unsavedManifest.encryptionInformation.policy,
533
+ entity: isAppIdProviderCheck(authProvider) ? entity : undefined,
534
+ authToken: undefined,
535
+ clientPayloadSignature: undefined,
536
+ };
537
+
538
+ if (isAppIdProviderCheck(authProvider)) {
539
+ body.authToken = await reqSignature({}, privateKey);
540
+ } else {
541
+ body.clientPayloadSignature = await reqSignature(body, privateKey);
542
+ }
543
+ const httpReq = await authProvider.withCreds(buildRequest('POST', url, body));
544
+
545
+ try {
546
+ const response = await axios.post(httpReq.url, httpReq.body, {
547
+ headers: httpReq.headers,
548
+ });
549
+
550
+ // Remove additional properties which were needed to sync, but not that we want to save to
551
+ // the manifest
552
+ delete keyAccessObject.wrappedKey;
553
+ delete keyAccessObject.encryptedMetadata;
554
+ delete keyAccessObject.policyBinding;
555
+
556
+ if (isRemote) {
557
+ // Decode the policy and extract only the required info to save -- the uuid
558
+ const decodedPolicy = JSON.parse(base64.decode(policy));
559
+ unsavedManifest.encryptionInformation.policy = base64.encode(
560
+ JSON.stringify({ uuid: decodedPolicy.uuid })
561
+ );
562
+ }
563
+ return response.data;
564
+ } catch (e) {
565
+ if (e.response) {
566
+ if (e.response.status >= 500) {
567
+ throw new ServiceError('upsert failure', e);
568
+ } else if (e.response.status === 403) {
569
+ throw new PermissionDeniedError('upsert failure', e);
570
+ } else if (e.response.status === 401) {
571
+ throw new UnauthenticatedError('upsert auth failure', e);
572
+ } else if (e.response.status === 400) {
573
+ throw new ConfigurationError('upsert bad request; likely a configuration error', e);
574
+ } else {
575
+ throw new NetworkError('upsert server error', e);
576
+ }
577
+ } else if (e.request) {
578
+ throw new NetworkError('upsert request failure', e);
579
+ }
580
+ throw new TdfError(
581
+ `Unable to perform upsert operation on the KAS: [${e.name}: ${e.message}], response: [${e?.response?.body}]`,
582
+ e
583
+ );
584
+ }
585
+ })
586
+ );
587
+ }
588
+
589
+ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedReadableStream> {
590
+ if (!cfg.authProvider) {
591
+ throw new ConfigurationError('No authorization middleware defined');
592
+ }
593
+ if (!cfg.contentStream) {
594
+ throw new ConfigurationError('No input stream defined');
595
+ }
596
+
597
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
598
+ const segmentInfos: Segment[] = [];
599
+
600
+ cfg.byteLimit ??= Number.MAX_SAFE_INTEGER;
601
+
602
+ const entryInfos: EntryInfo[] = [
603
+ {
604
+ filename: '0.payload',
605
+ },
606
+ {
607
+ filename: '0.manifest.json',
608
+ },
609
+ ];
610
+
611
+ let currentBuffer = new Uint8Array();
612
+
613
+ let totalByteCount = 0;
614
+ let bytesProcessed = 0;
615
+ let crcCounter = 0;
616
+ let fileByteCount = 0;
617
+ let aggregateHash = '';
618
+
619
+ const zipWriter = new ZipWriter();
620
+ const manifest = await _generateManifest(
621
+ cfg.keyForManifest,
622
+ cfg.encryptionInformation,
623
+ cfg.policy,
624
+ cfg.mimeType
625
+ );
626
+
627
+ if (!manifest) {
628
+ // Set in encrypt; should never be reached.
629
+ throw new ConfigurationError('internal: please use "loadTDFStream" first to load a manifest.');
630
+ }
631
+ const pkKeyLike = cfg.dpopKeys.privateKey;
632
+
633
+ // For all remote key access objects, sync its policy
634
+ const upsertResponse = await upsert({
635
+ allowedKases: cfg.allowList ? undefined : cfg.allowedKases,
636
+ allowList: cfg.allowList,
637
+ authProvider: cfg.authProvider,
638
+ entity: cfg.entity,
639
+ privateKey: pkKeyLike,
640
+ unsavedManifest: manifest,
641
+ });
642
+
643
+ // determine default segment size by writing empty buffer
644
+ const { segmentSizeDefault } = cfg;
645
+ const encryptedBlargh = await cfg.encryptionInformation.encrypt(
646
+ Binary.fromArrayBuffer(new ArrayBuffer(segmentSizeDefault)),
647
+ cfg.keyForEncryption.unwrappedKeyBinary
648
+ );
649
+ const payloadBuffer = new Uint8Array(encryptedBlargh.payload.asByteArray());
650
+ const encryptedSegmentSizeDefault = payloadBuffer.length;
651
+
652
+ // start writing the content
653
+ entryInfos[0].filename = '0.payload';
654
+ entryInfos[0].offset = totalByteCount;
655
+ const sourceReader = cfg.contentStream.getReader();
656
+
657
+ /*
658
+ TODO: Code duplication should be addressed
659
+ - RCA operations require that the write stream has already finished executing it's .on('end') handler before being returned,
660
+ thus both handlers are wrapped in a encompassing promise when we have an RCA source. We should investigate
661
+ if this causes O(n) promises to be loaded into memory.
662
+ - LFS operations can have the write stream returned immediately after both .on('end') and .on('data') handlers
663
+ have been defined, thus not requiring the handlers to be wrapped in a promise.
664
+ */
665
+ const underlingSource = {
666
+ start: (controller: ReadableStreamDefaultController) => {
667
+ controller.enqueue(getHeader(entryInfos[0].filename));
668
+ _countChunk(getHeader(entryInfos[0].filename));
669
+ crcCounter = 0;
670
+ fileByteCount = 0;
671
+ },
672
+
673
+ pull: async (controller: ReadableStreamDefaultController) => {
674
+ let isDone;
675
+
676
+ while (currentBuffer.length < segmentSizeDefault && !isDone) {
677
+ const { value, done } = await sourceReader.read();
678
+ isDone = done;
679
+ if (value) {
680
+ currentBuffer = concatUint8([currentBuffer, value]);
681
+ }
682
+ }
683
+
684
+ while (
685
+ currentBuffer.length >= segmentSizeDefault &&
686
+ !!controller.desiredSize &&
687
+ controller.desiredSize > 0
688
+ ) {
689
+ const segment = currentBuffer.slice(0, segmentSizeDefault);
690
+ const encryptedSegment = await _encryptAndCountSegment(segment);
691
+ controller.enqueue(encryptedSegment);
692
+
693
+ currentBuffer = currentBuffer.slice(segmentSizeDefault);
694
+ }
695
+
696
+ const isFinalChunkLeft = isDone && currentBuffer.length;
697
+
698
+ if (isFinalChunkLeft) {
699
+ const encryptedSegment = await _encryptAndCountSegment(currentBuffer);
700
+ controller.enqueue(encryptedSegment);
701
+ currentBuffer = new Uint8Array();
702
+ }
703
+
704
+ if (isDone && currentBuffer.length === 0) {
705
+ entryInfos[0].crcCounter = crcCounter;
706
+ entryInfos[0].fileByteCount = fileByteCount;
707
+ const payloadDataDescriptor = zipWriter.writeDataDescriptor(crcCounter, fileByteCount);
708
+
709
+ controller.enqueue(payloadDataDescriptor);
710
+ _countChunk(payloadDataDescriptor);
711
+
712
+ // prepare the manifest
713
+ entryInfos[1].filename = '0.manifest.json';
714
+ entryInfos[1].offset = totalByteCount;
715
+ controller.enqueue(getHeader(entryInfos[1].filename));
716
+ _countChunk(getHeader(entryInfos[1].filename));
717
+ crcCounter = 0;
718
+ fileByteCount = 0;
719
+
720
+ // hash the concat of all hashes
721
+ const payloadSigStr = await getSignature(
722
+ cfg.keyForEncryption.unwrappedKeyBinary,
723
+ Binary.fromString(aggregateHash),
724
+ cfg.integrityAlgorithm,
725
+ cfg.cryptoService
726
+ );
727
+ manifest.encryptionInformation.integrityInformation.rootSignature.sig =
728
+ base64.encode(payloadSigStr);
729
+ manifest.encryptionInformation.integrityInformation.rootSignature.alg =
730
+ cfg.integrityAlgorithm;
731
+
732
+ manifest.encryptionInformation.integrityInformation.segmentSizeDefault = segmentSizeDefault;
733
+ manifest.encryptionInformation.integrityInformation.encryptedSegmentSizeDefault =
734
+ encryptedSegmentSizeDefault;
735
+ manifest.encryptionInformation.integrityInformation.segmentHashAlg =
736
+ cfg.segmentIntegrityAlgorithm;
737
+ manifest.encryptionInformation.integrityInformation.segments = segmentInfos;
738
+
739
+ manifest.encryptionInformation.method.isStreamable = true;
740
+
741
+ const signedAssertions: assertions.Assertion[] = [];
742
+ if (cfg.assertionConfigs && cfg.assertionConfigs.length > 0) {
743
+ await Promise.all(
744
+ cfg.assertionConfigs.map(async (assertionConfig) => {
745
+ // Create assertion using the assertionConfig values
746
+ const signingKey: AssertionKey = assertionConfig.signingKey ?? {
747
+ alg: 'HS256',
748
+ key: new Uint8Array(cfg.keyForEncryption.unwrappedKeyBinary.asArrayBuffer()),
749
+ };
750
+ const assertion = await assertions.CreateAssertion(aggregateHash, {
751
+ ...assertionConfig,
752
+ signingKey,
753
+ });
754
+
755
+ // Add signed assertion to the signedAssertions array
756
+ signedAssertions.push(assertion);
757
+ })
758
+ );
759
+ }
760
+
761
+ manifest.assertions = signedAssertions;
762
+
763
+ // write the manifest
764
+ const manifestBuffer = new TextEncoder().encode(JSON.stringify(manifest));
765
+ controller.enqueue(manifestBuffer);
766
+ _countChunk(manifestBuffer);
767
+ entryInfos[1].crcCounter = crcCounter;
768
+ entryInfos[1].fileByteCount = fileByteCount;
769
+ const manifestDataDescriptor = zipWriter.writeDataDescriptor(crcCounter, fileByteCount);
770
+ controller.enqueue(manifestDataDescriptor);
771
+ _countChunk(manifestDataDescriptor);
772
+
773
+ // write the central directory out
774
+ const centralDirectoryByteCount = totalByteCount;
775
+ for (let i = 0; i < entryInfos.length; i++) {
776
+ const entryInfo = entryInfos[i];
777
+ const result = zipWriter.writeCentralDirectoryRecord(
778
+ entryInfo.fileByteCount || 0,
779
+ entryInfo.filename,
780
+ entryInfo.offset || 0,
781
+ entryInfo.crcCounter || 0,
782
+ 2175008768
783
+ );
784
+ controller.enqueue(result);
785
+ _countChunk(result);
786
+ }
787
+ const endOfCentralDirectoryByteCount = totalByteCount - centralDirectoryByteCount;
788
+ const finalChunk = zipWriter.writeEndOfCentralDirectoryRecord(
789
+ entryInfos.length,
790
+ endOfCentralDirectoryByteCount,
791
+ centralDirectoryByteCount
792
+ );
793
+ controller.enqueue(finalChunk);
794
+ _countChunk(finalChunk);
795
+
796
+ controller.close();
797
+ }
798
+ },
799
+ };
800
+
801
+ const plaintextStream = new DecoratedReadableStream(underlingSource);
802
+ plaintextStream.manifest = manifest;
803
+
804
+ if (upsertResponse) {
805
+ plaintextStream.upsertResponse = upsertResponse;
806
+ plaintextStream.tdfSize = totalByteCount;
807
+ plaintextStream.algorithm = manifest.encryptionInformation.method.algorithm;
808
+ }
809
+
810
+ return plaintextStream;
811
+
812
+ // nested helper fn's
813
+ function getHeader(filename: string) {
814
+ return zipWriter.getLocalFileHeader(filename, 0, 0, 0);
815
+ }
816
+
817
+ function _countChunk(chunk: string | Uint8Array) {
818
+ if (typeof chunk === 'string') {
819
+ chunk = new TextEncoder().encode(chunk);
820
+ }
821
+ totalByteCount += chunk.length;
822
+ if (totalByteCount > cfg.byteLimit) {
823
+ throw new ConfigurationError(`Safe byte limit (${cfg.byteLimit}) exceeded`);
824
+ }
825
+ //new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
826
+ crcCounter = unsigned(chunk, crcCounter);
827
+ fileByteCount += chunk.length;
828
+ }
829
+
830
+ async function _encryptAndCountSegment(chunk: Uint8Array) {
831
+ bytesProcessed += chunk.length;
832
+ cfg.progressHandler?.(bytesProcessed);
833
+
834
+ // Don't pass in an IV here. The encrypt function will generate one for you, ensuring that each segment has a unique IV.
835
+ const encryptedResult = await cfg.encryptionInformation.encrypt(
836
+ Binary.fromArrayBuffer(chunk.buffer),
837
+ cfg.keyForEncryption.unwrappedKeyBinary
838
+ );
839
+ const payloadBuffer = new Uint8Array(encryptedResult.payload.asByteArray());
840
+ const payloadSigStr = await getSignature(
841
+ cfg.keyForEncryption.unwrappedKeyBinary,
842
+ encryptedResult.payload,
843
+ cfg.segmentIntegrityAlgorithm,
844
+ cfg.cryptoService
845
+ );
846
+
847
+ // combined string of all hashes for root signature
848
+ aggregateHash += payloadSigStr;
849
+
850
+ segmentInfos.push({
851
+ hash: base64.encode(payloadSigStr),
852
+ segmentSize: chunk.length === segmentSizeDefault ? undefined : chunk.length,
853
+ encryptedSegmentSize:
854
+ payloadBuffer.length === encryptedSegmentSizeDefault ? undefined : payloadBuffer.length,
855
+ });
856
+ const result = new Uint8Array(encryptedResult.payload.asByteArray());
857
+ _countChunk(result);
858
+
859
+ return result;
860
+ }
861
+ }
862
+
863
+ // load the TDF as a stream in memory, for further use in reading and key syncing
864
+ export async function loadTDFStream(
865
+ chunker: Chunker
866
+ ): Promise<{ manifest: Manifest; zipReader: ZipReader; centralDirectory: CentralDirectory[] }> {
867
+ const zipReader = new ZipReader(chunker);
868
+ const centralDirectory = await zipReader.getCentralDirectory();
869
+ const manifest = await zipReader.getManifest(centralDirectory, '0.manifest.json');
870
+ return { manifest, zipReader, centralDirectory };
871
+ }
872
+
873
+ export function splitLookupTableFactory(
874
+ keyAccess: KeyAccessObject[],
875
+ allowedKases: OriginAllowList
876
+ ): Record<string, Record<string, KeyAccessObject>> {
877
+ const allowed = (k: KeyAccessObject) => allowedKases.allows(k.url);
878
+ const splitIds = new Set(keyAccess.map(({ sid }) => sid ?? ''));
879
+
880
+ const accessibleSplits = new Set(keyAccess.filter(allowed).map(({ sid }) => sid));
881
+ if (splitIds.size > accessibleSplits.size) {
882
+ const disallowedKases = new Set(keyAccess.filter((k) => !allowed(k)).map(({ url }) => url));
883
+ throw new UnsafeUrlError(
884
+ `Unreconstructable key - disallowed KASes include: ${JSON.stringify([
885
+ ...disallowedKases,
886
+ ])} from splitIds ${JSON.stringify([...splitIds])}`,
887
+ ...disallowedKases
888
+ );
889
+ }
890
+ const splitPotentials: Record<string, Record<string, KeyAccessObject>> = Object.fromEntries(
891
+ [...splitIds].map((s) => [s, {}])
892
+ );
893
+ for (const kao of keyAccess) {
894
+ const disjunction = splitPotentials[kao.sid ?? ''];
895
+ if (kao.url in disjunction) {
896
+ throw new InvalidFileError(
897
+ `TODO: Fallback to no split ids. Repetition found for [${kao.url}] on split [${kao.sid}]`
898
+ );
899
+ }
900
+ if (allowed(kao)) {
901
+ disjunction[kao.url] = kao;
902
+ }
903
+ }
904
+ return splitPotentials;
905
+ }
906
+
907
+ async function unwrapKey({
908
+ manifest,
909
+ allowedKases,
910
+ authProvider,
911
+ dpopKeys,
912
+ entity,
913
+ cryptoService,
914
+ }: {
915
+ manifest: Manifest;
916
+ allowedKases: OriginAllowList;
917
+ authProvider: AuthProvider | AppIdAuthProvider;
918
+ dpopKeys: CryptoKeyPair;
919
+ entity: EntityObject | undefined;
920
+ cryptoService: CryptoService;
921
+ }) {
922
+ if (authProvider === undefined) {
923
+ throw new ConfigurationError(
924
+ 'upsert requires auth provider; must be configured in client constructor'
925
+ );
926
+ }
927
+ const { keyAccess } = manifest.encryptionInformation;
928
+ const splitPotentials = splitLookupTableFactory(keyAccess, allowedKases);
929
+ const isAppIdProvider = authProvider && isAppIdProviderCheck(authProvider);
930
+
931
+ async function tryKasRewrap(keySplitInfo: KeyAccessObject) {
932
+ const url = `${keySplitInfo.url}/${isAppIdProvider ? '' : 'v2/'}rewrap`;
933
+ const ephemeralEncryptionKeys = await cryptoService.cryptoToPemPair(
934
+ await cryptoService.generateKeyPair()
935
+ );
936
+ const clientPublicKey = ephemeralEncryptionKeys.publicKey;
937
+
938
+ const requestBodyStr = JSON.stringify({
939
+ algorithm: 'RS256',
940
+ keyAccess: keySplitInfo,
941
+ policy: manifest.encryptionInformation.policy,
942
+ clientPublicKey,
943
+ });
944
+
945
+ const jwtPayload = { requestBody: requestBodyStr };
946
+ const signedRequestToken = await reqSignature(
947
+ isAppIdProvider ? {} : jwtPayload,
948
+ dpopKeys.privateKey
949
+ );
950
+
951
+ let requestBody;
952
+ if (isAppIdProvider) {
953
+ requestBody = {
954
+ keyAccess: keySplitInfo,
955
+ policy: manifest.encryptionInformation.policy,
956
+ entity: {
957
+ ...entity,
958
+ publicKey: clientPublicKey,
959
+ },
960
+ authToken: signedRequestToken,
961
+ };
962
+ } else {
963
+ requestBody = {
964
+ signedRequestToken,
965
+ };
966
+ }
967
+
968
+ const httpReq = await authProvider.withCreds(buildRequest('POST', url, requestBody));
969
+ const {
970
+ data: { entityWrappedKey, metadata },
971
+ } = await axios.post(httpReq.url, httpReq.body, { headers: httpReq.headers });
972
+
973
+ const key = Binary.fromString(base64.decode(entityWrappedKey));
974
+ const decryptedKeyBinary = await cryptoService.decryptWithPrivateKey(
975
+ key,
976
+ ephemeralEncryptionKeys.privateKey
977
+ );
978
+
979
+ return {
980
+ key: new Uint8Array(decryptedKeyBinary.asByteArray()),
981
+ metadata,
982
+ };
983
+ }
984
+
985
+ // Get unique split IDs to determine if we have an OR or AND condition
986
+ const splitIds = new Set(Object.keys(splitPotentials));
987
+
988
+ // If we have only one split ID, it's an OR condition
989
+ if (splitIds.size === 1) {
990
+ const [splitId] = splitIds;
991
+ const potentials = splitPotentials[splitId];
992
+
993
+ try {
994
+ // OR condition: Try all KAS servers for this split, take first success
995
+ const result = await Promise.any(
996
+ Object.values(potentials).map(async (keySplitInfo) => {
997
+ try {
998
+ return await tryKasRewrap(keySplitInfo);
999
+ } catch (e) {
1000
+ // Rethrow with more context
1001
+ throw handleRewrapError(e as Error | AxiosError);
1002
+ }
1003
+ })
1004
+ );
1005
+
1006
+ const reconstructedKey = keyMerge([result.key]);
1007
+ return {
1008
+ reconstructedKeyBinary: Binary.fromArrayBuffer(reconstructedKey),
1009
+ metadata: result.metadata,
1010
+ };
1011
+ } catch (error) {
1012
+ if (error instanceof AggregateError) {
1013
+ // All KAS servers failed
1014
+ throw error.errors[0]; // Throw the first error since we've already wrapped them
1015
+ }
1016
+ throw error;
1017
+ }
1018
+ } else {
1019
+ // AND condition: We need successful results from all different splits
1020
+ const splitResults = await Promise.all(
1021
+ Object.entries(splitPotentials).map(async ([splitId, potentials]) => {
1022
+ if (!potentials || !Object.keys(potentials).length) {
1023
+ throw new UnsafeUrlError(
1024
+ `Unreconstructable key - no valid KAS found for split ${JSON.stringify(splitId)}`,
1025
+ ''
1026
+ );
1027
+ }
1028
+
1029
+ try {
1030
+ // For each split, try all potential KAS servers until one succeeds
1031
+ return await Promise.any(
1032
+ Object.values(potentials).map(async (keySplitInfo) => {
1033
+ try {
1034
+ return await tryKasRewrap(keySplitInfo);
1035
+ } catch (e) {
1036
+ throw handleRewrapError(e as Error | AxiosError);
1037
+ }
1038
+ })
1039
+ );
1040
+ } catch (error) {
1041
+ if (error instanceof AggregateError) {
1042
+ // All KAS servers for this split failed
1043
+ throw error.errors[0]; // Throw the first error since we've already wrapped them
1044
+ }
1045
+ throw error;
1046
+ }
1047
+ })
1048
+ );
1049
+
1050
+ // Merge all the split keys
1051
+ const reconstructedKey = keyMerge(splitResults.map((r) => r.key));
1052
+ return {
1053
+ reconstructedKeyBinary: Binary.fromArrayBuffer(reconstructedKey),
1054
+ metadata: splitResults[0].metadata, // Use metadata from first split
1055
+ };
1056
+ }
1057
+ }
1058
+
1059
+ function handleRewrapError(error: Error | AxiosError) {
1060
+ if (axios.isAxiosError(error)) {
1061
+ if (error.response?.status && error.response?.status >= 500) {
1062
+ return new ServiceError('rewrap failure', error);
1063
+ } else if (error.response?.status === 403) {
1064
+ return new PermissionDeniedError('rewrap failure', error);
1065
+ } else if (error.response?.status === 401) {
1066
+ return new UnauthenticatedError('rewrap auth failure', error);
1067
+ } else if (error.response?.status === 400) {
1068
+ return new InvalidFileError(
1069
+ 'rewrap bad request; could indicate an invalid policy binding or a configuration error',
1070
+ error
1071
+ );
1072
+ } else {
1073
+ return new NetworkError('rewrap server error', error);
1074
+ }
1075
+ } else {
1076
+ if (error.name === 'InvalidAccessError' || error.name === 'OperationError') {
1077
+ return new DecryptError('unable to unwrap key from kas', error);
1078
+ }
1079
+ return new InvalidFileError(
1080
+ `Unable to decrypt the response from KAS: [${error.name}: ${error.message}]`,
1081
+ error
1082
+ );
1083
+ }
1084
+ }
1085
+
1086
+ async function decryptChunk(
1087
+ encryptedChunk: Uint8Array,
1088
+ reconstructedKeyBinary: Binary,
1089
+ hash: string,
1090
+ cipher: SymmetricCipher,
1091
+ segmentIntegrityAlgorithm: IntegrityAlgorithm,
1092
+ cryptoService: CryptoService
1093
+ ): Promise<DecryptResult> {
1094
+ if (segmentIntegrityAlgorithm !== 'GMAC' && segmentIntegrityAlgorithm !== 'HS256') {
1095
+ }
1096
+ const segmentHashStr = await getSignature(
1097
+ reconstructedKeyBinary,
1098
+ Binary.fromArrayBuffer(encryptedChunk.buffer),
1099
+ segmentIntegrityAlgorithm,
1100
+ cryptoService
1101
+ );
1102
+ if (hash !== btoa(segmentHashStr)) {
1103
+ throw new IntegrityError('Failed integrity check on segment hash');
1104
+ }
1105
+ return await cipher.decrypt(encryptedChunk, reconstructedKeyBinary);
1106
+ }
1107
+
1108
+ async function updateChunkQueue(
1109
+ chunkMap: Chunk[],
1110
+ centralDirectory: CentralDirectory[],
1111
+ zipReader: ZipReader,
1112
+ reconstructedKeyBinary: Binary,
1113
+ cipher: SymmetricCipher,
1114
+ segmentIntegrityAlgorithm: IntegrityAlgorithm,
1115
+ cryptoService: CryptoService
1116
+ ) {
1117
+ const chunksInOneDownload = 500;
1118
+ let requests = [];
1119
+ const maxLength = 3;
1120
+
1121
+ for (let i = 0; i < chunkMap.length; i += chunksInOneDownload) {
1122
+ if (requests.length === maxLength) {
1123
+ await Promise.all(requests);
1124
+ requests = [];
1125
+ }
1126
+ requests.push(
1127
+ (async () => {
1128
+ let buffer: Uint8Array | null;
1129
+
1130
+ const slice = chunkMap.slice(i, i + chunksInOneDownload);
1131
+ try {
1132
+ const bufferSize = slice.reduce(
1133
+ (currentVal, { encryptedSegmentSize }) => currentVal + (encryptedSegmentSize as number),
1134
+ 0
1135
+ );
1136
+ buffer = await zipReader.getPayloadSegment(
1137
+ centralDirectory,
1138
+ '0.payload',
1139
+ slice[0].encryptedOffset,
1140
+ bufferSize
1141
+ );
1142
+ } catch (e) {
1143
+ if (e instanceof InvalidFileError) {
1144
+ throw e;
1145
+ }
1146
+ throw new NetworkError('unable to fetch payload segment', e);
1147
+ }
1148
+ if (buffer) {
1149
+ sliceAndDecrypt({
1150
+ buffer,
1151
+ cryptoService,
1152
+ reconstructedKeyBinary,
1153
+ slice,
1154
+ cipher,
1155
+ segmentIntegrityAlgorithm,
1156
+ });
1157
+ }
1158
+ })()
1159
+ );
1160
+ }
1161
+ }
1162
+
1163
+ export async function sliceAndDecrypt({
1164
+ buffer,
1165
+ reconstructedKeyBinary,
1166
+ slice,
1167
+ cipher,
1168
+ cryptoService,
1169
+ segmentIntegrityAlgorithm,
1170
+ }: {
1171
+ buffer: Uint8Array;
1172
+ reconstructedKeyBinary: Binary;
1173
+ slice: Chunk[];
1174
+ cipher: SymmetricCipher;
1175
+ cryptoService: CryptoService;
1176
+ segmentIntegrityAlgorithm: IntegrityAlgorithm;
1177
+ }) {
1178
+ for (const index in slice) {
1179
+ const { encryptedOffset, encryptedSegmentSize, _resolve, _reject } = slice[index];
1180
+
1181
+ const offset =
1182
+ slice[0].encryptedOffset === 0 ? encryptedOffset : encryptedOffset % slice[0].encryptedOffset;
1183
+ const encryptedChunk = new Uint8Array(
1184
+ buffer.slice(offset, offset + (encryptedSegmentSize as number))
1185
+ );
1186
+
1187
+ try {
1188
+ const result = await decryptChunk(
1189
+ encryptedChunk,
1190
+ reconstructedKeyBinary,
1191
+ slice[index]['hash'],
1192
+ cipher,
1193
+ segmentIntegrityAlgorithm,
1194
+ cryptoService
1195
+ );
1196
+ slice[index].decryptedChunk = result;
1197
+ if (_resolve) {
1198
+ _resolve(null);
1199
+ }
1200
+ } catch (e) {
1201
+ if (_reject) {
1202
+ _reject(e);
1203
+ } else {
1204
+ throw e;
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+
1210
+ export async function readStream(cfg: DecryptConfiguration) {
1211
+ let { allowList } = cfg;
1212
+ if (!allowList) {
1213
+ if (!cfg.allowedKases) {
1214
+ throw new ConfigurationError('Upsert cannot be done without allowlist');
1215
+ }
1216
+ allowList = new OriginAllowList(cfg.allowedKases);
1217
+ }
1218
+ const { manifest, zipReader, centralDirectory } = await loadTDFStream(cfg.chunker);
1219
+ if (!manifest) {
1220
+ throw new InvalidFileError('Missing manifest data');
1221
+ }
1222
+ cfg.keyMiddleware ??= async (key) => key;
1223
+
1224
+ const {
1225
+ encryptedSegmentSizeDefault: defaultSegmentSize,
1226
+ rootSignature,
1227
+ segmentHashAlg,
1228
+ segments,
1229
+ } = manifest.encryptionInformation.integrityInformation;
1230
+ const { metadata, reconstructedKeyBinary } = await unwrapKey({
1231
+ manifest,
1232
+ authProvider: cfg.authProvider,
1233
+ allowedKases: allowList,
1234
+ dpopKeys: cfg.dpopKeys,
1235
+ entity: cfg.entity,
1236
+ cryptoService: cfg.cryptoService,
1237
+ });
1238
+ // async function unwrapKey(manifest: Manifest, allowedKases: string[], authProvider: AuthProvider | AppIdAuthProvider, publicKey: string, privateKey: string, entity: EntityObject) {
1239
+ const keyForDecryption = await cfg.keyMiddleware(reconstructedKeyBinary);
1240
+ const encryptedSegmentSizeDefault = defaultSegmentSize || DEFAULT_SEGMENT_SIZE;
1241
+
1242
+ // check the combined string of hashes
1243
+ const aggregateHash = segments.map(({ hash }) => base64.decode(hash)).join('');
1244
+ const integrityAlgorithm = rootSignature.alg;
1245
+ if (integrityAlgorithm !== 'GMAC' && integrityAlgorithm !== 'HS256') {
1246
+ throw new UnsupportedError(`Unsupported integrity alg [${integrityAlgorithm}]`);
1247
+ }
1248
+ const payloadSigStr = await getSignature(
1249
+ keyForDecryption,
1250
+ Binary.fromString(aggregateHash),
1251
+ integrityAlgorithm,
1252
+ cfg.cryptoService
1253
+ );
1254
+
1255
+ if (
1256
+ manifest.encryptionInformation.integrityInformation.rootSignature.sig !==
1257
+ base64.encode(payloadSigStr)
1258
+ ) {
1259
+ throw new IntegrityError('Failed integrity check on root signature');
1260
+ }
1261
+
1262
+ if (!cfg.noVerifyAssertions) {
1263
+ for (const assertion of manifest.assertions || []) {
1264
+ // Create a default assertion key
1265
+ let assertionKey: AssertionKey = {
1266
+ alg: 'HS256',
1267
+ key: new Uint8Array(reconstructedKeyBinary.asArrayBuffer()),
1268
+ };
1269
+
1270
+ if (cfg.assertionVerificationKeys) {
1271
+ const foundKey = cfg.assertionVerificationKeys.Keys[assertion.id];
1272
+ if (foundKey) {
1273
+ assertionKey = foundKey;
1274
+ }
1275
+ }
1276
+ await assertions.verify(assertion, aggregateHash, assertionKey);
1277
+ }
1278
+ }
1279
+
1280
+ let mapOfRequestsOffset = 0;
1281
+ const chunkMap = new Map(
1282
+ segments.map(({ hash, encryptedSegmentSize = encryptedSegmentSizeDefault }) => {
1283
+ const result = (() => {
1284
+ let _resolve, _reject;
1285
+ const chunk: Chunk = {
1286
+ hash,
1287
+ encryptedOffset: mapOfRequestsOffset,
1288
+ encryptedSegmentSize,
1289
+ promise: new Promise((resolve, reject) => {
1290
+ _resolve = resolve;
1291
+ _reject = reject;
1292
+ }),
1293
+ };
1294
+ chunk._resolve = _resolve;
1295
+ chunk._reject = _reject;
1296
+ return chunk;
1297
+ })();
1298
+ mapOfRequestsOffset += encryptedSegmentSize || encryptedSegmentSizeDefault;
1299
+ return [hash, result];
1300
+ })
1301
+ );
1302
+
1303
+ const cipher = new AesGcmCipher(cfg.cryptoService);
1304
+ const segmentIntegrityAlg = segmentHashAlg || integrityAlgorithm;
1305
+ if (segmentIntegrityAlg !== 'GMAC' && segmentIntegrityAlg !== 'HS256') {
1306
+ throw new UnsupportedError(`Unsupported segment hash alg [${segmentIntegrityAlg}]`);
1307
+ }
1308
+
1309
+ // Not waiting for Promise to resolve
1310
+ updateChunkQueue(
1311
+ Array.from(chunkMap.values()),
1312
+ centralDirectory,
1313
+ zipReader,
1314
+ keyForDecryption,
1315
+ cipher,
1316
+ segmentIntegrityAlg,
1317
+ cfg.cryptoService
1318
+ );
1319
+
1320
+ let progress = 0;
1321
+ const underlyingSource = {
1322
+ pull: async (controller: ReadableStreamDefaultController) => {
1323
+ if (chunkMap.size === 0) {
1324
+ controller.close();
1325
+ return;
1326
+ }
1327
+
1328
+ const [hash, chunk] = chunkMap.entries().next().value;
1329
+ if (!chunk.decryptedChunk) {
1330
+ await chunk.promise;
1331
+ }
1332
+ const decryptedSegment = chunk.decryptedChunk;
1333
+
1334
+ controller.enqueue(new Uint8Array(decryptedSegment.payload.asByteArray()));
1335
+ progress += chunk.encryptedSegmentSize;
1336
+ cfg.progressHandler?.(progress);
1337
+
1338
+ chunk.decryptedChunk = null;
1339
+ chunkMap.delete(hash);
1340
+ },
1341
+ ...(cfg.fileStreamServiceWorker && { fileStreamServiceWorker: cfg.fileStreamServiceWorker }),
1342
+ };
1343
+
1344
+ const outputStream = new DecoratedReadableStream(underlyingSource);
1345
+
1346
+ outputStream.manifest = manifest;
1347
+ outputStream.emit('manifest', manifest);
1348
+ outputStream.metadata = metadata;
1349
+ outputStream.emit('rewrap', metadata);
1350
+ return outputStream;
1351
+ }