@bsv/sdk 1.9.31 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/dist/cjs/package.json +2 -3
  2. package/dist/cjs/src/auth/Peer.js +11 -18
  3. package/dist/cjs/src/auth/Peer.js.map +1 -1
  4. package/dist/cjs/src/auth/SessionManager.js.map +1 -1
  5. package/dist/cjs/src/auth/certificates/Certificate.js +8 -18
  6. package/dist/cjs/src/auth/certificates/Certificate.js.map +1 -1
  7. package/dist/cjs/src/auth/certificates/MasterCertificate.js +9 -19
  8. package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -1
  9. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js +7 -17
  10. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  11. package/dist/cjs/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
  12. package/dist/cjs/src/auth/clients/AuthFetch.js +7 -17
  13. package/dist/cjs/src/auth/clients/AuthFetch.js.map +1 -1
  14. package/dist/cjs/src/auth/clients/__tests__/AuthFetch.test.js.map +1 -1
  15. package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js +7 -17
  16. package/dist/cjs/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
  17. package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.test.js +7 -17
  18. package/dist/cjs/src/auth/transports/__tests__/SimplifiedFetchTransport.test.js.map +1 -1
  19. package/dist/cjs/src/auth/utils/createNonce.js +9 -18
  20. package/dist/cjs/src/auth/utils/createNonce.js.map +1 -1
  21. package/dist/cjs/src/auth/utils/validateCertificates.js.map +1 -1
  22. package/dist/cjs/src/auth/utils/verifyNonce.js +9 -18
  23. package/dist/cjs/src/auth/utils/verifyNonce.js.map +1 -1
  24. package/dist/cjs/src/compat/BSM.js +7 -17
  25. package/dist/cjs/src/compat/BSM.js.map +1 -1
  26. package/dist/cjs/src/compat/ECIES.js +7 -17
  27. package/dist/cjs/src/compat/ECIES.js.map +1 -1
  28. package/dist/cjs/src/compat/HD.js +7 -17
  29. package/dist/cjs/src/compat/HD.js.map +1 -1
  30. package/dist/cjs/src/compat/Mnemonic.js +7 -17
  31. package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
  32. package/dist/cjs/src/compat/Utxo.js +1 -1
  33. package/dist/cjs/src/compat/Utxo.js.map +1 -1
  34. package/dist/cjs/src/compat/index.js +7 -17
  35. package/dist/cjs/src/compat/index.js.map +1 -1
  36. package/dist/cjs/src/identity/ContactsManager.js +1 -1
  37. package/dist/cjs/src/identity/ContactsManager.js.map +1 -1
  38. package/dist/cjs/src/identity/IdentityClient.js.map +1 -1
  39. package/dist/cjs/src/kvstore/GlobalKVStore.js +10 -20
  40. package/dist/cjs/src/kvstore/GlobalKVStore.js.map +1 -1
  41. package/dist/cjs/src/kvstore/LocalKVStore.js +7 -17
  42. package/dist/cjs/src/kvstore/LocalKVStore.js.map +1 -1
  43. package/dist/cjs/src/kvstore/kvStoreInterpreter.js +7 -17
  44. package/dist/cjs/src/kvstore/kvStoreInterpreter.js.map +1 -1
  45. package/dist/cjs/src/messages/EncryptedMessage.js +0 -19
  46. package/dist/cjs/src/messages/EncryptedMessage.js.map +1 -1
  47. package/dist/cjs/src/messages/SignedMessage.js.map +1 -1
  48. package/dist/cjs/src/messages/index.js +7 -17
  49. package/dist/cjs/src/messages/index.js.map +1 -1
  50. package/dist/cjs/src/overlay-tools/Historian.js.map +1 -1
  51. package/dist/cjs/src/overlay-tools/HostReputationTracker.js.map +1 -1
  52. package/dist/cjs/src/overlay-tools/LookupResolver.js +7 -17
  53. package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
  54. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
  55. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +7 -17
  56. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
  57. package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js +2 -1
  58. package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js.map +1 -1
  59. package/dist/cjs/src/primitives/AESGCM.js +32 -77
  60. package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
  61. package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
  62. package/dist/cjs/src/primitives/Curve.js.map +1 -1
  63. package/dist/cjs/src/primitives/DRBG.js.map +1 -1
  64. package/dist/cjs/src/primitives/ECDSA.js +23 -22
  65. package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
  66. package/dist/cjs/src/primitives/Hash.js +6 -6
  67. package/dist/cjs/src/primitives/Hash.js.map +1 -1
  68. package/dist/cjs/src/primitives/JacobianPoint.js.map +1 -1
  69. package/dist/cjs/src/primitives/K256.js.map +1 -1
  70. package/dist/cjs/src/primitives/Mersenne.js.map +1 -1
  71. package/dist/cjs/src/primitives/MontgomoryMethod.js.map +1 -1
  72. package/dist/cjs/src/primitives/Point.js +6 -63
  73. package/dist/cjs/src/primitives/Point.js.map +1 -1
  74. package/dist/cjs/src/primitives/Polynomial.js.map +1 -1
  75. package/dist/cjs/src/primitives/PrivateKey.js +9 -46
  76. package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
  77. package/dist/cjs/src/primitives/PublicKey.js +1 -1
  78. package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
  79. package/dist/cjs/src/primitives/Random.js.map +1 -1
  80. package/dist/cjs/src/primitives/ReductionContext.js.map +1 -1
  81. package/dist/cjs/src/primitives/Schnorr.js.map +1 -1
  82. package/dist/cjs/src/primitives/Secp256r1.js.map +1 -1
  83. package/dist/cjs/src/primitives/Signature.js.map +1 -1
  84. package/dist/cjs/src/primitives/SymmetricKey.js.map +1 -1
  85. package/dist/cjs/src/primitives/TransactionSignature.js +7 -17
  86. package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
  87. package/dist/cjs/src/primitives/hex.js +3 -2
  88. package/dist/cjs/src/primitives/hex.js.map +1 -1
  89. package/dist/cjs/src/primitives/index.js +7 -17
  90. package/dist/cjs/src/primitives/index.js.map +1 -1
  91. package/dist/cjs/src/primitives/utils.js +15 -123
  92. package/dist/cjs/src/primitives/utils.js.map +1 -1
  93. package/dist/cjs/src/registry/RegistryClient.js +2 -2
  94. package/dist/cjs/src/registry/RegistryClient.js.map +1 -1
  95. package/dist/cjs/src/script/OP.js +3 -3
  96. package/dist/cjs/src/script/OP.js.map +1 -1
  97. package/dist/cjs/src/script/Script.js.map +1 -1
  98. package/dist/cjs/src/script/Spend.js +7 -17
  99. package/dist/cjs/src/script/Spend.js.map +1 -1
  100. package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
  101. package/dist/cjs/src/script/templates/PushDrop.js.map +1 -1
  102. package/dist/cjs/src/script/templates/RPuzzle.js.map +1 -1
  103. package/dist/cjs/src/storage/StorageDownloader.js.map +1 -1
  104. package/dist/cjs/src/storage/StorageUploader.js +7 -17
  105. package/dist/cjs/src/storage/StorageUploader.js.map +1 -1
  106. package/dist/cjs/src/storage/StorageUtils.js.map +1 -1
  107. package/dist/cjs/src/storage/__test/StorageDownloader.test.js +171 -0
  108. package/dist/cjs/src/storage/__test/StorageDownloader.test.js.map +1 -0
  109. package/dist/cjs/src/storage/__test/StorageUploader.test.js +163 -0
  110. package/dist/cjs/src/storage/__test/StorageUploader.test.js.map +1 -0
  111. package/dist/cjs/src/storage/__test/StorageUtils.test.js +97 -0
  112. package/dist/cjs/src/storage/__test/StorageUtils.test.js.map +1 -0
  113. package/dist/cjs/src/storage/index.js +7 -17
  114. package/dist/cjs/src/storage/index.js.map +1 -1
  115. package/dist/cjs/src/totp/totp.js.map +1 -1
  116. package/dist/cjs/src/transaction/Beef.js.map +1 -1
  117. package/dist/cjs/src/transaction/BeefParty.js.map +1 -1
  118. package/dist/cjs/src/transaction/BeefTx.js.map +1 -1
  119. package/dist/cjs/src/transaction/Broadcaster.js +3 -2
  120. package/dist/cjs/src/transaction/Broadcaster.js.map +1 -1
  121. package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
  122. package/dist/cjs/src/transaction/Transaction.js +1 -1
  123. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  124. package/dist/cjs/src/transaction/broadcasters/ARC.js.map +1 -1
  125. package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js +2 -1
  126. package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
  127. package/dist/cjs/src/transaction/broadcasters/Teranode.js.map +1 -1
  128. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
  129. package/dist/cjs/src/transaction/chaintrackers/BlockHeadersService.js.map +1 -1
  130. package/dist/cjs/src/transaction/chaintrackers/DefaultChainTracker.js +2 -1
  131. package/dist/cjs/src/transaction/chaintrackers/DefaultChainTracker.js.map +1 -1
  132. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
  133. package/dist/cjs/src/transaction/fee-models/LivePolicy.js.map +1 -1
  134. package/dist/cjs/src/transaction/fee-models/SatoshisPerKilobyte.js.map +1 -1
  135. package/dist/cjs/src/transaction/http/BinaryFetchClient.js +2 -2
  136. package/dist/cjs/src/transaction/http/BinaryFetchClient.js.map +1 -1
  137. package/dist/cjs/src/transaction/http/DefaultHttpClient.js +2 -1
  138. package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -1
  139. package/dist/cjs/src/transaction/http/NodejsHttpClient.js.map +1 -1
  140. package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
  141. package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
  142. package/dist/cjs/src/wallet/ProtoWallet.js +1 -1
  143. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
  144. package/dist/cjs/src/wallet/WalletClient.js.map +1 -1
  145. package/dist/cjs/src/wallet/WalletError.js.map +1 -1
  146. package/dist/cjs/src/wallet/index.js +7 -17
  147. package/dist/cjs/src/wallet/index.js.map +1 -1
  148. package/dist/cjs/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
  149. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +7 -17
  150. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -1
  151. package/dist/cjs/src/wallet/substrates/ReactNativeWebView.js +7 -17
  152. package/dist/cjs/src/wallet/substrates/ReactNativeWebView.js.map +1 -1
  153. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +7 -17
  154. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
  155. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +7 -17
  156. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
  157. package/dist/cjs/src/wallet/substrates/XDM.js +7 -17
  158. package/dist/cjs/src/wallet/substrates/XDM.js.map +1 -1
  159. package/dist/cjs/src/wallet/substrates/utils/toOriginHeader.js +2 -1
  160. package/dist/cjs/src/wallet/substrates/utils/toOriginHeader.js.map +1 -1
  161. package/dist/cjs/src/wallet/substrates/window.CWI.js.map +1 -1
  162. package/dist/cjs/src/wallet/validationHelpers.js +41 -51
  163. package/dist/cjs/src/wallet/validationHelpers.js.map +1 -1
  164. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  165. package/dist/esm/src/auth/Peer.js +4 -1
  166. package/dist/esm/src/auth/Peer.js.map +1 -1
  167. package/dist/esm/src/auth/SessionManager.js.map +1 -1
  168. package/dist/esm/src/auth/certificates/Certificate.js +1 -1
  169. package/dist/esm/src/auth/certificates/Certificate.js.map +1 -1
  170. package/dist/esm/src/auth/certificates/MasterCertificate.js +2 -2
  171. package/dist/esm/src/auth/certificates/MasterCertificate.js.map +1 -1
  172. package/dist/esm/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  173. package/dist/esm/src/auth/certificates/__tests/CompletedProtoWallet.js.map +1 -1
  174. package/dist/esm/src/auth/clients/AuthFetch.js.map +1 -1
  175. package/dist/esm/src/auth/clients/__tests__/AuthFetch.test.js.map +1 -1
  176. package/dist/esm/src/auth/transports/SimplifiedFetchTransport.js.map +1 -1
  177. package/dist/esm/src/auth/transports/__tests__/SimplifiedFetchTransport.test.js.map +1 -1
  178. package/dist/esm/src/auth/utils/validateCertificates.js.map +1 -1
  179. package/dist/esm/src/compat/BSM.js.map +1 -1
  180. package/dist/esm/src/compat/ECIES.js.map +1 -1
  181. package/dist/esm/src/compat/HD.js.map +1 -1
  182. package/dist/esm/src/compat/Mnemonic.js.map +1 -1
  183. package/dist/esm/src/identity/ContactsManager.js +1 -1
  184. package/dist/esm/src/identity/ContactsManager.js.map +1 -1
  185. package/dist/esm/src/identity/IdentityClient.js.map +1 -1
  186. package/dist/esm/src/kvstore/GlobalKVStore.js +3 -3
  187. package/dist/esm/src/kvstore/GlobalKVStore.js.map +1 -1
  188. package/dist/esm/src/kvstore/LocalKVStore.js.map +1 -1
  189. package/dist/esm/src/kvstore/kvStoreInterpreter.js.map +1 -1
  190. package/dist/esm/src/messages/EncryptedMessage.js +0 -19
  191. package/dist/esm/src/messages/EncryptedMessage.js.map +1 -1
  192. package/dist/esm/src/messages/SignedMessage.js.map +1 -1
  193. package/dist/esm/src/overlay-tools/Historian.js.map +1 -1
  194. package/dist/esm/src/overlay-tools/HostReputationTracker.js.map +1 -1
  195. package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -1
  196. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
  197. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
  198. package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js.map +1 -1
  199. package/dist/esm/src/primitives/AESGCM.js +26 -71
  200. package/dist/esm/src/primitives/AESGCM.js.map +1 -1
  201. package/dist/esm/src/primitives/BigNumber.js.map +1 -1
  202. package/dist/esm/src/primitives/Curve.js.map +1 -1
  203. package/dist/esm/src/primitives/DRBG.js.map +1 -1
  204. package/dist/esm/src/primitives/ECDSA.js +23 -22
  205. package/dist/esm/src/primitives/ECDSA.js.map +1 -1
  206. package/dist/esm/src/primitives/Hash.js.map +1 -1
  207. package/dist/esm/src/primitives/JacobianPoint.js.map +1 -1
  208. package/dist/esm/src/primitives/K256.js.map +1 -1
  209. package/dist/esm/src/primitives/Mersenne.js.map +1 -1
  210. package/dist/esm/src/primitives/MontgomoryMethod.js.map +1 -1
  211. package/dist/esm/src/primitives/Point.js +4 -61
  212. package/dist/esm/src/primitives/Point.js.map +1 -1
  213. package/dist/esm/src/primitives/Polynomial.js.map +1 -1
  214. package/dist/esm/src/primitives/PrivateKey.js +2 -29
  215. package/dist/esm/src/primitives/PrivateKey.js.map +1 -1
  216. package/dist/esm/src/primitives/PublicKey.js +1 -1
  217. package/dist/esm/src/primitives/PublicKey.js.map +1 -1
  218. package/dist/esm/src/primitives/Random.js.map +1 -1
  219. package/dist/esm/src/primitives/ReductionContext.js.map +1 -1
  220. package/dist/esm/src/primitives/Schnorr.js.map +1 -1
  221. package/dist/esm/src/primitives/Secp256r1.js.map +1 -1
  222. package/dist/esm/src/primitives/Signature.js.map +1 -1
  223. package/dist/esm/src/primitives/SymmetricKey.js.map +1 -1
  224. package/dist/esm/src/primitives/TransactionSignature.js.map +1 -1
  225. package/dist/esm/src/primitives/hex.js.map +1 -1
  226. package/dist/esm/src/primitives/utils.js +10 -118
  227. package/dist/esm/src/primitives/utils.js.map +1 -1
  228. package/dist/esm/src/registry/RegistryClient.js.map +1 -1
  229. package/dist/esm/src/script/OP.js +3 -3
  230. package/dist/esm/src/script/OP.js.map +1 -1
  231. package/dist/esm/src/script/Script.js.map +1 -1
  232. package/dist/esm/src/script/Spend.js.map +1 -1
  233. package/dist/esm/src/script/templates/P2PKH.js.map +1 -1
  234. package/dist/esm/src/script/templates/PushDrop.js.map +1 -1
  235. package/dist/esm/src/script/templates/RPuzzle.js.map +1 -1
  236. package/dist/esm/src/storage/StorageDownloader.js.map +1 -1
  237. package/dist/esm/src/storage/StorageUploader.js.map +1 -1
  238. package/dist/esm/src/storage/StorageUtils.js.map +1 -1
  239. package/dist/esm/src/storage/__test/StorageDownloader.test.js +166 -0
  240. package/dist/esm/src/storage/__test/StorageDownloader.test.js.map +1 -0
  241. package/dist/esm/src/storage/__test/StorageUploader.test.js +135 -0
  242. package/dist/esm/src/storage/__test/StorageUploader.test.js.map +1 -0
  243. package/dist/esm/src/storage/__test/StorageUtils.test.js +72 -0
  244. package/dist/esm/src/storage/__test/StorageUtils.test.js.map +1 -0
  245. package/dist/esm/src/totp/totp.js.map +1 -1
  246. package/dist/esm/src/transaction/Beef.js.map +1 -1
  247. package/dist/esm/src/transaction/BeefParty.js.map +1 -1
  248. package/dist/esm/src/transaction/BeefTx.js.map +1 -1
  249. package/dist/esm/src/transaction/MerklePath.js.map +1 -1
  250. package/dist/esm/src/transaction/Transaction.js +1 -1
  251. package/dist/esm/src/transaction/Transaction.js.map +1 -1
  252. package/dist/esm/src/transaction/broadcasters/ARC.js.map +1 -1
  253. package/dist/esm/src/transaction/broadcasters/Teranode.js.map +1 -1
  254. package/dist/esm/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -1
  255. package/dist/esm/src/transaction/chaintrackers/BlockHeadersService.js.map +1 -1
  256. package/dist/esm/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -1
  257. package/dist/esm/src/transaction/fee-models/LivePolicy.js.map +1 -1
  258. package/dist/esm/src/transaction/fee-models/SatoshisPerKilobyte.js.map +1 -1
  259. package/dist/esm/src/transaction/http/BinaryFetchClient.js.map +1 -1
  260. package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -1
  261. package/dist/esm/src/transaction/http/NodejsHttpClient.js.map +1 -1
  262. package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -1
  263. package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
  264. package/dist/esm/src/wallet/ProtoWallet.js +1 -1
  265. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
  266. package/dist/esm/src/wallet/WalletClient.js.map +1 -1
  267. package/dist/esm/src/wallet/WalletError.js.map +1 -1
  268. package/dist/esm/src/wallet/substrates/HTTPWalletJSON.js.map +1 -1
  269. package/dist/esm/src/wallet/substrates/HTTPWalletWire.js.map +1 -1
  270. package/dist/esm/src/wallet/substrates/ReactNativeWebView.js.map +1 -1
  271. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -1
  272. package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js.map +1 -1
  273. package/dist/esm/src/wallet/substrates/XDM.js.map +1 -1
  274. package/dist/esm/src/wallet/substrates/utils/toOriginHeader.js.map +1 -1
  275. package/dist/esm/src/wallet/substrates/window.CWI.js.map +1 -1
  276. package/dist/esm/src/wallet/validationHelpers.js +1 -1
  277. package/dist/esm/src/wallet/validationHelpers.js.map +1 -1
  278. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  279. package/dist/types/src/auth/Peer.d.ts.map +1 -1
  280. package/dist/types/src/auth/certificates/MasterCertificate.d.ts.map +1 -1
  281. package/dist/types/src/auth/utils/getVerifiableCertificates.d.ts.map +1 -1
  282. package/dist/types/src/auth/utils/validateCertificates.d.ts.map +1 -1
  283. package/dist/types/src/compat/BSM.d.ts +1 -1
  284. package/dist/types/src/compat/BSM.d.ts.map +1 -1
  285. package/dist/types/src/messages/EncryptedMessage.d.ts +0 -19
  286. package/dist/types/src/messages/EncryptedMessage.d.ts.map +1 -1
  287. package/dist/types/src/messages/SignedMessage.d.ts.map +1 -1
  288. package/dist/types/src/primitives/AESGCM.d.ts +0 -18
  289. package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
  290. package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
  291. package/dist/types/src/primitives/Hash.d.ts +8 -8
  292. package/dist/types/src/primitives/Hash.d.ts.map +1 -1
  293. package/dist/types/src/primitives/Point.d.ts +0 -1
  294. package/dist/types/src/primitives/Point.d.ts.map +1 -1
  295. package/dist/types/src/primitives/PrivateKey.d.ts +0 -27
  296. package/dist/types/src/primitives/PrivateKey.d.ts.map +1 -1
  297. package/dist/types/src/primitives/Random.d.ts.map +1 -1
  298. package/dist/types/src/primitives/Secp256r1.d.ts.map +1 -1
  299. package/dist/types/src/primitives/utils.d.ts +3 -3
  300. package/dist/types/src/primitives/utils.d.ts.map +1 -1
  301. package/dist/types/src/storage/StorageUtils.d.ts.map +1 -1
  302. package/dist/types/src/storage/__test/StorageDownloader.test.d.ts +2 -0
  303. package/dist/types/src/storage/__test/StorageDownloader.test.d.ts.map +1 -0
  304. package/dist/types/src/storage/__test/StorageUploader.test.d.ts +2 -0
  305. package/dist/types/src/storage/__test/StorageUploader.test.d.ts.map +1 -0
  306. package/dist/types/src/storage/__test/StorageUtils.test.d.ts +2 -0
  307. package/dist/types/src/storage/__test/StorageUtils.test.d.ts.map +1 -0
  308. package/dist/types/src/transaction/Beef.d.ts +2 -2
  309. package/dist/types/src/transaction/Beef.d.ts.map +1 -1
  310. package/dist/types/src/transaction/http/BinaryFetchClient.d.ts +2 -0
  311. package/dist/types/src/transaction/http/BinaryFetchClient.d.ts.map +1 -1
  312. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  313. package/dist/umd/bundle.js +3 -3
  314. package/dist/umd/bundle.js.map +1 -1
  315. package/docs/reference/messages.md +0 -24
  316. package/docs/reference/primitives.md +17 -82
  317. package/package.json +2 -3
  318. package/src/auth/Peer.ts +4 -1
  319. package/src/messages/EncryptedMessage.ts +0 -19
  320. package/src/primitives/AESGCM.ts +34 -75
  321. package/src/primitives/PrivateKey.ts +0 -27
  322. package/src/primitives/__tests/AESGCM.test.ts +0 -31
  323. package/src/primitives/__tests/utils.test.ts +30 -7
  324. package/src/primitives/utils.ts +2 -127
