Skip to content

Commit

Permalink
Add GQ proofs-of-authentication.
Browse files Browse the repository at this point in the history
Proof of concept for sigstore#1071 .

To test:

```
$ go run main.go serve --port 5555 --ca ephemeralca --ct-log-url=""
$ ./cosign sign-blob \                                                                                                                                                                        ~/git/cosign
    --fulcio-url http://localhost:5555 \
    --insecure-skip-verify \
    --tlog-upload=false \
    --output-certificate crt.pem.b64 \
    --output-signature sig \
    --yes \
    /dev/null
$ step certificate inspect --format json <(base64 -d crt.pem.b64)
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 591924787950286913218593311682257250005470899824 (0x67aed352de3c3eb6c935b5b93f64624b80576e70)
    Signature Algorithm: ECDSA-SHA256
        Issuer: C=USA,ST=WA,L=Kirkland,STREET=767 6th St S,POSTALCODE=98033,O=sigstore
        Validity
            Not Before: Jul 13 03:02:12 2023 UTC
            Not After : Jul 13 03:12:12 2023 UTC
        Subject:
        Subject Public Key Info:
            Public Key Algorithm: ECDSA
                Public-Key: (256 bit)
                X:
                    5d:00:66:db:8e:01:2d:7a:51:26:b6:96:65:ad:fd:
                    66:28:db:c4:10:fd:6c:7e:b7:74:be:7e:38:c4:e8:
                    bc:4d
                Y:
                    df:ad:e0:e4:fa:94:d9:36:81:0e:96:77:31:13:bc:
                    13:ea:04:69:4c:4e:a0:62:1b:98:8c:1c:d3:f0:13:
                    3d:31
                Curve: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage:
                Code Signing
            X509v3 Subject Key Identifier:
                22:47:23:46:A6:C4:8A:FE:DD:1E:E3:A0:39:B6:98:5B:13:61:83:B4
            X509v3 Authority Key Identifier:
                keyid:93:54:F8:AF:1B:DC:2B:C2:71:FB:8F:E7:70:5F:08:86:14:AA:3B:79
            X509v3 Subject Alternative Name: critical
                email:zjn@chainguard.dev
            Sigstore OIDC Issuer:
                https://accounts.google.com
            1.3.6.1.4.1.57264.1.8:
                ..https://accounts.google.com
            1.3.9901:
                ....eyJhbGciOiJSUzI1NiIsImtpZCI6ImEzNDUzNjE0YzVkOThhYThiNzQyYjJiYTVhZTFjNTY2NzFmYjgyYWYifQ.eyJpc3MiOiJodHRwczovL29hdXRoMi5zaWdzdG9yZS5kZXYvYXV0aCIsInN1YiI6IkNoVXhNVGd5TnpFek1qSTFNVFV6TmpFeE1EazJNekVTSDJoMGRIQnpPaVV5UmlVeVJtRmpZMjkxYm5SekxtZHZiMmRzWlM1amIyMCIsImF1ZCI6InNpZ3N0b3JlIiwiZXhwIjoxNjg5MjE3MzkyLCJpYXQiOjE2ODkyMTczMzIsIm5vbmNlIjoiMlNWMkdOdDRtV2t6STE1Wk5FZ0dTU3FMbHVCIiwiYXRfaGFzaCI6InZET1lZbnRlX0c4RkNGOFgxSnlqMHciLCJjX2hhc2giOiJJQkNJRmRLVUl3dnpxX290TjZBREZ3IiwiZW1haWwiOiJ6am5AY2hhaW5ndWFyZC5kZXYiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZmVkZXJhdGVkX2NsYWltcyI6eyJjb25uZWN0b3JfaWQiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJ1c2VyX2lkIjoiMTE4MjcxMzIyNTE1MzYxMTA5NjMxIn19
            1.3.9902:
                ....{"Data":{"Round1":{"Pub":{"N":28070169755581386667437819450594913842446058566312248362488431550452327180771668694566958982231153239223207750514843228889849138467821049164767718727244839495922422496304381549328654085511887755075971204801723207114576081583911873129739320162443294174496792029835924675740072553464008368490661565630606061935141754560520595862703723981716412325623767556613166179401496695829458751124848584649668298938416237727401130044300603750914600510582900320509286362001468253982253031417502341212077586248942527869541614414254482042263206306154518897469365521680684942548823841919122471527179903649562711489277652019751462647739,"V":65537,"X":986236757547332986472011617696226561292849812918563355472727826767720188564083584387121625107510786855734801053524719833194566624465665316622563244215340671405971599343902468620306327831715457360719532421388780770165778156818229863337344187575566725786793391480600129482653072861971002459947277805295727097226389568776499707662505334062639449916265137796823793276300221537201727072401742985542559596685092673521228140822200236743113743661549252453726123450722876929538747702356573783116197523966334991563351853851212597377279504828784737035057630632270649616902422974306504680292018366321657348804190525202425699},"Msg1":{"T":2351076426232626148752483123315923449891310622328956880091101853373383247112012179424044324821006974774293124100582355517074320400151805903752206752519359906866266355131814824142359891140408021169969026923603493083607859590541997601652785145556988411763394573993032192436328983449099723590584914539545744196468848429652503889874096862905913537056029653464052940400576470910836246301669489448525151467864234919761978720209173001593225591389889308142322072838320986145158317496860440927831452769413779581145703178021032034600819119398863254219505712692893599595889886210602693471576404593924841607524137029909992803963}},"D":83,"Msg2":{"T":18959599301938102359557306258727591685947268304912402802229111659306878630842974344671290933616860374219837425749602925125131463212045780964350522234550666883161207109290182944695295226265223633341170476623254934623340647216243823514191972880710976273840382028518009858687372256758231291478829745548537842205646651604955581491737928734515931900834419145338861082397683997577789545907136662845403488217686102159618500589437050379925691843568643952251864205297536417828150834590850305495292849471744452792814804441968742070796386634978604153177013805125605023745430986337734931444997274902771795258148120953054587602138}}}
    Signature Algorithm: ECDSA-SHA256
         30:45:02:21:00:eb:bc:81:81:fa:2d:c2:d5:15:04:58:15:d7:
         fa:97:9f:15:5a:ca:59:2f:e4:7f:6f:80:28:24:79:81:4b:48:
         c9:02:20:02:52:c1:e3:ea:16:ef:41:5c:a6:6d:54:1f:15:b5:
         5f:30:ae:12:0f:58:df:87:04:c3:e8:6d:79:5d:e8:03:6d
```

In particular, look for the `1.3.9001` and `1.3.9002` extensions above, which
now embed (respectively) a JWT token header/body (no signature!) and a GQ
proof-of-knowledge-of-signature.

This change includes:

- Reimplementing RSA signature validation for JWTs.
- Turning RSA signatures for JWTs into GQ proofs-of-knowledge-of-signatures.
  Involves implementing GQ scheme manually, along with a probably-insecure
  implementation of the Fiat-Shamir transform.
- Adding the JWT and GQ proof into the certificate. This is crammed in awkardly,
  doing inefficient things like re-fetching the JWKs (and hard-coding the JWK
  URL for the issuer used for testing).
  • Loading branch information
znewman01 committed Jul 13, 2023
1 parent 948b43d commit 7c21cc6
Show file tree
Hide file tree
Showing 11 changed files with 520 additions and 10 deletions.
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
Expand All @@ -106,6 +108,12 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx v1.2.26 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
Expand Down
31 changes: 31 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -177,6 +180,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/goadesign/goa v2.2.5+incompatible h1:SLgzk0V+QfFs7MVz9sbDHelbTDI9B/d4W7Hl5udTynY=
github.com/goadesign/goa v2.2.5+incompatible/go.mod h1:d/9lpuZBK7HFi/7O0oXfwvdoIl+nx2bwKqctZe/lQao=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
Expand Down Expand Up @@ -330,6 +335,19 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx v1.2.26 h1:4iFo8FPRZGDYe1t19mQP0zTRqA7n8HnJ5lkIiDvJcB0=
github.com/lestrrat-go/jwx v1.2.26/go.mod h1:MaiCdGbn3/cckbOFSCluJlJMmp9dmZm5hDuIkx8ftpQ=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf h1:ndns1qx/5dL43g16EQkPV/i8+b3l5bYQwLeoSBe7tS8=
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf/go.mod h1:aGkAgvWY/IUcVFfuly53REpfv5edu25oij+qHRFaraA=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
Expand Down Expand Up @@ -438,6 +456,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg=
Expand Down Expand Up @@ -511,6 +530,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down Expand Up @@ -547,6 +567,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -584,6 +605,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand All @@ -608,6 +631,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -653,11 +677,15 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -670,6 +698,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -729,6 +759,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
27 changes: 27 additions & 0 deletions pkg/certificate/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ var (
OIDBuildConfigDigest = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}
OIDBuildTrigger = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}
OIDRunInvocationURI = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}

// Experimental
OIDJWTNoSig = asn1.ObjectIdentifier{1, 3, 9901}
OIDGQProof = asn1.ObjectIdentifier{1, 3, 9902}
)

// Extensions contains all custom x509 extensions defined by Fulcio
Expand Down Expand Up @@ -128,6 +132,9 @@ type Extensions struct {

// Run Invocation URL to uniquely identify the build execution.
RunInvocationURI string // 1.3.6.1.4.1.57264.1.21

JWTNoSig string // 1.3.9901
GQProof string // 1.3.9902
}

func (e Extensions) Render() ([]pkix.Extension, error) {
Expand Down Expand Up @@ -320,6 +327,26 @@ func (e Extensions) Render() ([]pkix.Extension, error) {
Value: val,
})
}
if e.JWTNoSig != "" {
val, err := asn1.MarshalWithParams(e.JWTNoSig, "utf8")
if err != nil {
return nil, err
}
exts = append(exts, pkix.Extension{
Id: OIDJWTNoSig,
Value: val,
})
}
if e.GQProof != "" {
val, err := asn1.MarshalWithParams(e.GQProof, "utf8")
if err != nil {
return nil, err
}
exts = append(exts, pkix.Extension{
Id: OIDGQProof,
Value: val,
})
}

return exts, nil
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/challenges/challenges.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/sigstore/fulcio/pkg/config"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/fulcio/pkg/identity/buildkite"
"github.com/sigstore/fulcio/pkg/identity/email"
// "github.com/sigstore/fulcio/pkg/identity/email"
"github.com/sigstore/fulcio/pkg/identity/github"
"github.com/sigstore/fulcio/pkg/identity/gitlabcom"
"github.com/sigstore/fulcio/pkg/identity/kubernetes"
Expand Down Expand Up @@ -63,8 +63,8 @@ func PrincipalFromIDToken(ctx context.Context, tok *oidc.IDToken) (identity.Prin
principal, err = buildkite.JobPrincipalFromIDToken(ctx, tok)
case config.IssuerTypeGitLabPipeline:
principal, err = gitlabcom.JobPrincipalFromIDToken(ctx, tok)
case config.IssuerTypeEmail:
principal, err = email.PrincipalFromIDToken(ctx, tok)
// case config.IssuerTypeEmail:
// principal, err = email.PrincipalFromIDToken(ctx, tok)
case config.IssuerTypeSpiffe:
principal, err = spiffe.PrincipalFromIDToken(ctx, tok)
case config.IssuerTypeGithubWorkflow:
Expand Down
2 changes: 1 addition & 1 deletion pkg/identity/email/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ func (e *emailIssuer) Authenticate(ctx context.Context, token string) (identity.
if err != nil {
return nil, err
}
return PrincipalFromIDToken(ctx, idtoken)
return PrincipalFromIDToken(ctx, idtoken, token)
}
69 changes: 63 additions & 6 deletions pkg/identity/email/principal.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,32 @@ package email

import (
"context"
"crypto/rsa"
"crypto/x509"
"encoding/json"

// "encoding/json"
"errors"
"fmt"
"math/big"

"github.com/asaskevich/govalidator"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/lestrrat-go/jwx/jwk"
"github.com/sigstore/fulcio/pkg/certificate"
"github.com/sigstore/fulcio/pkg/config"
"github.com/sigstore/fulcio/pkg/identity"
"github.com/sigstore/fulcio/pkg/oauthflow"
"github.com/sigstore/fulcio/pkg/poa"
)

type principal struct {
address string
issuer string
rawJWT string
}

func PrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Principal, error) {
func PrincipalFromIDToken(ctx context.Context, token *oidc.IDToken, rawJWT string) (identity.Principal, error) {
emailAddress, emailVerified, err := oauthflow.EmailFromIDToken(token)
if err != nil {
return nil, err
Expand All @@ -59,20 +67,69 @@ func PrincipalFromIDToken(ctx context.Context, token *oidc.IDToken) (identity.Pr
return principal{
issuer: issuer,
address: emailAddress,
rawJWT: rawJWT,
}, nil
}

func (p principal) Name(_ context.Context) string {
return p.address
}

func (p principal) Embed(_ context.Context, cert *x509.Certificate) error {
type jwtHeader struct {
Alg string // `json`:"alg"`
Kid string // `json`:"kid"`
}

func (p principal) Embed(ctx context.Context, cert *x509.Certificate) error {
cert.EmailAddresses = []string{p.address}

var err error
cert.ExtraExtensions, err = certificate.Extensions{
Issuer: p.issuer,
}.Render()
jwt := poa.ParseJWT(p.rawJWT)

var header jwtHeader
err := json.Unmarshal(jwt.Header, &header)
if err != nil {
return err
}

// TODO: use the cached JWKs. There's no easy access so we just re-request here.
set, err := jwk.Fetch(ctx, "https://oauth2.sigstore.dev/auth/keys")
if err != nil {
return err
}
var matchingKey jwk.Key
found := false
for it := set.Iterate(ctx); it.Next(ctx); {
pair := it.Pair()
key := pair.Value.(jwk.Key)

if key.KeyID() == header.Kid {
found = true
matchingKey = key
}
}

ext := certificate.Extensions{
Issuer: p.issuer,
JWTNoSig: string(jwt.SignedPart()),
}
if found {
// Base64urlUInt-encoded
rsaPubJwk := matchingKey.(jwk.RSAPublicKey)
e := new(big.Int).SetBytes(rsaPubJwk.E())
n := new(big.Int).SetBytes(rsaPubJwk.N())
rsaPub := rsa.PublicKey{n, int(e.Int64())}
if !jwt.Verify(&rsaPub) {
return fmt.Errorf("uh oh")
}

proof := jwt.GQProve(&rsaPub)
proofJson, jsonErr := json.Marshal(proof)
if jsonErr != nil {
return jsonErr
}
ext.GQProof = string(proofJson)
}
cert.ExtraExtensions, err = ext.Render()
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 7c21cc6

Please # to comment.