Commit 1edc5d24 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Move issuance state from client to session

parent 63efef57
......@@ -58,7 +58,6 @@ type Client struct {
irmaConfigurationPath string
androidStoragePath string
handler ClientHandler
state *issuanceState
}
// SentryDSN should be set in the init() function
......@@ -578,63 +577,73 @@ func (client *Client) Proofs(choice *irma.DisclosureChoice, request irma.Session
return builders.BuildProofList(request.GetContext(), request.GetNonce(), issig), nil
}
// generateIssuerProofNonce generates a nonce which the issuer must use in its gabi.ProofS.
func generateIssuerProofNonce() (*big.Int, error) {
return gabi.RandomBigInt(gabi.DefaultSystemParameters[4096].Lstatzk)
}
// IssuanceProofBuilders constructs a list of proof builders in the issuance protocol
// for the future credentials as well as possibly any disclosed attributes.
func (client *Client) IssuanceProofBuilders(request *irma.IssuanceRequest) (gabi.ProofBuilderList, error) {
state, err := newIssuanceState()
// for the future credentials as well as possibly any disclosed attributes, and generates
// a nonce against which the issuer's proof of knowledge must verify.
func (client *Client) IssuanceProofBuilders(request *irma.IssuanceRequest) (gabi.ProofBuilderList, *big.Int, error) {
issuerProofNonce, err := generateIssuerProofNonce()
if err != nil {
return nil, err
return nil, nil, err
}
client.state = state
proofBuilders := gabi.ProofBuilderList([]gabi.ProofBuilder{})
builders := gabi.ProofBuilderList([]gabi.ProofBuilder{})
for _, futurecred := range request.Credentials {
var pk *gabi.PublicKey
pk, err = client.Configuration.PublicKey(futurecred.CredentialTypeID.IssuerIdentifier(), futurecred.KeyCounter)
if err != nil {
return nil, err
return nil, nil, err
}
credBuilder := gabi.NewCredentialBuilder(
pk, request.GetContext(), client.secretkey.Key, state.nonce2)
state.builders = append(state.builders, credBuilder)
proofBuilders = append(proofBuilders, credBuilder)
pk, request.GetContext(), client.secretkey.Key, issuerProofNonce)
builders = append(builders, credBuilder)
}
disclosures, err := client.ProofBuilders(request.Choice, request, false)
if err != nil {
return nil, err
return nil, nil, err
}
proofBuilders = append(disclosures, proofBuilders...)
return proofBuilders, nil
builders = append(disclosures, builders...)
return builders, issuerProofNonce, nil
}
// IssueCommitments computes issuance commitments, along with disclosure proofs
// specified by choice.
func (client *Client) IssueCommitments(request *irma.IssuanceRequest) (*gabi.IssueCommitmentMessage, error) {
proofBuilders, err := client.IssuanceProofBuilders(request)
// IssueCommitments computes issuance commitments, along with disclosure proofs specified by choice,
// and also returns the credential builders which will become the new credentials upon combination with the issuer's signature.
func (client *Client) IssueCommitments(request *irma.IssuanceRequest) (*gabi.IssueCommitmentMessage, gabi.ProofBuilderList, error) {
builders, issuerProofNonce, err := client.IssuanceProofBuilders(request)
if err != nil {
return nil, err
return nil, nil, err
}
list := proofBuilders.BuildProofList(request.GetContext(), request.GetNonce(), false)
return &gabi.IssueCommitmentMessage{Proofs: list, Nonce2: client.state.nonce2}, nil
list := builders.BuildProofList(request.GetContext(), request.GetNonce(), false)
return &gabi.IssueCommitmentMessage{Proofs: list, Nonce2: issuerProofNonce}, builders, nil
}
// ConstructCredentials constructs and saves new credentials
// using the specified issuance signature messages.
func (client *Client) ConstructCredentials(msg []*gabi.IssueSignatureMessage, request *irma.IssuanceRequest) error {
if len(msg) != len(client.state.builders) {
// ConstructCredentials constructs and saves new credentials using the specified issuance signature messages
// and credential builders.
func (client *Client) ConstructCredentials(msg []*gabi.IssueSignatureMessage, request *irma.IssuanceRequest, builders gabi.ProofBuilderList) error {
if len(msg) > len(builders) {
return errors.New("Received unexpected amount of signatures")
}
// First collect all credentials in a slice, so that if one of them induces an error,
// we save none of them to fail the session cleanly
gabicreds := []*gabi.Credential{}
for i, sig := range msg {
attrs, err := request.Credentials[i].AttributeList(client.Configuration, irma.GetMetadataVersion(request.GetVersion()))
offset := 0
for i, builder := range builders {
credbuilder, ok := builder.(*gabi.CredentialBuilder)
if !ok { // Skip builders of disclosure proofs
offset++
continue
}
sig := msg[i-offset]
attrs, err := request.Credentials[i-offset].AttributeList(client.Configuration, irma.GetMetadataVersion(request.GetVersion()))
if err != nil {
return err
}
cred, err := client.state.builders[i].ConstructCredential(sig, attrs.Ints)
cred, err := credbuilder.ConstructCredential(sig, attrs.Ints)
if err != nil {
return err
}
......
......@@ -34,15 +34,15 @@ type keyshareSessionHandler interface {
}
type keyshareSession struct {
sessionHandler keyshareSessionHandler
pinRequestor KeysharePinRequestor
builders gabi.ProofBuilderList
session irma.SessionRequest
conf *irma.Configuration
keyshareServers map[irma.SchemeManagerIdentifier]*keyshareServer
keyshareServer *keyshareServer // The one keyshare server in use in case of issuance
transports map[irma.SchemeManagerIdentifier]*irma.HTTPTransport
state *issuanceState
sessionHandler keyshareSessionHandler
pinRequestor KeysharePinRequestor
builders gabi.ProofBuilderList
session irma.SessionRequest
conf *irma.Configuration
keyshareServers map[irma.SchemeManagerIdentifier]*keyshareServer
keyshareServer *keyshareServer // The one keyshare server in use in case of issuance
transports map[irma.SchemeManagerIdentifier]*irma.HTTPTransport
issuerProofNonce *big.Int
}
type keyshareServer struct {
......@@ -156,7 +156,7 @@ func startKeyshareSession(
session irma.SessionRequest,
conf *irma.Configuration,
keyshareServers map[irma.SchemeManagerIdentifier]*keyshareServer,
state *issuanceState,
issuerProofNonce *big.Int,
) {
ksscount := 0
for managerID := range session.Identifiers().SchemeManagers {
......@@ -176,14 +176,14 @@ func startKeyshareSession(
}
ks := &keyshareSession{
session: session,
builders: builders,
sessionHandler: sessionHandler,
transports: map[irma.SchemeManagerIdentifier]*irma.HTTPTransport{},
pinRequestor: pin,
conf: conf,
keyshareServers: keyshareServers,
state: state,
session: session,
builders: builders,
sessionHandler: sessionHandler,
transports: map[irma.SchemeManagerIdentifier]*irma.HTTPTransport{},
pinRequestor: pin,
conf: conf,
keyshareServers: keyshareServers,
issuerProofNonce: issuerProofNonce,
}
requestPin := false
......@@ -427,7 +427,7 @@ func (ks *keyshareSession) Finish(challenge *big.Int, responses map[irma.SchemeM
ks.sessionHandler.KeyshareError(&ks.keyshareServer.SchemeManagerIdentifier, err)
return
}
message := &gabi.IssueCommitmentMessage{Proofs: list, Nonce2: ks.state.nonce2}
message := &gabi.IssueCommitmentMessage{Proofs: list, Nonce2: ks.issuerProofNonce}
for _, response := range responses {
message.ProofPjwt = response
break
......
......@@ -61,6 +61,10 @@ type session struct {
request irma.SessionRequest
done bool
// State for issuance protocol
issuerProofNonce *big.Int
builders gabi.ProofBuilderList
// These are empty on manual sessions
ServerURL string
info *irma.SessionInfo
......@@ -115,22 +119,27 @@ func (session *session) IsInteractive() bool {
return session.ServerURL != ""
}
func (session *session) getBuilders() (gabi.ProofBuilderList, error) {
// getBuilders computes the builders for disclosure proofs or secretkey-knowledge proof (in case of disclosure/signing
// and issuing respectively).
func (session *session) getBuilders() (gabi.ProofBuilderList, *big.Int, error) {
var builders gabi.ProofBuilderList
var err error
var issuerProofNonce *big.Int
switch session.Action {
case irma.ActionSigning:
builders, err = session.client.ProofBuilders(session.choice, session.request, true)
case irma.ActionDisclosing:
builders, err = session.client.ProofBuilders(session.choice, session.request, false)
case irma.ActionIssuing:
builders, err = session.client.IssuanceProofBuilders(session.request.(*irma.IssuanceRequest))
builders, issuerProofNonce, err = session.client.IssuanceProofBuilders(session.request.(*irma.IssuanceRequest))
}
return builders, err
return builders, issuerProofNonce, err
}
// getProofs computes the disclosure proofs or secretkey-knowledge proof (in case of disclosure/signing
// and issuing respectively) to be sent to the server.
func (session *session) getProof() (interface{}, error) {
var message interface{}
var err error
......@@ -141,7 +150,7 @@ func (session *session) getProof() (interface{}, error) {
case irma.ActionDisclosing:
message, err = session.client.Proofs(session.choice, session.request, false)
case irma.ActionIssuing:
message, err = session.client.IssueCommitments(session.request.(*irma.IssuanceRequest))
message, session.builders, err = session.client.IssueCommitments(session.request.(*irma.IssuanceRequest))
}
return message, err
......@@ -394,18 +403,19 @@ func (session *session) doSession(proceed bool) {
}
session.sendResponse(message)
} else {
builders, err := session.getBuilders()
var err error
session.builders, session.issuerProofNonce, err = session.getBuilders()
if err != nil {
session.fail(&irma.SessionError{ErrorType: irma.ErrorCrypto, Err: err})
}
startKeyshareSession(
session,
session.Handler,
builders,
session.builders,
session.request,
session.client.Configuration,
session.client.keyshareServers,
session.client.state,
session.issuerProofNonce,
)
}
}
......@@ -530,7 +540,7 @@ func (session *session) sendResponse(message interface{}) {
session.fail(err.(*irma.SessionError))
return
}
if err = session.client.ConstructCredentials(response, session.request.(*irma.IssuanceRequest)); err != nil {
if err = session.client.ConstructCredentials(response, session.request.(*irma.IssuanceRequest), session.builders); err != nil {
session.fail(&irma.SessionError{ErrorType: irma.ErrorCrypto, Err: err})
return
}
......@@ -599,6 +609,7 @@ func panicToError(e interface{}) *irma.SessionError {
info = x.String()
default: // nop
}
fmt.Println("Panic: " + info)
return &irma.SessionError{ErrorType: irma.ErrorPanic, Info: info}
}
......@@ -630,19 +641,3 @@ func (session *session) cancel() {
func (session *session) Dismiss() {
session.cancel()
}
type issuanceState struct {
nonce2 *big.Int
builders []*gabi.CredentialBuilder
}
func newIssuanceState() (*issuanceState, error) {
nonce2, err := gabi.RandomBigInt(gabi.DefaultSystemParameters[4096].Lstatzk)
if err != nil {
return nil, err
}
return &issuanceState{
nonce2: nonce2,
builders: []*gabi.CredentialBuilder{},
}, nil
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment