github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/cl/ursa/prover.go (about)

     1  //go:build ursa
     2  // +build ursa
     3  
     4  /*
     5  Copyright Avast Software. All Rights Reserved.
     6  
     7  SPDX-License-Identifier: Apache-2.0
     8  */
     9  
    10  package ursa
    11  
    12  import (
    13  	"fmt"
    14  
    15  	"github.com/hyperledger/aries-framework-go/pkg/crypto"
    16  	"github.com/hyperledger/aries-framework-go/pkg/doc/cl"
    17  )
    18  
    19  // Prover is an ursa implementation of the CL Prover API.
    20  type Prover struct {
    21  	crypto crypto.Crypto
    22  	kh     interface{}
    23  }
    24  
    25  // NewProver insaniates a Prover service for the provided keyID.
    26  func NewProver(provider cl.Provider, keyID string) (*Prover, error) {
    27  	km := provider.KMS()
    28  
    29  	kh, err := km.Get(keyID)
    30  	if err != nil {
    31  		return nil, fmt.Errorf("failed to get KeyHandle for %s: %w", keyID, err)
    32  	}
    33  
    34  	return &Prover{kh: kh, crypto: provider.Crypto()}, nil
    35  }
    36  
    37  // RequestCredential generates CredRequest which contains blinded secrets with MS, using issuer's CredDef public data
    38  // and CredOffer from the previous step
    39  // returns:
    40  // 		request as *CredentialRequest
    41  //		error in case of errors
    42  func (s *Prover) RequestCredential(
    43  	credOffer *cl.CredentialOffer,
    44  	credDef *cl.CredentialDefinition,
    45  	proverID string,
    46  ) (*cl.CredentialRequest, error) {
    47  	blindedMs, err := s.crypto.Blind(s.kh)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	nonce, err := newNonce()
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	secrets, err := blindCredentialSecrets(
    58  		credDef.CredPubKey,
    59  		credDef.CredDefCorrectnessProof,
    60  		credOffer.Nonce,
    61  		blindedMs[0],
    62  	)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	return &cl.CredentialRequest{BlindedCredentialSecrets: secrets, Nonce: nonce, ProverID: proverID}, nil
    68  }
    69  
    70  // ProcessCredential updates issued Credential signature for CredDef, using blinding factor from a CredRequest
    71  // returns:
    72  // 		credential as *Credential
    73  //		error in case of errors
    74  func (s *Prover) ProcessCredential(
    75  	credential *cl.Credential,
    76  	credRequest *cl.CredentialRequest,
    77  	credDef *cl.CredentialDefinition,
    78  ) error {
    79  	blindedVals, err := s.crypto.Blind(s.kh, credential.Values)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	err = processCredentialSignature(
    85  		credential,
    86  		credRequest,
    87  		credDef,
    88  		blindedVals[0],
    89  	)
    90  
    91  	return err
    92  }
    93  
    94  // CreateProof composes Proof for the provided Credentials for CredDefs
    95  // matching revealead attrs and predicates specified in PresentationRequest
    96  // returns:
    97  // 		proof as *Proof
    98  //		error in case of errors
    99  func (s *Prover) CreateProof(
   100  	presentationRequest *cl.PresentationRequest,
   101  	credentials []*cl.Credential,
   102  	credDefs []*cl.CredentialDefinition,
   103  ) (*cl.Proof, error) {
   104  	if len(presentationRequest.Items) != len(credentials) {
   105  		return nil, fmt.Errorf("not enough credentials provided to fulfill the presentsation request")
   106  	}
   107  
   108  	if len(presentationRequest.Items) != len(credDefs) {
   109  		return nil, fmt.Errorf("not enough credential definitions provided to fulfill the presentsation request")
   110  	}
   111  
   112  	var multivals []map[string]interface{}
   113  	for _, cred := range credentials {
   114  		multivals = append(multivals, cred.Values)
   115  	}
   116  
   117  	blindedMultiVals, err := s.crypto.Blind(s.kh, multivals...)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	var subProofItems []*subProofItem
   123  
   124  	for i, item := range presentationRequest.Items {
   125  		subProofItem := &subProofItem{
   126  			BlindedVals:          blindedMultiVals[i],
   127  			Credential:           credentials[i],
   128  			CredentialDefinition: credDefs[i],
   129  			Item:                 item,
   130  		}
   131  
   132  		subProofItems = append(subProofItems, subProofItem)
   133  	}
   134  
   135  	proof, err := createProof(subProofItems, presentationRequest.Nonce)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	return &cl.Proof{Proof: proof}, nil
   141  }