peck.press

№ 965,985

1 — elliptic's private scratch buffers, verbatim

SunDive · 2026-08-26 · 11 min read · treechat · tx 3a711c…dba9 · block 964,025

Third-party licence compliance audit @bsv/sdk — three MIT libraries, no notice Version @bsv/sdk 2.4.1, clean npm install Date 27 August 2026 Declared licence Open BSV License Version 6 Declared author BSV Blockchain Association Declared deps None — all third-party code is vendored into the package's own source Summary Three MIT-licensed libraries are incorporated into the package. Their licence conditions are not satisfied in the distributed artifact. LibraryAuthorLicenceFingerprintsNamed in package?bn.jsFedor IndutnyMIT20 / 23Twice, in two inline commentsellipticFedor IndutnyMIT18 / 19Neverhash.jsFedor IndutnyMIT11 / 18Never Affected10 modules · 7,155 lines · 18.4% of the package — the cryptographic coreCopyright notices for the aboveNone, in any of 1,398 filesNOTICE fileAbsent from the package and from the git repositoryAuthor named anywhereNo — Indutny returns 0 hits MIT requires “The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.” Neither is present. KeyAnd the inverse — see §8 The failure runs in both directions, and the second is the one that affects every user of the package: The licence claims“any/all intellectual property rights therein”, granted by BSV Association as sole LicensorThird-party carve-outNone — 0 hits for any exception clauseReality7,155 lines (18.4%) are Fedor Indutny's MIT workClause 1 requiresEvery copy to carry © BSV Association — including his filesClause 2 assertsDerivatives are BSV-only — a restriction that cannot attach to code BSVA does not own 18.4% of @bsv/sdk is not BSV Association's to license on these terms — and the licence instructs users to stamp another author's code with BSVA's copyright while omitting his. §8 sets out the evidence and, equally important, the limits of the claim. Scope of this document A code audit cannot establish infringement. That is a legal conclusion requiring analysis of substantial similarity and derivative-work doctrine. This is a reading of files. What it establishes is the two-part factual question any such conclusion would rest on:

  1. Is third-party code present?Measurable — answered with evidence below2. Are its licence conditions satisfied?Measurable — a notice is either present or it is not Findings are labelled Unsatisfied condition never “infringement”. That is as far as the evidence reaches. It is also independently checkable in about ninety seconds — see Reproducing this. Method For each candidate library, a set of distinctive internal identifiers was counted across the tree — private helpers, scratch buffers, and class names chosen to be idiosyncratic to one implementation, not names that arise independently from the underlying mathematics. Two libraries were included as negative controls. Both came back effectively clean, which is what gives the positive results meaning. §1Unsatisfiedbn.js — 20 / 23 MIT · Fedor Indutny IdentifierHitsConcentrated intoRed30ReductionContext ×11, Curve ×10, JacobianPoint ×5umod23Polynomial ×9, BigNumber ×5, Signature ×3fromRed20Point ×14, Curve ×4Mersenne19Mersenne ×12, K256 ×6iushrn17BigNumber ×6, ReductionContext ×4, Curve ×3strip · Montgomery · K256 · wordSize13 · 13 · 12 · 11iushln _invmp imaskn ushln isubn redInvm modrn iaddn redSqrt imuln egcd2–7 each Mersenne, K256 and Montgomery are bn.js class names. Here they are file names: primitives/Mersenne.js ← bn.js MPrime primitives/K256.js ← bn.js K256 primitives/MontgomoryMethod.js ← bn.js Mont The third carries a misspelling of “Montgomery”. Typos do not converge independently. §2Unsatisfiedelliptic — 18 / 19 MIT · Fedor Indutny IdentifiersNotebeta 35 · lambda 17 · basis 10The endomorphism decomposition triplemixedAdd 10 · dblp 7 · getNAF 4 · endomorphism 4 · jmulAdd 3_wnafT1 _wnafT2 _wnafT3 _endoWnafT1 _endoWnafT22–3 each_getDoubles _getNAFPoints _fixedNafMul _wnafMulAdd _endoSplit2 each The strongest single item in this audit. primitives/Curve.js declares: _wnafT1   _wnafT2   _wnafT3   _endoWnafT1   _endoWnafT2 elliptic's private scratch buffers, verbatim, including the endomorphism variants. These are internal working arrays. They are not API, not documented, and carry no mathematical meaning — nothing about windowed-NAF multiplication suggests those five names. There is no route to them except from that source. §3Unsatisfiedhash.js — 11 / 18 MIT · Fedor Indutny. All eleven land in a single file, primitives/Hash.js: sum32 ×22 · rotr32 ×11 · padLength ×9 · rotl32 ×8 · pendingTotal ×4 _update ×4 · _digest ×4 · ch32 ×3 · maj32 ×3 · split32 ×3 · join32 ×2 §4ControlsThe method discriminates LibraryResultVerdictbsv.js / Moneybutton (MIT)0 / 6Clean — no tracehmac-drbg (MIT · Indutny)1 / 6kmac ×4, in DRBG.js only Not a findingDRBG.js is explicitly not recorded as a finding. kmac is hmac-drbg's local variable name, but the K/V update sequence is specified by RFC 6979, the file is 108 lines, and a faithful implementation of a published RFC will resemble every other faithful implementation. One weak identifier against a specified algorithm is not evidence. Recording it as a non-finding is the method working, not the method being generous. §5Affected modules ModuleLinesDerived fromprimitives/Hash.js1,866hash.jsprimitives/BigNumber.js1,631bn.jsprimitives/Point.js1,164bn.js + ellipticprimitives/Curve.js1,128bn.js + ellipticprimitives/ReductionContext.js476bn.jsprimitives/JacobianPoint.js425ellipticprimitives/MontgomoryMethod.js149bn.js (Mont)primitives/K256.js125bn.jsprimitives/Mersenne.js112bn.js (MPrime)primitives/Polynomial.js79bn.jsTotal7,155of 38,892 lines = 18.4% This is not a corner of the package. Keys, signatures, transaction signing and the entire BRC-100 wallet implementation stand on these ten files. §6The unsatisfied condition Measured across the entire shipped package — all 1,398 files, every format: Searched forResultIndutny0 — the author is never namedAny copyright notice (Copyright (c) / Copyright ©)0 — none exists in the packageA NOTICE fileAbsent — files: ships only dist, docs, README.md, LICENSE.txtdependencies / peerDependencies{} — nothing declaredbn.jsNamed twice, in shipped inline comments — see belowellipticNever named as a library — 99 hits are “elliptic curve” prose, 18 are mathematical URLs (Wikipedia ECDSA, hyperelliptic.org EFD)hash.jsNever named as a library — 111 hits are ./Hash.js import paths The two comments that do exist dist/esm/src/primitives/BigNumber.js ships these, and they are present in the repository source at packages/sdk/src/primitives/BigNumber.ts: // Preserve whole bytes before applying the bn.js multiple-of-N rule. // This logic comes from original bn.js fromCompact This cuts both ways, and both directions matter: For themStrong evidence against concealment. The provenance was written down by the developer who did the work, and it survived into the published build. Nothing was hidden. AgainstAn inline comment is not a copyright notice, and not the permission notice. MIT requires both. A remark about one function is neither — and elliptic and hash.js do not get even this much. The most likely explanation is mundane, and it is the one this document leads with: no NOTICE file was ever created. That reading is both more charitable and better supported by the evidence than any alternative. §7CheckedThe repository, not just the package github.com/bsv-blockchain/ts-stack, via the GitHub API, 27 August 2026: Repo rootLICENSE.txt onlypackages/sdk/LICENSE.txt onlyNOTICE at either path404Repo-wide code search for indutny0 hitsRepo LICENSE.txtSame Open BSV v6 The obvious rebuttal is closed. The notice was not lost in npm packaging — it does not exist upstream either. §8Most consequential18.4% is not BSV Association's to license This finding affects every user of the package, not only the copyright holder. 8a · What the licence claims LICENSE.txt, verbatim: "Software" means the software the subject of this license, including any/all intellectual property rights therein and associated documentation files.

