Skip to content

Commit

Permalink
minor gist data response fix; add claim revocation status
Browse files Browse the repository at this point in the history
  • Loading branch information
freigeistig committed Feb 16, 2024
1 parent d5ef589 commit 26d7c40
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 52 deletions.
2 changes: 2 additions & 0 deletions docs/spec/components/schemas/GistProof.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ properties:
type: array
items:
type: string
index:
type: string
value:
type: string
aux_existence:
Expand Down
5 changes: 5 additions & 0 deletions internal/assets/migrations/003_claim_revoked.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- +migrate Up
alter table claims add column revoked boolean default false;

-- +migrate Down
alter table claims drop column revoked;
2 changes: 2 additions & 0 deletions internal/data/claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type ClaimQ interface {
Insert(value Claim) error
FilterBy(column string, value any) ClaimQ
Get() (*Claim, error)
Select() ([]Claim, error)
DeleteByID(id uuid.UUID) error
ForUpdate() ClaimQ
ResetFilter() ClaimQ
Expand All @@ -17,4 +18,5 @@ type Claim struct {
UserDID string `db:"user_did" structs:"user_did"`
IssuerDID string `db:"issuer_did" structs:"issuer_did"`
Document string `db:"document" structs:"document"`
Revoked bool `db:"revoked" structs:"revoked"`
}
6 changes: 6 additions & 0 deletions internal/data/pg/claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ func (q *claimsQ) Get() (*data.Claim, error) {
return &result, err
}

func (q *claimsQ) Select() ([]data.Claim, error) {
var result []data.Claim
err := q.db.Select(&result, q.sql)
return result, err
}

func (q *claimsQ) DeleteByID(id uuid.UUID) error {
if err := q.db.Exec(sq.Delete(claimsTableName).Where(sq.Eq{"id": id})); err != nil {
return err
Expand Down
117 changes: 65 additions & 52 deletions internal/service/api/handlers/create_identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) {
iss := Issuer(r)
masterQ := MasterQ(r)

claim, err := masterQ.Claim().ResetFilter().FilterBy("user_did", req.Data.ID).Get()
claim, err := masterQ.Claim().ResetFilter().
FilterBy("user_did", req.Data.ID).
FilterBy("revoked", false).
Get()
if err != nil {
Log(r).WithError(err).Error("failed to get claim by user DID")
ape.RenderErr(w, problems.InternalError())
Expand All @@ -87,75 +90,85 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) {
return
}

if err := masterQ.Transaction(func(db data.MasterQ) error {
cfg := VerifierConfig(r)
cfg := VerifierConfig(r)

if err := verifySignature(req); err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to verify signature")
}
if err := verifySignature(req); err != nil {
Log(r).WithError(err).Error("failed to verify signature")
ape.RenderErr(w, problems.InternalError())
return
}

switch algorithms[req.Data.DocumentSOD.Algorithm] {
case SHA1withECDSA:
if err := verifier.VerifyGroth16(req.Data.ZKProof, cfg.VerificationKeys[SHA1]); err != nil {
ape.RenderErr(w, problems.BadRequest(err)...)
return errors.Wrap(err, "failed to verify Groth16")
}
case SHA256withRSA, SHA256withECDSA:
if err := verifier.VerifyGroth16(req.Data.ZKProof, cfg.VerificationKeys[SHA256]); err != nil {
ape.RenderErr(w, problems.BadRequest(err)...)
return errors.Wrap(err, "failed to verify Groth16")
}
switch algorithms[req.Data.DocumentSOD.Algorithm] {
case SHA1withECDSA:
if err := verifier.VerifyGroth16(req.Data.ZKProof, cfg.VerificationKeys[SHA1]); err != nil {
Log(r).WithError(err).Error("failed to verify Groth16")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}

encapsulatedContentBytes, err := hex.DecodeString(req.Data.DocumentSOD.EncapsulatedContent)
if err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to decode hex string")
case SHA256withRSA, SHA256withECDSA:
if err := verifier.VerifyGroth16(req.Data.ZKProof, cfg.VerificationKeys[SHA256]); err != nil {
Log(r).WithError(err).Error("failed to verify Groth16")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}
}

encapsulatedData := resources.EncapsulatedData{}
_, err = asn1.Unmarshal(encapsulatedContentBytes, &encapsulatedData)
if err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to unmarshal ASN.1")
}
encapsulatedContentBytes, err := hex.DecodeString(req.Data.DocumentSOD.EncapsulatedContent)
if err != nil {
Log(r).WithError(err).Error("failed to decode hex string")
ape.RenderErr(w, problems.InternalError())
return
}

if err := validatePubSignals(cfg, req.Data, encapsulatedData.PrivateKey.El1.OctetStr.Bytes); err != nil {
ape.RenderErr(w, problems.BadRequest(err)...)
return errors.Wrap(err, "failed to validate pub signals")
}
encapsulatedData := resources.EncapsulatedData{}
_, err = asn1.Unmarshal(encapsulatedContentBytes, &encapsulatedData)
if err != nil {
Log(r).WithError(err).Error("failed to unmarshal ASN.1")
ape.RenderErr(w, problems.InternalError())
return
}

if err := validateCert([]byte(req.Data.DocumentSOD.PemFile), cfg.MasterCerts); err != nil {
ape.RenderErr(w, problems.BadRequest(err)...)
return errors.Wrap(err, "failed to validate certificate")
}
if err := validatePubSignals(cfg, req.Data, encapsulatedData.PrivateKey.El1.OctetStr.Bytes); err != nil {
Log(r).WithError(err).Error("failed to validate pub signals")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}

identityExpiration, err := getExpirationTimeFromPubSignals(req.Data.ZKProof.PubSignals)
if err != nil {
ape.RenderErr(w, problems.BadRequest(err)...)
return errors.Wrap(err, "failed to get expiration time")
}
if err := validateCert([]byte(req.Data.DocumentSOD.PemFile), cfg.MasterCerts); err != nil {
Log(r).WithError(err).Error("failed to validate certificate")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}

issuingAuthority, err := strconv.Atoi(req.Data.ZKProof.PubSignals[2])
if err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to convert string to int")
}
identityExpiration, err := getExpirationTimeFromPubSignals(req.Data.ZKProof.PubSignals)
if err != nil {
Log(r).WithError(err).Error("failed to get expiration time")
ape.RenderErr(w, problems.BadRequest(err)...)
return
}

// check if there is a claim for this document already
claim, err := db.Claim().ResetFilter().
issuingAuthority, err := strconv.Atoi(req.Data.ZKProof.PubSignals[2])
if err != nil {
Log(r).WithError(err).Error("failed to convert string to int")
ape.RenderErr(w, problems.InternalError())
return
}

if err := masterQ.Transaction(func(db data.MasterQ) error {
// check if there are any claims for this document already
claims, err := db.Claim().ResetFilter().
FilterBy("document", req.Data.DocumentSOD.SignedAttributes).
FilterBy("revoked", false).
ForUpdate().
Get()
Select()
if err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to get claim")
}

// revoke if so
if claim != nil {
if err := revokeOutdatedClaim(db, iss, claim.ID); err != nil {
for _, claimToRevoke := range claims {
if err := revokeOutdatedClaim(db, iss, claimToRevoke.ID); err != nil {
ape.RenderErr(w, problems.InternalError())
return errors.Wrap(err, "failed to revoke outdated claim")
}
Expand Down
1 change: 1 addition & 0 deletions internal/service/api/handlers/get_gist_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func newGistDataResponse(userDID string, proof abi.IStateGistProof, root *big.In
Root: proof.Root.String(),
Existence: proof.Existence,
Siblings: siblings,
Index: proof.Index.String(),
Value: proof.Value.String(),
AuxExistence: proof.AuxExistence,
AuxIndex: proof.AuxIndex.String(),
Expand Down
1 change: 1 addition & 0 deletions resources/model_gist_proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type GistProof struct {
AuxIndex string `json:"aux_index"`
AuxValue string `json:"aux_value"`
Existence bool `json:"existence"`
Index string `json:"index"`
Root string `json:"root"`
Siblings []string `json:"siblings"`
Value string `json:"value"`
Expand Down

0 comments on commit 26d7c40

Please sign in to comment.