Skip to content

Commit

Permalink
feat: working verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
natesales committed Jan 16, 2025
1 parent ec2d892 commit a65e748
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 141 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

## Online In-Browser Verification

https://tinfoilanalytics.github.io/verifier/
https://tinfoilanalytics.github.io/verifier

## Local Verification

```bash
go run cmd/main.go \
-u https://inference-enclave.tinfoil.sh/.well-known/tinfoil-attestation \
-r tinfoilanalytics/nitro-enclave-build-demo \
-d 55b9a80c11415508cf178f1c94c6c8837a21a8bbae51130234d93404dc922baf
-r tinfoilanalytics/nitro-enclave-build-demo
```
123 changes: 77 additions & 46 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,45 @@ import (
"io"
"log"
"net/http"
"os"
"strings"
"regexp"

"github.com/tinfoilanalytics/verifier/pkg/attestation"
"github.com/tinfoilanalytics/verifier/pkg/sigstore"
)

var (
attestationDoc = flag.String("attestation", "", "Path to the attestation document or URL")
digest = flag.String("digest", "", "Artifact digest")
repo = flag.String("repo", "", "Attested repo (e.g. tinfoilanalytics/nitro-private-inference-image)")
attestationDoc = flag.String("u", "", "Attestation document URL")
repo = flag.String("r", "", "Attested repo (e.g. tinfoilanalytics/nitro-private-inference-image)")
)

func fetchLatestRelease(repo string) (string, string, error) {
url := "https://api.github.com/repos/" + repo + "/releases/latest"
log.Printf("Fetching latest release for %s", repo)
releaseResponse, err := http.Get(url)
if err != nil {
return "", "", err
}
if releaseResponse.StatusCode != 200 {
return "", "", fmt.Errorf("failed to fetch latest release: %s", releaseResponse.Status)
}

var responseJSON struct {
TagName string `json:"tag_name"`
Body string `json:"body"`
}
if err := json.NewDecoder(releaseResponse.Body).Decode(&responseJSON); err != nil {
return "", "", err
}

eifRegex := regexp.MustCompile(`EIF hash: ([a-fA-F0-9]{64})`)
eifHash := eifRegex.FindStringSubmatch(responseJSON.Body)[1]

return responseJSON.TagName, eifHash, nil
}

func gitHubAttestation(digest string) ([]byte, error) {
url := "https://api.github.com/repos/" + *repo + "/attestations/sha256:" + digest
log.Printf("Fetching sigstore bundle from %s", url)
log.Printf("Fetching sigstore bundle from %s for EIF %s", *repo, digest)
bundleResponse, err := http.Get(url)
if err != nil {
return nil, err
Expand All @@ -49,67 +72,75 @@ func main() {

var codeMeasurements, enclaveMeasurements *attestation.Measurement

if *digest != "" {
if *repo == "" {
log.Fatal("Missing repo")
}
latestTag, eifHash, err := fetchLatestRelease(*repo)
if err != nil {
log.Fatalf("Failed to fetch latest release: %v", err)
}

bundleBytes, err := gitHubAttestation(*digest)
if err != nil {
panic(err)
}
log.Printf("Latest release: %s", latestTag)
log.Printf("EIF hash: %s", eifHash)

sigstoreResponse, err := http.Get("https://tuf-repo-cdn.sigstore.dev/targets/4364d7724c04cc912ce2a6c45ed2610e8d8d1c4dc857fb500292738d4d9c8d2c.trusted_root.json")
if err != nil {
panic(err)
}
sigstoreRootBytes, err := io.ReadAll(sigstoreResponse.Body)
if err != nil {
panic(err)
}
if *repo == "" {
log.Fatal("Missing repo")
}

codeMeasurements, err = sigstore.VerifyAttestedMeasurements(
sigstoreRootBytes,
bundleBytes,
*digest,
*repo,
)
if err != nil {
panic(err)
}
log.Println("Sigstore", codeMeasurements)
bundleBytes, err := gitHubAttestation(eifHash)
if err != nil {
panic(err)
}

sigstoreResponse, err := http.Get("https://tuf-repo-cdn.sigstore.dev/targets/4364d7724c04cc912ce2a6c45ed2610e8d8d1c4dc857fb500292738d4d9c8d2c.trusted_root.json")
if err != nil {
panic(err)
}
sigstoreRootBytes, err := io.ReadAll(sigstoreResponse.Body)
if err != nil {
panic(err)
}

log.Println("Verifying code measurements")
codeMeasurements, err = sigstore.VerifyAttestedMeasurements(
sigstoreRootBytes,
bundleBytes,
eifHash,
*repo,
)
if err != nil {
log.Fatalf("Failed to verify source measurements: %v", err)
}

if *attestationDoc != "" {
var attDocJSON []byte
var err error
if strings.HasPrefix(*attestationDoc, "http") {
log.Printf("Fetching attestation doc from %s", *attestationDoc)
resp, err := http.Get(*attestationDoc)
if err != nil {
panic(err)
}
defer resp.Body.Close()
attDocJSON, err = io.ReadAll(resp.Body)
} else {
log.Printf("Reading attestation doc from %s", *attestationDoc)
attDocJSON, err = os.ReadFile(*attestationDoc)
log.Printf("Fetching attestation doc from %s", *attestationDoc)
resp, err := http.Get(*attestationDoc)
if err != nil {
panic(err)
}
defer resp.Body.Close()

attDocJSON, err = io.ReadAll(resp.Body)
if err != nil {
panic(err)
}

enclaveMeasurements, _, err = attestation.VerifyAttestationJSON(attDocJSON)
log.Println("Verifying enclave measurements")
var tlsPubkey []byte
enclaveMeasurements, tlsPubkey, err = attestation.VerifyAttestationJSON(attDocJSON)
if err != nil {
log.Fatalf("Failed to parse enclave attestation doc: %v", err)
}

log.Printf("TLS public key fingerprint: %x", tlsPubkey)
}

if codeMeasurements != nil && enclaveMeasurements != nil {
if err := codeMeasurements.Equals(enclaveMeasurements); err != nil {
log.Println("PCR values match! Verification success")
} else {
log.Printf("PCR register mismatch. Verification failed: %v", err)
log.Printf("Code: %s", codeMeasurements.Fingerprint())
log.Printf("Enclave: %s", enclaveMeasurements.Fingerprint())
} else {
log.Println("Verification successful, measurements match")
}
}
}
92 changes: 0 additions & 92 deletions main.go

This file was deleted.

8 changes: 8 additions & 0 deletions pkg/attestation/attestation.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package attestation

import (
"crypto/sha256"
"encoding/json"
"errors"
"fmt"
"slices"
"strings"
)

type PredicateType string
Expand All @@ -23,6 +25,12 @@ type Measurement struct {
Registers []string
}

// Fingerprint computes the SHA-256 hash of all measurements
func (m *Measurement) Fingerprint() string {
all := string(m.Type) + strings.Join(m.Registers, "")
return fmt.Sprintf("%x", sha256.Sum256([]byte(all)))
}

func (m *Measurement) Equals(other *Measurement) error {
if m.Type != other.Type {
return ErrFormatMismatch
Expand Down

0 comments on commit a65e748

Please sign in to comment.