Commit da9fdf3d authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Reinstate session logging

parent 8a194570
package sessiontest
import (
"testing"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/test"
"github.com/stretchr/testify/require"
)
func TestLogging(t *testing.T) {
client := parseStorage(t)
logs, err := client.Logs()
oldLogLength := len(logs)
require.NoError(t, err)
attrid := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
var request irma.SessionRequest
// Do issuance session
request = getCombinedIssuanceRequest(attrid)
sessionHelper(t, request, "issue", client)
logs, err = client.Logs()
require.NoError(t, err)
require.True(t, len(logs) == oldLogLength+1)
entry := logs[len(logs)-1]
require.NotNil(t, entry)
require.NoError(t, err)
issued, err := entry.GetIssuedCredentials(client.Configuration)
require.NoError(t, err)
require.NotNil(t, issued)
disclosed, err := entry.GetDisclosedCredentials(client.Configuration)
require.NoError(t, err)
require.NotEmpty(t, disclosed)
// Do disclosure session
request = getDisclosureRequest(attrid)
sessionHelper(t, request, "verification", client)
logs, err = client.Logs()
require.NoError(t, err)
require.True(t, len(logs) == oldLogLength+2)
entry = logs[len(logs)-1]
require.NotNil(t, entry)
require.NoError(t, err)
disclosed, err = entry.GetDisclosedCredentials(client.Configuration)
require.NoError(t, err)
require.NotEmpty(t, disclosed)
// Do signature session
request = getSigningRequest(attrid)
sessionHelper(t, request, "signature", client)
logs, err = client.Logs()
require.NoError(t, err)
require.True(t, len(logs) == oldLogLength+3)
entry = logs[len(logs)-1]
require.NotNil(t, entry)
require.NoError(t, err)
sig, err := entry.GetSignedMessage()
require.NoError(t, err)
require.NotNil(t, sig)
attrs, status, err := sig.Verify(client.Configuration, nil)
require.NoError(t, err)
require.Equal(t, irma.ProofStatusValid, status)
require.NotEmpty(t, attrs)
require.Equal(t, attrid, attrs[0].Identifier)
require.Equal(t, "s1234567", attrs[0].Value["en"])
test.ClearTestStorage(t)
}
......@@ -118,70 +118,6 @@ func TestStorageDeserialization(t *testing.T) {
verifyKeyshareIsUnmarshaled(t, client)
}
//func disabledTestLogging(t *testing.T) {
// client := parseStorage(t)
//
// logs, err := client.Logs()
// oldLogLength := len(logs)
// require.NoError(t, err)
// attrid := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
//
// // Do issuance session
// jwt := getCombinedJwt("testip", attrid)
// sessionHelper(t, jwt, "issue", client)
//
// logs, err = client.Logs()
// require.NoError(t, err)
// require.True(t, len(logs) == oldLogLength+1)
//
// entry := logs[len(logs)-1]
// require.NotNil(t, entry)
// //require.Equal(t, "testip", entry.Request.GetRequestorName())
// require.NoError(t, err)
// issued, err := entry.GetIssuedCredentials(client.Configuration)
// require.NoError(t, err)
// require.NotNil(t, issued)
// disclosed, err := entry.GetDisclosedCredentials(client.Configuration)
// require.NoError(t, err)
// require.NotEmpty(t, disclosed)
//
// // Do disclosure session
// jwt = getDisclosureJwt("testsp", attrid)
// sessionHelper(t, jwt, "verification", client)
// logs, err = client.Logs()
// require.NoError(t, err)
// require.True(t, len(logs) == oldLogLength+2)
//
// entry = logs[len(logs)-1]
// require.NotNil(t, entry)
// //require.Equal(t, "testsp", entry.Request.GetRequestorName())
// require.NoError(t, err)
// disclosed, err = entry.GetDisclosedCredentials(client.Configuration)
// require.NoError(t, err)
// require.NotEmpty(t, disclosed)
//
// // Do signature session
// jwt = getSigningJwt("testsigclient", attrid)
// sessionHelper(t, jwt, "signature", client)
// logs, err = client.Logs()
// require.NoError(t, err)
// require.True(t, len(logs) == oldLogLength+3)
// entry = logs[len(logs)-1]
// require.NotNil(t, entry)
// //require.Equal(t, "testsigclient", entry.Request.GetRequestorName())
// require.NoError(t, err)
// sig, err := entry.GetSignedMessage()
// require.NoError(t, err)
// require.NotNil(t, sig)
// attrs, status := sig.Verify(client.Configuration, nil)
// require.Equal(t, irma.ProofStatusValid, status)
// require.NotEmpty(t, attrs)
// require.Equal(t, attrs[0].Identifier, attrid)
// require.Equal(t, "s1234567", attrs[0].Value["en"])
//
// test.ClearTestStorage(t)
//}
// TestCandidates tests the correctness of the function of the client that, given a disjunction of attributes
// requested by the verifier, calculates a list of candidate attributes contained by the client that would
// satisfy the attribute disjunction.
......
package irmaclient
import (
"encoding/json"
"time"
"github.com/bwesterb/go-atum"
"github.com/go-errors/errors"
"github.com/mhe/gabi"
"github.com/privacybydesign/irmago"
)
......@@ -12,7 +16,9 @@ type LogEntry struct {
Type irma.Action
Time irma.Timestamp // Time at which the session was completed
Version *irma.ProtocolVersion `json:",omitempty"` // Protocol version that was used in the session
//Request irma.SessionRequest `json:",omitempty"` // Message that started the session
Request json.RawMessage `json:",omitempty"` // Message that started the session
request irma.SessionRequest // cached parsed version of Request; get with LogEntry.SessionRequest()
// Session type-specific info
Removed map[irma.CredentialTypeIdentifier][]irma.TranslatedString `json:",omitempty"` // In case of credential removal
......@@ -25,21 +31,118 @@ type LogEntry struct {
const actionRemoval = irma.Action("removal")
func (entry *LogEntry) SessionRequest() (irma.SessionRequest, error) {
if entry.request == nil {
switch entry.Type {
case irma.ActionDisclosing:
entry.request = &irma.DisclosureRequest{}
case irma.ActionSigning:
entry.request = &irma.SignatureRequest{}
case irma.ActionIssuing:
entry.request = &irma.IssuanceRequest{}
default:
return nil, nil
}
}
err := json.Unmarshal([]byte(entry.Request), entry.request)
if err != nil {
return nil, err
}
return entry.request, nil
}
func (entry *LogEntry) setSessionRequest() error {
bts, err := json.Marshal(entry.request)
if err != nil {
return err
}
entry.Request = json.RawMessage(bts)
return nil
}
// GetDisclosedCredentials gets the list of disclosed credentials for a log entry
func (entry *LogEntry) GetDisclosedCredentials(conf *irma.Configuration) ([]*irma.DisclosedAttribute, error) {
return nil, nil
if entry.Type == actionRemoval {
return []*irma.DisclosedAttribute{}, nil
}
request, err := entry.SessionRequest()
if err != nil {
return nil, err
}
var proofs gabi.ProofList
disjunctions := request.ToDisclose()
if entry.Type == irma.ActionIssuing {
proofs = entry.IssueCommitment.Proofs
} else {
proofs = entry.ProofList
}
_, attrs, err := irma.ProofList(proofs).DisclosedAttributes(conf, disjunctions)
return attrs, err
}
// GetIssuedCredentials gets the list of issued credentials for a log entry
func (entry *LogEntry) GetIssuedCredentials(conf *irma.Configuration) (list irma.CredentialInfoList, err error) {
return nil, nil
if entry.Type != irma.ActionIssuing {
return irma.CredentialInfoList{}, nil
}
request, err := entry.SessionRequest()
if err != nil {
return nil, err
}
return request.(*irma.IssuanceRequest).GetCredentialInfoList(conf, entry.Version)
}
// GetSignedMessage gets the signed for a log entry
func (entry *LogEntry) GetSignedMessage() (abs *irma.SignedMessage, err error) {
return nil, nil
if entry.Type != irma.ActionSigning {
return nil, nil
}
request, err := entry.SessionRequest()
if err != nil {
return nil, err
}
sigrequest := request.(*irma.SignatureRequest)
return &irma.SignedMessage{
Signature: entry.ProofList,
Nonce: sigrequest.Nonce,
Context: sigrequest.Context,
Message: string(entry.SignedMessage),
Timestamp: entry.Timestamp,
}, nil
}
func (session *session) createLogEntry(response interface{}) (*LogEntry, error) {
return nil, nil
entry := &LogEntry{
Type: session.Action,
Time: irma.Timestamp(time.Now()),
Version: session.Version,
request: session.request,
}
if err := entry.setSessionRequest(); err != nil {
return nil, err
}
switch entry.Type {
case actionRemoval:
case irma.ActionSigning:
// Get the signed message and timestamp
request := session.request.(*irma.SignatureRequest)
entry.SignedMessage = []byte(request.Message)
entry.Timestamp = request.Timestamp
fallthrough
case irma.ActionDisclosing:
entry.ProofList = response.(gabi.ProofList)
case irma.ActionIssuing:
entry.IssueCommitment = response.(*gabi.IssueCommitmentMessage)
default:
return nil, errors.New("Invalid log type")
}
return entry, nil
}
package irmaclient
import (
"os"
"encoding/json"
"regexp"
"time"
"github.com/go-errors/errors"
"github.com/mhe/gabi"
"github.com/mhe/gabi/big"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
)
......@@ -68,9 +72,95 @@ var clientUpdates = []func(client *Client) error{
// 6: Guess and include version protocol in issuance logs, and convert log entry structure
// from Response to either IssueCommitment or ProofList
func(client *Client) (err error) {
// TODO: this has been temporarily removed and should be restored
os.Remove(client.storage.path(logsFile))
return nil
logs, err := client.Logs()
if err != nil {
return
}
// The logs read above do not contain the Response field as it has been removed from the LogEntry struct.
// So read the logs again into a slice of a temp struct that does contain this field.
type oldLogEntry struct {
Response json.RawMessage
SessionInfo struct {
Nonce *big.Int `json:"nonce"`
Context *big.Int `json:"context"`
Jwt string `json:"jwt"`
Keys map[irma.IssuerIdentifier]int `json:"keys"`
}
}
var oldLogs []*oldLogEntry
if err = client.storage.load(&oldLogs, logsFile); err != nil {
return
}
// Sanity check, this should be true as both log slices were read from the same source
if len(oldLogs) != len(logs) {
return errors.New("Log count does not match")
}
for i, entry := range logs {
oldEntry := oldLogs[i]
if len(oldEntry.Response) == 0 {
return errors.New("Log entry had no Response field")
}
var jwt irma.RequestorJwt
jwt, err = irma.ParseRequestorJwt(string(entry.Type), oldEntry.SessionInfo.Jwt)
if err != nil {
return err
}
entry.request = jwt.SessionRequest()
// Ugly hack alert: unfortunately the protocol version that was used in the session is nowhere recorded.
// This means that we cannot be sure whether or not we should byteshift the presence bit out of the attributes
// that was introduced in version 2.3 of the protocol. The only thing that I can think of to determine this
// is to check if the attributes are human-readable, i.e., alphanumeric: if the presence bit is present and
// we do not shift it away, then they almost certainly will not be.
if entry.Type == irma.ActionIssuing && entry.Version == nil {
for _, attr := range entry.request.(*irma.IssuanceRequest).Credentials[0].Attributes {
if regexp.MustCompile("^\\w").Match([]byte(attr)) {
entry.Version = irma.NewVersion(2, 2)
} else {
entry.Version = irma.NewVersion(2, 3)
}
break
}
}
if entry.Version == nil {
entry.Version = irma.NewVersion(2, 3)
}
entry.request.SetNonce(oldEntry.SessionInfo.Nonce)
entry.request.SetContext(oldEntry.SessionInfo.Context)
entry.request.SetVersion(entry.Version)
if err := entry.setSessionRequest(); err != nil {
return err
}
switch entry.Type {
case actionRemoval: // nop
case irma.ActionSigning:
fallthrough
case irma.ActionDisclosing:
proofs := []*gabi.ProofD{}
if err = json.Unmarshal(oldEntry.Response, &proofs); err != nil {
return
}
for _, proof := range proofs {
entry.ProofList = append(entry.ProofList, proof)
}
case irma.ActionIssuing:
entry.IssueCommitment = &gabi.IssueCommitmentMessage{}
if err = json.Unmarshal(oldEntry.Response, entry.IssueCommitment); err != nil {
return err
}
isreq := entry.request.(*irma.IssuanceRequest)
for _, cred := range isreq.Credentials {
cred.KeyCounter = oldEntry.SessionInfo.Keys[cred.CredentialTypeID.IssuerIdentifier()]
}
default:
return errors.New("Invalid log type")
}
}
return client.storage.StoreLogs(logs)
},
}
......
......@@ -255,11 +255,11 @@ func JwtDecode(jwt string, body interface{}) error {
func ParseRequestorJwt(action string, jwt string) (RequestorJwt, error) {
var retval RequestorJwt
switch action {
case "verification_request":
case "verification_request", string(ActionDisclosing):
retval = &ServiceProviderJwt{}
case "signature_request":
case "signature_request", string(ActionSigning):
retval = &SignatureRequestorJwt{}
case "issue_request":
case "issue_request", string(ActionIssuing):
retval = &IdentityProviderJwt{}
default:
return nil, errors.New("Invalid session type")
......
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