@@ -2,30 +2,6 @@
2
2
 
3
3
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Variables](#variables)
4
4
 
5
- ## Security Considerations for Encrypted Messages
6
-
7
- The encrypted message protocol implemented in this SDK derives per-message
8
- encryption keys deterministically from the parties’ long-term keys and a
9
- caller-supplied invoice number (BRC-42 style derivation).
10
-
11
- This construction does **not** provide the guarantees of a standard
12
- authenticated key exchange (AKE). In particular:
13
-
14
- - **No forward secrecy**: Compromise of a long-term private key compromises
15
- all past and future messages derived from it.
16
- - **No replay protection**: Messages encrypted under the same invoice number
17
- and key pair can be replayed.
18
- - **Potential identity misbinding**: Public keys alone do not guarantee peer
19
- identity without additional authentication or identity verification.
20
-
21
- This protocol is intended for lightweight, deterministic messaging between
22
- parties that already trust each other’s long-term public keys. It SHOULD NOT
23
- be used for high-security or high-value communications without additional
24
- protocol-layer protections.
25
-
26
- Applications requiring strong authentication, replay protection, or forward
27
- secrecy should use a formally analyzed protocol such as X3DH, Noise, or SIGMA.
28
-
29
5
  ## Interfaces
30
6
 
31
7
  ## Classes
@@ -4961,14 +4961,14 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
4961
4961
 
4962
4962
  | | |
4963
4963
  | --- | --- |
4964
- | [AES](#function-aes) | [pbkdf2](#function-pbkdf2) |
4965
- | [AESGCM](#function-aesgcm) | [realHtonl](#function-realhtonl) |
4966
- | [AESGCMDecrypt](#function-aesgcmdecrypt) | [red](#function-red) |
4967
- | [assertValidHex](#function-assertvalidhex) | [swapBytes32](#function-swapbytes32) |
4968
- | [base64ToArray](#function-base64toarray) | [toArray](#function-toarray) |
4964
+ | [AES](#function-aes) | [normalizeHex](#function-normalizehex) |
4965
+ | [AESGCM](#function-aesgcm) | [pbkdf2](#function-pbkdf2) |
4966
+ | [AESGCMDecrypt](#function-aesgcmdecrypt) | [realHtonl](#function-realhtonl) |
4967
+ | [assertValidHex](#function-assertvalidhex) | [red](#function-red) |
4968
+ | [base64ToArray](#function-base64toarray) | [swapBytes32](#function-swapbytes32) |
4969
+ | [constantTimeEquals](#function-constanttimeequals) | [toArray](#function-toarray) |
4969
4970
  | [ghash](#function-ghash) | [toBase64](#function-tobase64) |
4970
4971
  | [htonl](#function-htonl) | [verifyNotNull](#function-verifynotnull) |
4971
- | [normalizeHex](#function-normalizehex) | |
4972
4972
 
4973
4973
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
4974
4974
 
@@ -5067,6 +5067,15 @@ export function base64ToArray(msg: string): number[]
5067
5067
 
5068
5068
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
5069
5069
 
5070
+ ---
5071
+ ### Function: constantTimeEquals
5072
+
5073
+ ```ts
5074
+ export function constantTimeEquals(a: Uint8Array | number[], b: Uint8Array | number[]): boolean
5075
+ ```
5076
+
5077
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
5078
+
5070
5079
  ---
5071
5080
  ### Function: ghash
5072
5081
 
@@ -5736,7 +5745,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
5736
5745
  ```ts
5737
5746
  incrementLeastSignificantThirtyTwoBits = function (block: Bytes): Bytes {
5738
5747
  const result = block.slice();
5739
- for (let i = 15; i !== 11; i--) {
5748
+ for (let i = 15; i > 11; i--) {
5740
5749
  result[i] = (result[i] + 1) & 255;
5741
5750
  if (result[i] !== 0) {
5742
5751
  break;
@@ -6265,81 +6274,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
6265
6274
 
6266
6275
  ```ts
6267
6276
  toUTF8 = (arr: number[]): string => {
6268
- let result = "";
6269
- const replacementChar = "\uFFFD";
6270
- for (let i = 0; i < arr.length; i++) {
6271
- const byte1 = arr[i];
6272
- if (byte1 <= 127) {
6273
- result += String.fromCharCode(byte1);
6274
- continue;
6275
- }
6276
- const emitReplacement = (): void => {
6277
- result += replacementChar;
6278
- };
6279
- if (byte1 >= 192 && byte1 <= 223) {
6280
- if (i + 1 >= arr.length) {
6281
- emitReplacement();
6282
- continue;
6283
- }
6284
- const byte2 = arr[i + 1];
6285
- if ((byte2 & 192) !== 128) {
6286
- emitReplacement();
6287
- i += 1;
6288
- continue;
6289
- }
6290
- const codePoint = ((byte1 & 31) << 6) | (byte2 & 63);
6291
- result += String.fromCharCode(codePoint);
6292
- i += 1;
6293
- continue;
6294
- }
6295
- if (byte1 >= 224 && byte1 <= 239) {
6296
- if (i + 2 >= arr.length) {
6297
- emitReplacement();
6298
- continue;
6299
- }
6300
- const byte2 = arr[i + 1];
6301
- const byte3 = arr[i + 2];
6302
- if ((byte2 & 192) !== 128 || (byte3 & 192) !== 128) {
6303
- emitReplacement();
6304
- i += 2;
6305
- continue;
6306
- }
6307
- const codePoint = ((byte1 & 15) << 12) |
6308
- ((byte2 & 63) << 6) |
6309
- (byte3 & 63);
6310
- result += String.fromCharCode(codePoint);
6311
- i += 2;
6312
- continue;
6313
- }
6314
- if (byte1 >= 240 && byte1 <= 247) {
6315
- if (i + 3 >= arr.length) {
6316
- emitReplacement();
6317
- continue;
6318
- }
6319
- const byte2 = arr[i + 1];
6320
- const byte3 = arr[i + 2];
6321
- const byte4 = arr[i + 3];
6322
- if ((byte2 & 192) !== 128 ||
6323
- (byte3 & 192) !== 128 ||
6324
- (byte4 & 192) !== 128) {
6325
- emitReplacement();
6326
- i += 3;
6327
- continue;
6328
- }
6329
- const codePoint = ((byte1 & 7) << 18) |
6330
- ((byte2 & 63) << 12) |
6331
- ((byte3 & 63) << 6) |
6332
- (byte4 & 63);
6333
- const offset = codePoint - 65536;
6334
- const highSurrogate = 55296 + (offset >> 10);
6335
- const lowSurrogate = 56320 + (offset & 1023);
6336
- result += String.fromCharCode(highSurrogate, lowSurrogate);
6337
- i += 3;
6338
- continue;
6339
- }
6340
- emitReplacement();
6341
- }
6342
- return result;
6277
+ return new TextDecoder().decode(new Uint8Array(arr));
6343
6278
  }
6344
6279
  ```
6345
6280
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.9.31",
3
+ "version": "2.0.0-beta.0",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -221,8 +221,7 @@
221
221
  "prepublish": "npm run build",
222
222
  "doc": "ts2md",
223
223
  "docs:serve": "mkdocs serve",
224
- "docs:build": "mkdocs build",
225
- "test:ci": "npm run build && jest --forceExit"
224
+ "docs:build": "mkdocs build"
226
225
  },
227
226
  "repository": {
228
227
  "type": "git",
package/src/auth/Peer.ts CHANGED
@@ -525,7 +525,10 @@ export class Peer {
525
525
 
526
526
  // Create signature
527
527
  const { signature } = await this.wallet.createSignature({
528
- data: Peer.base64ToBytes(message.initialNonce + sessionNonce),
528
+ data: [
529
+ ...Peer.base64ToBytes(message.initialNonce),
530
+ ...Peer.base64ToBytes(sessionNonce)
531
+ ],
529
532
  protocolID: [2, 'auth message signature'],
530
533
  keyID: `${message.initialNonce} ${sessionNonce}`,
531
534
  counterparty: message.identityKey
@@ -14,25 +14,6 @@ const VERSION = '42421033'
14
14
  *
15
15
  * @returns The encrypted message
16
16
  */
17
- /**
18
- * SECURITY NOTE – NON-AUTHENTICATED KEY EXCHANGE
19
- *
20
- * This encrypted message protocol does NOT implement a formally authenticated
21
- * key exchange (AKE). Session keys are deterministically derived from long-term
22
- * identity keys and a sender-chosen invoice value.
23
- *
24
- * As a result, this protocol does NOT provide:
25
- * - Forward secrecy
26
- * - Replay protection
27
- * - Explicit authentication of peer identity
28
- *
29
- * This scheme SHOULD NOT be used for high-value, long-lived, or sensitive
30
- * communications. It is intended for lightweight messaging where both parties
31
- * already possess each other's long-term public keys and accept these risks.
32
- *
33
- * Future versions may introduce a protocol upgrade based on a standard AKE
34
- * (e.g. X3DH, Noise, or SIGMA).
35
- */
36
17
  export const encrypt = (
37
18
  message: number[],
38
19
  sender: PrivateKey,
@@ -1,31 +1,5 @@
1
- // @ts-nocheck
2
1
 
3
- // NOTE:
4
- // Table-based AES is intentionally retained for performance.
5
- // JavaScript runtimes (JIT, GC, speculative execution) cannot provide
6
- // strong constant-time guarantees, and arithmetic-only AES implementations
7
- // cause catastrophic performance degradation in practice.
8
- //
9
- // This implementation therefore prioritizes correctness, performance,
10
- // and compatibility over attempting misleading "constant-time" behavior.
11
- //
12
- // Applications requiring strict side-channel resistance SHOULD use
13
- // platform-native crypto APIs (e.g. WebCrypto) or audited native libraries.
14
- /**
15
- * SECURITY DISCLAIMER – AES-GCM IMPLEMENTATION
16
- *
17
- * This module provides a self-contained AES-GCM implementation intended for
18
- * functional correctness and portability with minimal dependencies.
19
- *
20
- * While efforts are made to reduce timing side-channel leakage (e.g. avoiding
21
- * secret-dependent branches in GHASH), JavaScript does not guarantee
22
- * constant-time execution. As such, this implementation should not be used in
23
- * environments where attackers can reliably measure fine-grained execution
24
- * timing (e.g. shared hosts, co-resident VMs, or untrusted browser contexts).
25
- *
26
- * For high-assurance cryptographic use cases, prefer platform-provided
27
- * WebCrypto APIs or well-audited constant-time libraries.
28
- */
2
+ // @ts-nocheck
29
3
  const SBox = new Uint8Array([
30
4
  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
31
5
  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
@@ -44,7 +18,6 @@ const SBox = new Uint8Array([
44
18
  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
45
19
  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
46
20
  ])
47
-
48
21
  const Rcon = [
49
22
  [0x00, 0x00, 0x00, 0x00], [0x01, 0x00, 0x00, 0x00], [0x02, 0x00, 0x00, 0x00], [0x04, 0x00, 0x00, 0x00],
50
23
  [0x08, 0x00, 0x00, 0x00], [0x10, 0x00, 0x00, 0x00], [0x20, 0x00, 0x00, 0x00], [0x40, 0x00, 0x00, 0x00],
@@ -59,20 +32,6 @@ for (let i = 0; i < 256; i++) {
59
32
  mul3[i] = m2 ^ i
60
33
  }
61
34
 
62
- function mixColumnsFast (state: number[][]): void {
63
- for (let c = 0; c < 4; c++) {
64
- const s0 = state[0][c]
65
- const s1 = state[1][c]
66
- const s2 = state[2][c]
67
- const s3 = state[3][c]
68
-
69
- state[0][c] = mul2[s0] ^ mul3[s1] ^ s2 ^ s3
70
- state[1][c] = s0 ^ mul2[s1] ^ mul3[s2] ^ s3
71
- state[2][c] = s0 ^ s1 ^ mul2[s2] ^ mul3[s3]
72
- state[3][c] = mul3[s0] ^ s1 ^ s2 ^ mul2[s3]
73
- }
74
- }
75
-
76
35
  function addRoundKey (
77
36
  state: number[][],
78
37
  roundKeyArray: number[][],
@@ -130,6 +89,20 @@ function shiftRows (state: number[][]): void {
130
89
  state[3][0] = tmp
131
90
  }
132
91
 
92
+ function mixColumns (state: number[][]): void {
93
+ for (let c = 0; c < 4; c++) {
94
+ const s0 = state[0][c]
95
+ const s1 = state[1][c]
96
+ const s2 = state[2][c]
97
+ const s3 = state[3][c]
98
+
99
+ state[0][c] = mul2[s0] ^ mul3[s1] ^ s2 ^ s3
100
+ state[1][c] = s0 ^ mul2[s1] ^ mul3[s2] ^ s3
101
+ state[2][c] = s0 ^ s1 ^ mul2[s2] ^ mul3[s3]
102
+ state[3][c] = mul3[s0] ^ s1 ^ s2 ^ mul2[s3]
103
+ }
104
+ }
105
+
133
106
  function keyExpansion (roundLimit: number, key: number[]): number[][] {
134
107
  const nK = key.length / 4
135
108
  const result: number[][] = []
@@ -197,7 +170,7 @@ export function AES (input: number[], key: number[]): number[] {
197
170
  shiftRows(state)
198
171
 
199
172
  if (round + 1 < roundLimit) {
200
- mixColumnsFast(state)
173
+ mixColumns(state)
201
174
  }
202
175
 
203
176
  addRoundKey(state, w, round * 4)
@@ -285,6 +258,12 @@ export const exclusiveOR = function (block0: Bytes, block1: Bytes): Bytes {
285
258
  return result
286
259
  }
287
260
 
261
+ const xorInto = function (target: Bytes, block: Bytes): void {
262
+ for (let i = 0; i < target.length; i++) {
263
+ target[i] ^= block[i] ?? 0
264
+ }
265
+ }
266
+
288
267
  export const rightShift = function (block: Bytes): Bytes {
289
268
  let carry = 0
290
269
  let oldCarry = 0
@@ -302,48 +281,25 @@ export const rightShift = function (block: Bytes): Bytes {
302
281
  return block
303
282
  }
304
283
 
305
- /**
306
- * SECURITY NOTE – TIMING SIDE-CHANNEL MITIGATION
307
- *
308
- * This GHASH multiplication implementation avoids data-dependent conditional
309
- * branches by using mask-based operations instead. This reduces timing
310
- * side-channel leakage compared to a naive implementation that branches on
311
- * secret bits.
312
- *
313
- * IMPORTANT: JavaScript and TypedArray operations do NOT provide constant-time
314
- * execution guarantees. While this implementation mitigates obvious control-
315
- * flow timing leaks, it must not be considered constant-time in a strict
316
- * cryptographic sense and is not suitable for hostile shared-CPU or
317
- * multi-tenant environments.
318
- *
319
- * Applications requiring strict constant-time AES-GCM SHOULD use a dedicated,
320
- * audited cryptographic library (e.g. noble-ciphers, WebCrypto, or BearSSL
321
- * bindings).
322
- */
323
284
  export const multiply = function (block0: Bytes, block1: Bytes): Bytes {
324
285
  const v = block1.slice()
325
286
  const z = createZeroBlock(16)
326
287
 
327
288
  for (let i = 0; i < 16; i++) {
328
- const b = block0[i]
329
289
  for (let j = 7; j >= 0; j--) {
330
- // mask = 0xff if bit is set, 0x00 otherwise
331
- const bit = (b >> j) & 1
332
- const mask = -bit & 0xff
333
- // z ^= v & mask
334
- for (let k = 0; k < 16; k++) {
335
- z[k] ^= v[k] & mask
290
+ if ((block0[i] & (1 << j)) !== 0) {
291
+ xorInto(z, v)
336
292
  }
337
- // compute reduction mask
338
- const lsb = v[15] & 1
339
- const rmask = -lsb & 0xff
340
- rightShift(v)
341
- // v ^= R & rmask
342
- for (let k = 0; k < 16; k++) {
343
- v[k] ^= R[k] & rmask
293
+
294
+ if ((v[15] & 1) !== 0) {
295
+ rightShift(v)
296
+ xorInto(v, R)
297
+ } else {
298
+ rightShift(v)
344
299
  }
345
300
  }
346
301
  }
302
+
347
303
  return z
348
304
  }
349
305
 
@@ -351,12 +307,15 @@ export const incrementLeastSignificantThirtyTwoBits = function (
351
307
  block: Bytes
352
308
  ): Bytes {
353
309
  const result = block.slice()
310
+
354
311
  for (let i = 15; i > 11; i--) {
355
312
  result[i] = (result[i] + 1) & 0xff // wrap explicitly
313
+
356
314
  if (result[i] !== 0) {
357
315
  break
358
316
  }
359
317
  }
318
+
360
319
  return result
361
320
  }
362
321
 
@@ -355,33 +355,6 @@ export default class PrivateKey extends BigNumber {
355
355
  return key.mulCT(this)
356
356
  }
357
357
 
358
- /**
359
- * SECURITY NOTE – DETERMINISTIC CHILD KEY DERIVATION
360
- *
361
- * This method derives child private keys deterministically from the caller’s
362
- * long-term private key, the counterparty’s public key, and a caller-supplied
363
- * invoice number using HMAC over an ECDH shared secret (BRC-42 style derivation).
364
- *
365
- * This construction does NOT implement a formally authenticated key exchange
366
- * (AKE) and does NOT provide the following security properties:
367
- *
368
- * - Forward secrecy: Compromise of a long-term private key compromises all
369
- * past and future child keys derived from it.
370
- * - Replay protection: Child keys are deterministic for a given invoice
371
- * number and key pair; previously observed messages can be replayed.
372
- * - Explicit authentication / identity binding: Possession of a public key
373
- * alone does not guarantee the intended peer identity, enabling potential
374
- * identity misbinding attacks if higher-level identity verification is absent.
375
- *
376
- * This derivation is intended for lightweight, deterministic key hierarchies
377
- * where both parties already possess and trust each other’s long-term public
378
- * keys. It SHOULD NOT be used as a drop-in replacement for a standard
379
- * authenticated key exchange (e.g. X3DH, Noise, or SIGMA) in high-security or
380
- * high-value contexts.
381
- *
382
- * Any future protocol providing forward secrecy, replay protection, or strong
383
- * peer authentication will require a versioned, breaking change.
384
- */
385
358
  /**
386
359
  * Derives a child key with BRC-42.
387
360
  * @param publicKey The public key of the other party
@@ -598,34 +598,3 @@ describe('AESGCM large input (non-mocked)', () => {
598
598
  expectUint8ArrayEqual(decryptedBytes, plaintext)
599
599
  })
600
600
  })
601
-
602
- describe('multiply reduction edge cases', () => {
603
- it('applies reduction polynomial when LSB carry is set', () => {
604
- // Force reduction path by setting v[15] LSB = 1
605
- const a = new Uint8Array(16)
606
- a[0] = 0x01
607
-
608
- const b = new Uint8Array(16)
609
- b[15] = 0x01
610
-
611
- const out = multiply(a, b)
612
-
613
- // We don't assert a magic value — we assert that output is non-zero
614
- // and stable across runs (reduction happened)
615
- expect(out.some(v => v !== 0)).toBe(true)
616
- })
617
-
618
- it('does not reduce when LSB carry is zero', () => {
619
- const a = new Uint8Array(16)
620
- a[0] = 0x01
621
-
622
- const b = new Uint8Array(16)
623
- b[15] = 0x00
624
-
625
- const out = multiply(a, b)
626
-
627
- expect(out.some(v => v !== 0)).toBe(false)
628
- })
629
- })
630
-
631
-
@@ -323,13 +323,17 @@ describe('verifyNotNull', () => {
323
323
  })
324
324
  })
325
325
 
326
- describe('toUTF8 strict UTF-8 decoding (TOB-21)', () => {
326
+ describe('toUTF8 UTF-8 decoding', () => {
327
327
 
328
- it('replaces invalid 2-byte sequences with U+FFFD', () => {
328
+ it('decodes ASCII bytes', () => {
329
+ expect(toUTF8([0x48, 0x65, 0x6c, 0x6c, 0x6f])).toBe('Hello')
330
+ })
331
+
332
+ it('replaces invalid 2-byte sequences with U+FFFD and continues decoding', () => {
329
333
  // 0xC2 should expect a continuation byte 0x80–0xBF
330
334
  const arr = [0xC2, 0x20] // 0x20 is INVALID continuation
331
335
  const str = toUTF8(arr)
332
- expect(str).toBe('\uFFFD')
336
+ expect(str).toBe('\uFFFD ')
333
337
  })
334
338
 
335
339
  it('decodes valid 3-byte sequences', () => {
@@ -337,10 +341,10 @@ describe('toUTF8 strict UTF-8 decoding (TOB-21)', () => {
337
341
  expect(toUTF8(euro)).toBe('€')
338
342
  })
339
343
 
340
- it('replaces invalid 3-byte sequences', () => {
344
+ it('replaces invalid 3-byte sequences with U+FFFD and continues decoding', () => {
341
345
  // Middle byte invalid
342
346
  const arr = [0xE2, 0x20, 0xAC]
343
- expect(toUTF8(arr)).toBe('\uFFFD')
347
+ expect(toUTF8(arr)).toBe('\uFFFD \uFFFD')
344
348
  })
345
349
 
346
350
  it('decodes valid 4-byte sequences into surrogate pairs', () => {
@@ -348,10 +352,10 @@ describe('toUTF8 strict UTF-8 decoding (TOB-21)', () => {
348
352
  expect(toUTF8(smile)).toBe('😀')
349
353
  })
350
354
 
351
- it('replaces invalid 4-byte sequences with U+FFFD', () => {
355
+ it('replaces invalid 4-byte sequences with U+FFFD and continues decoding', () => {
352
356
  // 0x9F is valid, 0x20 is INVALID continuation for byte 3
353
357
  const arr = [0xF0, 0x9F, 0x20, 0x80]
354
- expect(toUTF8(arr)).toBe('\uFFFD')
358
+ expect(toUTF8(arr)).toBe('\uFFFD \uFFFD')
355
359
  })
356
360
 
357
361
  it('replaces incomplete UTF-8 sequence at end', () => {
@@ -359,6 +363,25 @@ describe('toUTF8 strict UTF-8 decoding (TOB-21)', () => {
359
363
  expect(toUTF8(arr)).toBe('\uFFFD')
360
364
  })
361
365
 
366
+ it('replaces overlong sequences with U+FFFD', () => {
367
+ expect(toUTF8([0xC0, 0xAF])).toBe('\uFFFD\uFFFD')
368
+ })
369
+
370
+ it('replaces UTF-8 encoded surrogates with U+FFFD', () => {
371
+ expect(toUTF8([0xED, 0xA0, 0x80])).toBe('\uFFFD\uFFFD\uFFFD')
372
+ })
373
+
374
+ })
375
+
376
+ describe("toArray('utf8') UTF-8 encoding", () => {
377
+ it('round-trips UTF-8 strings', () => {
378
+ const s = 'Hello € 😀'
379
+ expect(toUTF8(toArray(s, 'utf8') as number[])).toBe(s)
380
+ })
381
+
382
+ it('replaces lone surrogates with U+FFFD when encoding', () => {
383
+ expect(toArray('\uD800', 'utf8')).toEqual([0xEF, 0xBF, 0xBD])
384
+ })
362
385
  })
363
386
 
364
387
  describe('Point.encode infinity handling', () => {
@@ -168,53 +168,7 @@ export function base64ToArray (msg: string): number[] {
168
168
  * @returns An array of numbers, each representing a byte in the UTF-8 encoded string.
169
169
  */
170
170
  function utf8ToArray (str: string): number[] {
171
- const result: number[] = []
172
-
173
- for (let i = 0; i < str.length; i++) {
174
- const cp = str.codePointAt(i)
175
- if (cp === undefined) {
176
- // Should never be out of range.
177
- throw new Error(`Index out of range: ${i}`)
178
- }
179
- let codePoint = cp
180
-
181
- if (codePoint > 0xFFFF) {
182
- // Valid surrogate pair => skip the next code unit because codePointAt
183
- // has already combined them into a single code point.
184
- i++
185
- } else {
186
- // Check if codePoint is a lone (unpaired) high surrogate or low surrogate.
187
- if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
188
- // Replace with the replacement character (U+FFFD).
189
- codePoint = 0xFFFD
190
- }
191
- }
192
-
193
- // Encode according to the UTF-8 standard
194
- if (codePoint <= 0x7F) {
195
- result.push(codePoint)
196
- } else if (codePoint <= 0x7FF) {
197
- result.push(
198
- 0xC0 | (codePoint >> 6),
199
- 0x80 | (codePoint & 0x3F)
200
- )
201
- } else if (codePoint <= 0xFFFF) {
202
- result.push(
203
- 0xE0 | (codePoint >> 12),
204
- 0x80 | ((codePoint >> 6) & 0x3F),
205
- 0x80 | (codePoint & 0x3F)
206
- )
207
- } else {
208
- result.push(
209
- 0xF0 | (codePoint >> 18),
210
- 0x80 | ((codePoint >> 12) & 0x3F),
211
- 0x80 | ((codePoint >> 6) & 0x3F),
212
- 0x80 | (codePoint & 0x3F)
213
- )
214
- }
215
- }
216
-
217
- return result
171
+ return Array.from(new TextEncoder().encode(str))
218
172
  }
219
173
 
220
174
  /**
@@ -223,86 +177,7 @@ function utf8ToArray (str: string): number[] {
223
177
  * @returns {string} - The UTF-8 encoded string.
224
178
  */
225
179
  export const toUTF8 = (arr: number[]): string => {
226
- let result = ''
227
- const replacementChar = '\uFFFD'
228
- for (let i = 0; i < arr.length; i++) {
229
- const byte1 = arr[i]
230
- if (byte1 <= 0x7f) {
231
- result += String.fromCharCode(byte1)
232
- continue
233
- }
234
- const emitReplacement = (): void => {
235
- result += replacementChar
236
- }
237
- if (byte1 >= 0xc0 && byte1 <= 0xdf) {
238
- if (i + 1 >= arr.length) {
239
- emitReplacement()
240
- continue
241
- }
242
- const byte2 = arr[i + 1]
243
- if ((byte2 & 0xc0) !== 0x80) {
244
- emitReplacement()
245
- i += 1
246
- continue
247
- }
248
- const codePoint = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f)
249
- result += String.fromCharCode(codePoint)
250
- i += 1
251
- continue
252
- }
253
- if (byte1 >= 0xe0 && byte1 <= 0xef) {
254
- if (i + 2 >= arr.length) {
255
- emitReplacement()
256
- continue
257
- }
258
- const byte2 = arr[i + 1]
259
- const byte3 = arr[i + 2]
260
- if ((byte2 & 0xc0) !== 0x80 || (byte3 & 0xc0) !== 0x80) {
261
- emitReplacement()
262
- i += 2
263
- continue
264
- }
265
- const codePoint =
266
- ((byte1 & 0x0f) << 12) |
267
- ((byte2 & 0x3f) << 6) |
268
- (byte3 & 0x3f)
269
-
270
- result += String.fromCharCode(codePoint)
271
- i += 2
272
- continue
273
- }
274
- if (byte1 >= 0xf0 && byte1 <= 0xf7) {
275
- if (i + 3 >= arr.length) {
276
- emitReplacement()
277
- continue
278
- }
279
- const byte2 = arr[i + 1]
280
- const byte3 = arr[i + 2]
281
- const byte4 = arr[i + 3]
282
- if (
283
- (byte2 & 0xc0) !== 0x80 ||
284
- (byte3 & 0xc0) !== 0x80 ||
285
- (byte4 & 0xc0) !== 0x80
286
- ) {
287
- emitReplacement()
288
- i += 3
289
- continue
290
- }
291
- const codePoint =
292
- ((byte1 & 0x07) << 18) |
293
- ((byte2 & 0x3f) << 12) |
294
- ((byte3 & 0x3f) << 6) |
295
- (byte4 & 0x3f)
296
- const offset = codePoint - 0x10000
297
- const highSurrogate = 0xd800 + (offset >> 10)
298
- const lowSurrogate = 0xdc00 + (offset & 0x3ff)
299
- result += String.fromCharCode(highSurrogate, lowSurrogate)
300
- i += 3
301
- continue
302
- }
303
- emitReplacement()
304
- }
305
- return result
180
+ return new TextDecoder().decode(new Uint8Array(arr))
306
181
  }
307
182
 
308
183
  /**