vendor¶
第三方程式庫,原封不動放進來,不做任何修改。改過就失去「這是上游那一份」的可審性, 讀者要驗的時候只能相信我們的說法。
| 檔案 | 來源 | 版本 | 授權 |
|---|---|---|---|
qrcode-generator.js |
kazuhikoarase/qrcode-generator | 1.4.4 | MIT |
jsQR.js |
cozmo/jsQR | 1.4.0 | Apache-2.0,授權全文見 jsQR-LICENSE.txt |
pdf-lib.min.js |
Hopding/pdf-lib | 1.17.1 | MIT,授權全文見 pdf-lib-LICENSE.txt |
pdfjs/pdf.min.mjs、pdfjs/pdf.worker.min.mjs |
mozilla/pdf.js(npm pdfjs-dist 的 legacy build) |
6.3.289 | Apache-2.0,授權全文見 pdfjs/pdfjs-LICENSE.txt |
age/age-encryption/ |
FiloSottile/typage(npm age-encryption) |
0.3.1 | BSD-3-Clause,授權全文見 age/age-encryption/LICENSE |
age/noble-ciphers/ |
paulmillr/noble-ciphers | 2.1.1 | MIT,age/noble-ciphers/LICENSE |
age/noble-curves/ |
paulmillr/noble-curves | 2.0.1 | MIT,age/noble-curves/LICENSE |
age/noble-hashes/ |
paulmillr/noble-hashes | 2.0.1 | MIT,age/noble-hashes/LICENSE |
age/noble-post-quantum/ |
paulmillr/noble-post-quantum | 0.5.3 | MIT,age/noble-post-quantum/LICENSE |
age/scure-base/ |
paulmillr/scure-base | 2.0.0 | MIT,age/scure-base/LICENSE |
pico/pico.js |
nenadmarkus/picojs | 2022-08-25 的 master(無版本號) | MIT |
pico/facefinder |
nenadmarkus/pico | commit c2e81f9 |
MIT |
為什麼不自己寫¶
QR 編碼寫錯的典型後果是產生一個「掃得出來但內容錯」的碼,比壞掉更糟。Reed-Solomon 與遮罩選擇那兩段特別容易出錯,而錯了不會有任何徵兆。這一份用了十幾年、被大量專案 採用,比重寫一份可靠。
tools/test_qrcode.mjs 另外寫了一個獨立的解碼器,把產生出來的矩陣讀回字串再比對,
所以「我們呼叫的方式對不對」有測試守著,不是純粹相信上游。
jsQR.js 走的是相反方向:把影像解回文字。它要處理定位、透視校正與容錯還原,那是比編碼
更大的工程,自己寫不切實際。tools/test_qrread.mjs 用 qrcode-generator 產生已知內容
的碼、算成像素、再交給 jsQR 讀回來比對,兩個各自獨立的函式庫互相驗證。
pdf-lib.min.js 處理的是 PDF。那個格式的每個物件在交叉索引表裡都記著位元組位置,
拿掉一段東西之後整張表要重算,而 PDF 1.5 之後常見的物件流還會把好幾個物件壓進同一段
壓縮資料裡。自己寫一個能正確處理這些的解析器不切實際,寫半套的後果是「宣告清乾淨、
內容還在」,那比不清更危險。
Apache-2.0 與 MIT 都要求散布時附上授權副本,所以 jsQR-LICENSE.txt 與
pdf-lib-LICENSE.txt 也在這個目錄裡,不要刪。
pico/ 底下兩個檔案的授權都是 MIT,但上游兩個 repo 都沒有放 LICENSE 檔,也沒有
版權人那一行,所以這裡沒有對應的授權全文可以附。授權的依據寫在兩個地方:
pico.js 第一行的註解(This library is released under the MIT license,那一行
原封不動留在檔案裡),以及 picojs 的 readme 的 License 一節寫著 MIT。要重新確認
的時候看那兩處。
pico.js 沒有發行版本號,取的是 2022-08-25 那次 push 的 master。級聯檔取自同一位
作者的 pico repo,網址上釘死 commit c2e81f9,那是 picojs 的範例自己指向的
版本。兩個檔案的 SHA-256:
785b981cc79e5fa3f7557dc3fa7773629d7529994d7627de41b77d8687649309 pico/pico.js
d8014993e7298c7b1865d1f8b855d6dbf4ec5c808bf879e2091ab6837abf90cd pico/facefinder
為什麼臉部偵測用 pico 而不是 TensorFlow.js¶
截圖遮蔽的「自動找出人臉」需要一個偵測器。主流做法是 TensorFlow.js 加 BlazeFace,
量過實際要載入的東西是 tf-core.min.js 287 KB、tf-converter.min.js 315 KB、
tf-backend-cpu.min.js 129 KB、模型權重 455 KB,合計約 1.2 MB。而且
@tensorflow-models/blazeface 的 repo 已經掛上棄用公告。
pico 這條是 240 KB,純 JavaScript,不需要 WebGL 也不需要 WASM,Tor Browser 只要 JavaScript 開著就能執行。代價是它只抓得到正面、直立、夠大的臉。
那個代價在這一頁的設計裡被吸收掉了:偵測只提候選框,讀者看得到、刪得掉、補得上, 按下產生的仍然是人。漏抓由人補,多抓一鍵刪掉。另外兩百行的 JavaScript 讀者自己 讀得完,那比較接近這一區「看得懂的人可以自己驗」的立場。
pdfjs/ 為什麼取最新版而不是小一點的舊版¶
PDF 頁面整理的「看裡面有什麼」要把文字層抽出來,pdf-lib 做不到,那需要一個完整的 解析器。v5 量到約 1.4 MB,v6 是 1.8 MB,差 0.4 MB。
還是取最新的 6.3.289。這支解析的是別人給的檔案,而 pdf.js 出過從字型那條路做到 任意程式碼執行的 CVE(CVE-2024-4367),版本落後的風險比 0.4 MB 重要。
呼叫的時候另外關掉 isEvalSupported 與 enableXfa,這一頁只要文字與縮圖,
不需要那些能力。tools/test_pdfpages.mjs 盯著這兩個選項。
兩個檔案的 SHA-256:
f401927e692efc7735e0cd528c490d0dd31b7f0972c122b7040df805be45cce4 pdfjs/pdf.min.mjs
a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e pdfjs/pdf.worker.min.mjs
age/ 底下的 ES module¶
typage 與它相依的五個套件沒有單一檔案的發行版,所以照 npm tarball 裡的目錄結構原封不動放進
age/,每個套件自己的 LICENSE 與 package.json 跟著放。只放 age-encryption/dist/index.js
從 import 一路連到的 38 支 .js(typage 的 .d.ts 與套件裡沒有被 import 的其他模組不放),
清單由 tools/test_agecrypt.mjs 從 import 重算一次比對,多一個或少一個都會紅。
頁面用 <script type="importmap"> 把 age-encryption 與 @noble/... 等名稱接到 age/ 底下的檔案,
js/agecrypt.js 再 import("age-encryption")。要驗跟上游是不是同一份,拿下面的 tarball
雜湊去對:
| tarball | sha256 |
|---|---|
age-encryption-0.3.1.tgz |
5a318d61f29bafc02810feef65dcf9d82b17a44d9c777eed658d2abea5f74bc5 |
noble-ciphers-2.1.1.tgz |
1704cc39be04737a17f17c37b8556b195e2b6ed442ecc2b7be6230b2e26f0d82 |
noble-curves-2.0.1.tgz |
1271ac0dfa27c93e464e64b65ff2a255eea52c449ca86c149cfb0b9786dd9029 |
noble-hashes-2.0.1.tgz |
638ffb3053a7e7478c9e54a6e297f3601299ee570a41112e501af7050d086a0a |
noble-post-quantum-0.5.3.tgz |
30efd5f906fb181552a0ade106bb6d004725303360f6c041346fd578fff3438e |
scure-base-2.0.0.tgz |
758d9a74d504922c21f12afbb832a8da13634657fa842c1aee1ec3eac82c8902 |
npm pack [email protected] @noble/[email protected] @noble/[email protected] @noble/[email protected] @noble/[email protected] @scure/[email protected]
換版時重新執行 tools/test_agecrypt.mjs,它用 Node 內建的 crypto 獨立實作了 age 的密語模式,
typage 的輸出要能被它解開、它的輸出也要能被 typage 解開,兩邊互驗才算通過。