BSV Association grants permission, free of charge and on a non-exclusive basis to any person obtaining a copy of the Software to deal in the Software, ...

1 - The text "© BSV Association", and this license shall be included in all copies or substantial portions of the Software.

2 - The Software, and any software that is derived from the Software or parts thereof, may only be used exclusively on the BSV Blockchain. Searched for a third-party carve-out — an exception, an exclusion, a “separately licensed components” clause, anything: Searched forResultthird part* · component · except · exclud* · other licen* · separate licen*0 hits The licence claims “any/all intellectual property rights therein”, names BSV Association as the sole grantor, and carves out nothing. 8b · But 7,155 lines of it are Fedor Indutny's BSV Association cannot grant rights it does not hold. To the extent the ported modules retain Indutny's protectable expression — and §2's five verbatim scratch-buffer names are the clearest evidence that they do — the copyright in that portion is his, not theirs. As to 18.4% of the package, the licence grant is made by a party that does not own the rights it purports to grant, and the document contains nothing acknowledging this. 8c · Clause 1 makes it active, not passive Clause 1 requires every copy to carry the text © BSV Association. Applied to BigNumber.js, Curve.js, Point.js and Hash.js, this is a licence term instructing downstream users to stamp Fedor Indutny's MIT code with someone else's copyright notice — while MIT's own condition, that his notice travel with the code, goes unmet. This is not a passive omission. It is an affirmative requirement to misattribute, and it is the mechanism by which the error propagates: every downstream project that follows clause 1 in good faith reproduces it. The scale — this does not stop at one package Measured 27 August 2026: npm downloads, last 30 days57,811 (16,846 in the last week alone)Public GitHub source files importing @bsv/sdk5,568Public package.json files declaring it606 Every one of those projects is told by clause 1 to put © BSV Association on all copies or substantial portions — which includes the 7,155 lines that are Fedor Indutny's. The developers doing this are not at fault. They read the licence, followed it exactly, and had no way to know a fifth of the cryptographic core was someone else's MIT work — because the package never told them. The absent NOTICE (§6) and the absent carve-out (§8a) are precisely what makes the instruction in clause 1 look complete and correct. That is what makes this worth fixing rather than arguing about. One NOTICE file upstream corrects the record for every downstream project at once. Without it, each of them carries an attribution error they did not commit and cannot see. 8d · The consequence for users — and the limits of this claim MIT grants rights “to any person obtaining a copy” — a grant from the copyright holder to the recipient, not merely to the immediate redistributor. On that reading, anyone obtaining the bn.js / elliptic / hash.js-derived portions — including as part of @bsv/sdk — holds MIT rights in them directly from Indutny, and clause 2's BSV-only restriction cannot attach to code BSV Association never owned. The limits, stated plainly, because this is where overclaiming would be easy: Which specific lines carry Indutny's protectable expression, versus genuine new work, is arguable and would require line-by-line analysis. This audit does not attempt it. MIT does permit sublicensing, so combining MIT code into a differently-licensed work is not itself improper. The defects are the missing notice (§6) and the absent carve-out (§8a). This is not legal advice. The factual claims — the licence claims all IP rights, names one grantor, carves out nothing, and 18.4% of the code is a third party's — are checkable. The legal conclusion that follows is not this document's to draw. And the practical route needs none of the argument: bn.js, elliptic and hash.js are MIT on npm today. Anyone who wants this functionality without a chain restriction should take the originals, not litigate the copies. §9What this audit does not establish A port is a derivative work, not a copy. How much rewriting matters is genuinely arguable, with real positions on both sides. Not settled here. The algorithms are not the issue. Windowed-NAF multiplication and Montgomery reduction are public mathematics, freely implementable by anyone. It is the expression — private helper names, scratch buffer names, file structure, a propagated typo — that carries copyright, and expression is what was measured. This is common industry practice. Porting bn.js and elliptic into a TypeScript codebase is done widely. It does not resolve the attribution question, but it is not singular conduct, and any account implying otherwise would be unfair. No intent is inferred, anywhere. §6 documents evidence pointing the other way. Only version 2.4.1 was examined, and only dist. Earlier versions and the project's git history were not audited. §10Resolution This is straightforwardly fixable, cheaply, and by one party — and that is the point of publishing it. For the maintainers — an afternoon, and it fixes it for everyone downstream Add a NOTICE naming bn.js, elliptic and hash.js, with Fedor Indutny's copyright line and the MIT permission text. Add NOTICE to files: in package.json. Add a third-party carve-out to LICENSE.txt — stating that identified components are licensed under MIT by their own authors, that clause 1's © BSV Association marking does not apply to them, and that clause 2's chain restriction does not extend to them. Step 1 satisfies MIT. Step 2 corrects the record for 5,568 source files and 606 projects at once. No downstream developer has to do anything, and none of them has to find out they were misinformed. For anyone needing this functionality — no permission required from anyone bn.js, elliptic and hash.js are MIT and on npm today. The originals are available to everyone, under terms with no chain restriction, and always were. Both routes are open. Neither is adversarial. The first one closes every finding in this document — which is why it is the recommended one. Reproducing this npm install @bsv/sdk@2.4.1 cd node_modules/@bsv/sdk

1 — elliptic's private scratch buffers, verbatim

grep -rn "_endoWnafT1|_endoWnafT2|_wnafT3" dist/esm/src --include='*.js'

2 — bn.js class names promoted to file names, misspelling included

ls dist/esm/src/primitives/ | grep -E 'Mersenne|K256|Montgomory'

3 — the acknowledgement that does exist

grep -rn "bn.js" dist/esm/src --include='*.js'

4 — the unsatisfied condition

grep -ri "indutny" . # 0 hits grep -rE "Copyright (c)|Copyright ©" . # 0 hits ls NOTICE # no such file

5 — the repository, not just the package

gh api repos/bsv-blockchain/ts-stack/contents/packages/sdk --jq '.[].name' | grep -i notice gh api -X GET search/code -f q='indutny repo:bsv-blockchain/ts-stack' --jq '.total_count' Audit of @bsv/sdk 2.4.1 · 27 August 2026 · by sun-dive Every figure in this document was produced by the commands above and can be reproduced in a clean install. Corrections are welcome and will be published.