Commit 8b92dd59 authored by Koen van Ingen's avatar Koen van Ingen
Browse files

WIP: Initial support for manual sigrequests

parent d6636a55
package irmaclient
import (
"fmt"
"testing"
"github.com/credentials/irmago"
)
type ManualSessionHandler struct {
permissionHandler PermissionHandler
pinHandler PinHandler
t *testing.T
c chan *irma.SessionError
}
var client *Client
func TestManualSession(t *testing.T) {
request := "{\"nonce\": 0, \"message\":\"I owe you everything\",\"messageType\":\"STRING\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]}]}"
channel := make(chan *irma.SessionError)
manualSessionHandler := ManualSessionHandler{t: t, c: channel}
client = parseStorage(t)
TestAndroidParse(t)
client.NewManualSession(request, &manualSessionHandler)
teardown(t)
if err := <-channel; err != nil {
t.Fatal(*err)
}
}
func TestManualKeyShareSession(t *testing.T) {
keyshareRequest := "{\"nonce\": 0, \"message\":\"I owe you everything\",\"messageType\":\"STRING\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"test.test.mijnirma.email\"]}]}"
channel := make(chan *irma.SessionError)
manualSessionHandler := ManualSessionHandler{t: t, c: channel}
client = parseStorage(t)
TestAndroidParse(t)
client.NewManualSession(keyshareRequest, &manualSessionHandler)
teardown(t)
if err := <-channel; err != nil {
t.Fatal(*err)
}
}
func (sh *ManualSessionHandler) Success(irmaAction irma.Action) {
sh.c <- nil
}
func (sh *ManualSessionHandler) UnsatisfiableRequest(irmaAction irma.Action, missingAttributes irma.AttributeDisjunctionList) { sh.t.Fail() }
// Done in irma bridge?
func (sh *ManualSessionHandler) StatusUpdate(irmaAction irma.Action, status irma.Status) { }
func (sh *ManualSessionHandler) RequestPin(remainingAttempts int, ph PinHandler) {
ph(true, "12345")
}
func (sh *ManualSessionHandler) RequestSignaturePermission(request irma.SignatureRequest, requesterName string, ph PermissionHandler) {
c := irma.DisclosureChoice{request.Candidates[0]}
ph(true, &c)
}
// These handler should not be called, fail test if they are called
func (sh *ManualSessionHandler) Cancelled(irmaAction irma.Action) { sh.t.Fail() }
func (sh *ManualSessionHandler) MissingKeyshareEnrollment(manager irma.SchemeManagerIdentifier) { sh.t.Fail() }
func (sh *ManualSessionHandler) RequestIssuancePermission(request irma.IssuanceRequest, issuerName string, ph PermissionHandler) { sh.t.Fail() }
func (sh *ManualSessionHandler) RequestSchemeManagerPermission(manager *irma.SchemeManager, callback func(proceed bool)) { sh.t.Fail() }
func (sh *ManualSessionHandler) RequestVerificationPermission(request irma.DisclosureRequest, verifierName string, ph PermissionHandler) { sh.t.Fail() }
func (sh *ManualSessionHandler) Failure(irmaAction irma.Action, err *irma.SessionError) {
fmt.Println(err.Err)
sh.t.Fail()
}
......@@ -5,6 +5,7 @@ import (
"sort"
"strconv"
"strings"
"encoding/json"
"math/big"
......@@ -62,8 +63,18 @@ type session struct {
done bool
}
type manualSession struct {
Action irma.Action
Handler Handler
client *Client
request *irma.SignatureRequest
version irma.Version
choice *irma.DisclosureChoice
}
// We implement the handler for the keyshare protocol
var _ keyshareSessionHandler = (*session)(nil)
var _ keyshareSessionHandler = (*manualSession)(nil)
// Supported protocol versions. Minor version numbers should be reverse sorted.
var supportedVersions = map[int][]int{
......@@ -105,6 +116,112 @@ func calcVersion(qr *irma.Qr) (string, error) {
return "", fmt.Errorf("No supported protocol version between %s and %s", qr.ProtocolVersion, qr.ProtocolMaxVersion)
}
func parseSigrequestJSON(sigrequestJSONString string) (*irma.SignatureRequest, error) {
sigrequestJSON := []byte(sigrequestJSONString)
sigrequest := &irma.SignatureRequest{}
err := json.Unmarshal(sigrequestJSON, sigrequest)
return sigrequest, err
}
// Start a manual session
func (client *Client) NewManualSession(sigrequestJSONString string, handler Handler) {
sigrequest, err := parseSigrequestJSON(sigrequestJSONString);
if err != nil {
handler.Failure(irma.ActionUnknown, &irma.SessionError{Err: err})
return
}
session := &manualSession{
Action: irma.ActionSigning, // TODO hardcoded for now
Handler: handler,
client: client,
request: sigrequest,
version: irma.Version("2"), // TODO hardcoded for now
}
// Check if we are enrolled into all involved keyshare servers
for id := range session.request.Identifiers().SchemeManagers {
manager, ok := session.client.Configuration.SchemeManagers[id]
if !ok {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorUnknownSchemeManager, Info: id.String()})
return
}
distributed := manager.Distributed()
_, enrolled := session.client.keyshareServers[id]
if distributed && !enrolled {
session.Handler.MissingKeyshareEnrollment(id)
return
}
}
candidates, missing := session.client.CheckSatisfiability(session.request.ToDisclose())
if len(missing) > 0 {
session.Handler.UnsatisfiableRequest(session.Action, missing)
// TODO: session.transport.Delete() on dialog cancel
return
}
session.request.SetCandidates(candidates)
// Ask for permission to execute the session
callback := PermissionHandler(func(proceed bool, choice *irma.DisclosureChoice) {
session.choice = choice
session.request.SetDisclosureChoice(choice)
fmt.Println("Starting session.do()")
go session.do(proceed)
})
session.Handler.RequestSignaturePermission(
*session.request, "TODO: NAME", callback)
fmt.Println(session)
}
func (session *manualSession) do(proceed bool) {
if !proceed {
fmt.Println("Cancel..")
session.Handler.Cancelled(session.Action)
return
}
fmt.Println("Do manual session for session: ")
if !session.request.Identifiers().Distributed(session.client.Configuration) {
fmt.Println("No keyshare session needed...")
var message interface{}
var err error
message, err = session.client.Proofs(session.choice, session.request, true)
if err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorCrypto, Err: err})
return
}
mar, _ := json.Marshal(message)
fmt.Println(string(mar))
session.Handler.Success(session.Action)
} else {
fmt.Println("Starting keyshare session...")
var builders gabi.ProofBuilderList
var err error
builders, err = session.client.ProofBuilders(session.choice)
if err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorCrypto, Err: err})
}
startKeyshareSession(
session,
session.Handler,
builders,
session.request,
session.client.Configuration,
session.client.keyshareServers,
session.client.state,
)
fmt.Println("DONE")
}
}
// NewSession creates and starts a new IRMA session.
func (client *Client) NewSession(qr *irma.Qr, handler Handler) SessionDismisser {
session := &session{
......@@ -315,14 +432,28 @@ func (session *session) KeyshareDone(message interface{}) {
session.sendResponse(message)
}
func (session *manualSession) KeyshareDone(message interface{}) {
messageString, _ := json.Marshal(message)
fmt.Println(string(messageString))
session.Handler.Success(session.Action)
}
func (session *session) KeyshareCancelled() {
session.cancel()
}
func (session *manualSession) KeyshareCancelled() {
session.Handler.Cancelled(session.Action)
}
func (session *session) KeyshareBlocked(duration int) {
session.fail(&irma.SessionError{ErrorType: irma.ErrorKeyshareBlocked, Info: strconv.Itoa(duration)})
}
func (session *manualSession) KeyshareBlocked(duration int) {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorKeyshareBlocked, Info: strconv.Itoa(duration)})
}
func (session *session) KeyshareError(err error) {
var serr *irma.SessionError
var ok bool
......@@ -334,13 +465,30 @@ func (session *session) KeyshareError(err error) {
session.fail(serr)
}
func (session *manualSession) KeyshareError(err error) {
var serr *irma.SessionError
var ok bool
if serr, ok = err.(*irma.SessionError); !ok {
serr = &irma.SessionError{ErrorType: irma.ErrorKeyshare, Err: err}
} else {
serr.ErrorType = irma.ErrorKeyshare
}
session.Handler.Failure(session.Action, serr)
}
func (session *session) KeysharePin() {
session.Handler.StatusUpdate(session.Action, irma.StatusConnected)
}
func (session *manualSession) KeysharePin() {
session.Handler.StatusUpdate(session.Action, irma.StatusConnected)
}
func (session *session) KeysharePinOK() {
session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating)
}
func (session *manualSession) KeysharePinOK() {
session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating)
}
type disclosureResponse string
......
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