Skip to content

Commit

Permalink
Merge pull request #2 from RarimoVoting/feature/credential-hash
Browse files Browse the repository at this point in the history
add document nullifier and credential hash fields to credential subject
  • Loading branch information
1KitCat1 authored Feb 12, 2024
2 parents c18cf41 + 6266d12 commit 0c21108
Show file tree
Hide file tree
Showing 7 changed files with 24,112 additions and 55 deletions.
22 changes: 0 additions & 22 deletions .github/workflows/code-review.yaml

This file was deleted.

14 changes: 13 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
verifier:
verification_key_path: "./verification_key.json"
master_certs_path: "./masterList.dev.pem"
allowed_age: 18

issuer:
base_url: "http://localhost:3002/v1"
auth_username: ""
auth_password: ""
claim_type: "VotingCredential"
credential_schema: "https://bafybeibbniic63etdbcn5rs5ir5bhelym6ogv46afj35keatzhn2eqnioi.ipfs.w3s.link/VotingCredential.json"

log:
level: debug
disable_sentry: true

db:
url: db_url
url: postgres://voting:voting@localhost:35432/voting?sslmode=disable

listener:
addr: :8000
Expand Down
15 changes: 6 additions & 9 deletions internal/config/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ type VerifierConfiger interface {
}

type VerifierConfig struct {
VerificationKey []byte
MasterCerts []byte
IssuingAuthority string
AllowedAge int
VerificationKey []byte
MasterCerts []byte
AllowedAge int
}

type verifier struct {
Expand All @@ -34,7 +33,6 @@ func (v *verifier) VerifierConfig() *VerifierConfig {
newCfg := struct {
VerificationKeyPath string `fig:"verification_key_path,required"`
MasterCertsPath string `fig:"master_certs_path,required"`
IssuingAuthority string `fig:"issuing_authority,required"`
AllowedAge int `fig:"allowed_age,required"`
}{}

Expand All @@ -57,10 +55,9 @@ func (v *verifier) VerifierConfig() *VerifierConfig {
}

return &VerifierConfig{
VerificationKey: verificationKey,
MasterCerts: masterCerts,
IssuingAuthority: newCfg.IssuingAuthority,
AllowedAge: newCfg.AllowedAge,
VerificationKey: verificationKey,
MasterCerts: masterCerts,
AllowedAge: newCfg.AllowedAge,
}
}).(*VerifierConfig)
}
50 changes: 33 additions & 17 deletions internal/service/api/handlers/create_identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,22 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) {
return
}

if err := validatePubSignals(cfg, req.Data); err != nil {
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
}

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 := validatePubSignals(cfg, req.Data, encapsulatedData.PrivateKey.El1.OctetStr.Bytes); err != nil {
Log(r).WithError(err).Debug("failed to validate pub signals")
ape.RenderErr(w, problems.BadRequest(err)...)
return
Expand All @@ -69,7 +84,17 @@ func CreateIdentity(w http.ResponseWriter, r *http.Request) {
return
}

id, err := iss.IssueClaim(req.Data.ID, cfg.IssuingAuthority, true, identityExpiration)
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
}

id, err := iss.IssueClaim(
req.Data.ID, int64(issuingAuthority), true, identityExpiration,
encapsulatedData.PrivateKey.El2.OctetStr.Bytes,
)
if err != nil {
Log(r).WithError(err).Error("failed to issue voting claim")
ape.RenderErr(w, problems.InternalError())
Expand Down Expand Up @@ -187,8 +212,10 @@ func validateCert(certPem []byte, masterCertsPem []byte) error {
return nil
}

func validatePubSignals(cfg *config.VerifierConfig, requestData requests.CreateIdentityRequestData) error {
if err := validatePubSignalsDG1Hash(requestData.DocumentSOD.EncapsulatedContent, requestData.ZKProof.PubSignals); err != nil {
func validatePubSignals(
cfg *config.VerifierConfig, requestData requests.CreateIdentityRequestData, dg1 []byte,
) error {
if err := validatePubSignalsDG1Hash(dg1, requestData.ZKProof.PubSignals); err != nil {
return errors.Wrap(err, "failed to validate DG1 hash")
}

Expand All @@ -203,18 +230,7 @@ func validatePubSignals(cfg *config.VerifierConfig, requestData requests.CreateI
return nil
}

func validatePubSignalsDG1Hash(encapsulatedContent string, pubSignals []string) error {
encapsulatedContentBytes, err := hex.DecodeString(encapsulatedContent)
if err != nil {
return errors.Wrap(err, "failed to decode hex string")
}

encapsulatedData := resources.EncapsulatedData{}
_, err = asn1.Unmarshal(encapsulatedContentBytes, &encapsulatedData)
if err != nil {
return errors.Wrap(err, "failed to unmarshal ASN.1")
}

func validatePubSignalsDG1Hash(dg1 []byte, pubSignals []string) error {
ints, err := stringsToArrayBigInt([]string{pubSignals[0], pubSignals[1]})
if err != nil {
return errors.Wrap(err, "failed to convert strings to big integers")
Expand All @@ -224,7 +240,7 @@ func validatePubSignalsDG1Hash(encapsulatedContent string, pubSignals []string)
hashBytes = append(hashBytes, ints[0].Bytes()...)
hashBytes = append(hashBytes, ints[1].Bytes()...)

if !bytes.Equal(encapsulatedData.PrivateKey.El1.OctetStr.Bytes, hashBytes) {
if !bytes.Equal(dg1, hashBytes) {
return errors.New("encapsulated data and proof pub signals hashes are different")
}

Expand Down
30 changes: 25 additions & 5 deletions internal/service/issuer/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package issuer

import (
"math/big"
"time"

"github.com/RarimoVoting/identity-provider-service/internal/config"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/imroc/req/v3"
"gitlab.com/distributed_lab/logan/v3"
"gitlab.com/distributed_lab/logan/v3/errors"
"time"
)

type Issuer struct {
Expand All @@ -24,17 +27,34 @@ func New(log *logan.Entry, config *config.IssuerConfig) *Issuer {
}

func (is *Issuer) IssueClaim(
id, issuingAuthority string, isAdult bool, expiration *time.Time,
id string, issuingAuthority int64, isAdult bool, expiration *time.Time, dg2 []byte,
) (string, error) {
var result UUIDResponse

nullifierHash, err := poseidon.HashBytes(dg2)
if err != nil {
return "", errors.Wrap(err, "failed to hash bytes")
}

credHashInput := make([]byte, 0)
credHashInput = append(credHashInput, 1)
credHashInput = append(credHashInput, big.NewInt(issuingAuthority).Bytes()...)
credHashInput = append(credHashInput, nullifierHash.Bytes()...)

credentialHash, err := poseidon.HashBytes(credHashInput)
if err != nil {
return "", errors.Wrap(err, "failed to hash bytes")
}

credentialRequest := CredentialRequest{
CredentialSchema: is.cfg.CredentialSchema,
Type: is.cfg.ClaimType,
CredentialSubject: CredentialSubject{
ID: id,
IssuingAuthority: issuingAuthority,
IsAdult: isAdult,
ID: id,
IssuingAuthority: issuingAuthority,
IsAdult: isAdult,
DocumentNullifier: nullifierHash.String(),
CredentialHash: credentialHash.String(),
},
Expiration: expiration,
MtProof: true,
Expand Down
3 changes: 2 additions & 1 deletion internal/service/issuer/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type CredentialRequest struct {
type CredentialSubject struct {
ID string `json:"id"`
IsAdult bool `json:"isAdult"`
IssuingAuthority string `json:"issuingAuthority"`
IssuingAuthority int64 `json:"issuingAuthority"`
DocumentNullifier string `json:"documentNullifier"`
CredentialHash string `json:"credentialHash"`
}
Loading

0 comments on commit 0c21108

Please sign in to comment.