sigstore / sigstore-js

Code-signing for npm packages
Apache License 2.0
151 stars 20 forks source link

Browser-compatible version #1195

Open lsd-cat opened 6 days ago

lsd-cat commented 6 days ago

Description I need to use a minimal subset of Sigstore function, only for validation, inside a browser extension. While there are polyfills and stuff like browserify, I did not have much success with them, and I think that when doing delicate crypto I should not rely on automatic fillings.

I would like to work on achieving this, and could use some guidance and insights on the possible issues and, if there is interest, how to structure things in order to have them integrated here.

So far, I have started porting the core package, and these are my ideal steps on which I have experimented a bit:

  1. Swapping Buffer for the both node and browser native Uint8Array
  2. Porting the crypto to the Web Crypto API
  3. Build using vite
  4. Port the tests to something vite-compatible

I think that overall, having a verifying only minimal implementation should not be a very long job.

lsd-cat commented 5 days ago

Sample porting of core to Uint8Array only here: https://github.com/lsd-cat/sigstore-js/commit/934a73a769b6ff68f1389b5d23b125cd033f657f

image
lsd-cat commented 5 days ago

I have worked both on points 2 and 3, also porting the already existing tests to vitest as possible.

At the moment, the Sigstore core module successfully builds with vite. Also, almost all tests are passing, with the exception of some verify cases returning false instead of true that I will investigate soon.

The modified crypto.ts contains the crypto logic using the Web Crypto API. It's not perfect, and it probably cannot ever natively supports all algorithms that are currently supported by Sigstore, however most standard cases (P-256, P-384, P-521 - SHA-256, SHA-384, SHA-512) are either already covered or should be doable.

image
lsd-cat commented 5 days ago

I am having a hard time verifying signatures :/ somehow the verify() from the Web Crypto API seems to always fail, there might be an issue in the input format, but I would expect it to throw an exception instead.

I am testing with the publickey, data, and signature from https://github.com/sigstore/sigstore-js/blob/70cedf43463da1b57264074621da5adffb038ca8/packages/core/src/__tests__/x509/sct.test.ts#L118

And indeed it successfully verifies in python, and of course in the original Node native code, but not using crypto.subtle. I am attaching the test scripts for reference.

test.js.txt test.py.txt

Edit: this is the answer:

The main problem is that both codes use different signature formats: sign_payload() in the Python code generates an ECDSA signature in ASN.1/DER format. The WebCrypto API on the other hand can only handle the IEEE P1363 format.

lsd-cat commented 5 days ago

Fixed that, now all tests are passing using vitest and using browser-only native methods :D

Does not mean it's fully compatible, but it's a good start!

image
lsd-cat commented 4 days ago

Next step would be to port the verify package, and my understanding is that it depends on: