Commit 3b7621ea authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Documenting

parent 645b8397
......@@ -78,6 +78,7 @@ func (al *AttributeList) Strings() []string {
return al.strings
}
// Attribute returns the content of the specified attribute, or "" if not present in this attribute list.
func (al *AttributeList) Attribute(identifier AttributeTypeIdentifier) string {
if al.CredentialType().Identifier() != identifier.CredentialTypeIdentifier() {
return ""
......
......@@ -68,6 +68,8 @@ type AttributeDescription struct {
Description TranslatedString
}
// IndexOf returns the index of the specified attribute if present,
// or an error (and -1) if not present.
func (ct CredentialType) IndexOf(ai AttributeTypeIdentifier) (int, error) {
if ai.CredentialTypeIdentifier() != ct.Identifier() {
return -1, errors.New("Wrong credential type")
......@@ -80,26 +82,6 @@ func (ct CredentialType) IndexOf(ai AttributeTypeIdentifier) (int, error) {
return -1, errors.New("Attribute identifier not found")
}
// TranslatedString represents an XML tag containing a string translated to multiple languages.
// For example: <Foo id="bla"><Translation lang="en">Hello world</Translation><Translation lang="nl">Hallo wereld</Translation></Foo>
// type TranslatedString struct {
// Translations []struct {
// Language string `xml:"lang,attr"`
// Value string `xml:",chardata"`
// } `xml:"Translation"`
// ID string `xml:"id,attr"`
// }
//
// // Get returns the specified translation
// func (ts TranslatedString) Get(lang string) string {
// for _, l := range ts.Translations {
// if l.Language == lang {
// return l.Value
// }
// }
// return ""
// }
// TranslatedString represents an XML tag containing a string translated to multiple languages.
// For example: <Foo id="bla"><en>Hello world</en><nl>Hallo wereld</nl></Foo>
type TranslatedString struct {
......
......@@ -27,28 +27,33 @@ type AttributeTypeIdentifier struct {
metaObjectIdentifier
}
// CredentialIdentifier identifies a credential instance.
type CredentialIdentifier struct {
Type CredentialTypeIdentifier
Index int
Count int
}
// AttributeIdentifier identifies an attribute instance.
type AttributeIdentifier struct {
Type AttributeTypeIdentifier
Index int
Count int
}
// Parent returns the parent object of this identifier.
func (oi metaObjectIdentifier) Parent() string {
str := string(oi)
return str[:strings.LastIndex(str, ".")]
}
// Name returns the last part of this identifier.
func (oi metaObjectIdentifier) Name() string {
str := string(oi)
return str[strings.LastIndex(str, ".")+1:]
}
// String returns this identifier as a string.
func (oi metaObjectIdentifier) String() string {
return string(oi)
}
......@@ -88,23 +93,29 @@ func (id AttributeTypeIdentifier) CredentialTypeIdentifier() CredentialTypeIdent
return NewCredentialTypeIdentifier(id.Parent())
}
// IsCredential returns true if this attribute refers to its containing credential
// (i.e., it consists of only 3 parts).
func (id AttributeTypeIdentifier) IsCredential() bool {
return strings.Count(id.String(), ".") == 2
}
// CredentialIdentifier returns the credential identifier of this attribute.
func (ai *AttributeIdentifier) CredentialIdentifier() CredentialIdentifier {
return CredentialIdentifier{Type: ai.Type.CredentialTypeIdentifier(), Index: ai.Index, Count: ai.Count}
}
// MarshalJSON marshals this instance to JSON as a string.
func (id AttributeTypeIdentifier) MarshalJSON() ([]byte, error) {
return json.Marshal(id.String())
}
// MarshalJSON marshals this instance to JSON as a string.
func (id CredentialTypeIdentifier) MarshalJSON() ([]byte, error) {
return json.Marshal(id.String())
}
func (id AttributeTypeIdentifier) UnmarshalJSON(b []byte) error {
// UnmarshalJSON unmarshals this instance from JSON.
func (id *AttributeTypeIdentifier) UnmarshalJSON(b []byte) error {
var val string
err := json.Unmarshal(b, &val)
if err != nil {
......@@ -114,6 +125,7 @@ func (id AttributeTypeIdentifier) UnmarshalJSON(b []byte) error {
return nil
}
// UnmarshalJSON unmarshals this instance from JSON.
func (id *CredentialTypeIdentifier) UnmarshalJSON(b []byte) error {
var val string
err := json.Unmarshal(b, &val)
......
......@@ -204,6 +204,8 @@ func (cm *CredentialManager) add(cred *credential) (err error) {
return
}
// Candidates returns a list of attributes present in this credential manager
// that satisfy the specified attribute disjunction.
func (cm *CredentialManager) Candidates(disjunction *AttributeDisjunction) []*AttributeIdentifier {
candidates := make([]*AttributeIdentifier, 0, 10)
......@@ -237,6 +239,9 @@ func (cm *CredentialManager) Candidates(disjunction *AttributeDisjunction) []*At
return candidates
}
// CheckSatisfiability checks if this credential manager has the required attributes
// to satisfy the specifed disjunction list. If not, the unsatisfiable disjunctions
// are returned.
func (cm *CredentialManager) CheckSatisfiability(disjunctions AttributeDisjunctionList) AttributeDisjunctionList {
missing := make(AttributeDisjunctionList, 0, 5)
for _, disjunction := range disjunctions {
......@@ -279,6 +284,7 @@ func (cm *CredentialManager) groupCredentials(choice *DisclosureChoice) (map[Cre
return grouped, nil
}
// Session is an IRMA session.
type Session interface {
GetNonce() *big.Int
SetNonce(*big.Int)
......@@ -304,6 +310,7 @@ func (cm *CredentialManager) proofsBuilders(choice *DisclosureChoice) ([]gabi.Pr
return builders, nil
}
// Proofs computes disclosure proofs containing the attributes specified by choice.
func (cm *CredentialManager) Proofs(choice *DisclosureChoice, request Session, issig bool) (gabi.ProofList, error) {
builders, err := cm.proofsBuilders(choice)
if err != nil {
......@@ -312,6 +319,8 @@ func (cm *CredentialManager) Proofs(choice *DisclosureChoice, request Session, i
return gabi.BuildProofList(request.GetContext(), request.GetNonce(), builders, issig), nil
}
// IssueCommitments computes issuance commitments, along with disclosure proofs
// specified by choice.
func (cm *CredentialManager) IssueCommitments(choice *DisclosureChoice, request *IssuanceRequest) (*gabi.IssueCommitmentMessage, error) {
state, err := newIssuanceState(request)
if err != nil {
......@@ -337,6 +346,8 @@ func (cm *CredentialManager) IssueCommitments(choice *DisclosureChoice, request
return &gabi.IssueCommitmentMessage{Proofs: list, Nonce2: state.nonce2}, nil
}
// ConstructCredentials constructs and saves new credentials
// using the specified issuance signature messages.
func (cm *CredentialManager) ConstructCredentials(msg []*gabi.IssueSignatureMessage, request *IssuanceRequest) error {
if len(msg) != len(request.state.builders) {
return errors.New("Received unexpected amount of signatures")
......
......@@ -21,6 +21,7 @@ type Version string
// ErrorCode are session errors.
type ErrorCode string
// Error is a protocol error.
type Error struct {
ErrorCode
error
......@@ -103,6 +104,7 @@ type jsonSessionInfo struct {
Keys [][]interface{} `json:"keys"`
}
// UnmarshalJSON unmarshals session information.
func (si *SessionInfo) UnmarshalJSON(b []byte) error {
temp := &jsonSessionInfo{}
err := json.Unmarshal(b, temp)
......
......@@ -6,39 +6,47 @@ import (
"github.com/credentials/irmago"
)
// ServerJwt contains standard JWT fields.
type ServerJwt struct {
Type string `json:"sub"`
ServerName string `json:"iss"`
IssuedAt irmago.Timestamp `json:"iat"`
}
// A ServiceProviderRequest contains a disclosure request.
type ServiceProviderRequest struct {
Request *irmago.DisclosureRequest `json:"request"`
}
// A SignatureRequestorRequest contains a signing request.
type SignatureRequestorRequest struct {
Request *irmago.SignatureRequest `json:"request"`
}
// An IdentityProviderRequest contains an issuance request.
type IdentityProviderRequest struct {
Request *irmago.IssuanceRequest `json:"request"`
}
// ServiceProviderJwt is a requestor JWT for a disclosure session.
type ServiceProviderJwt struct {
ServerJwt
Request ServiceProviderRequest `json:"sprequest"`
}
// SignatureRequestorJwt is a requestor JWT for a signing session.
type SignatureRequestorJwt struct {
ServerJwt
Request SignatureRequestorRequest `json:"absrequest"`
}
// IdentityProviderJwt is a requestor JWT for issuance session.
type IdentityProviderJwt struct {
ServerJwt
Request IdentityProviderRequest `json:"iprequest"`
}
// NewServiceProviderJwt returns a new ServiceProviderJwt.
func NewServiceProviderJwt(servername string, dr *irmago.DisclosureRequest) *ServiceProviderJwt {
return &ServiceProviderJwt{
ServerJwt: ServerJwt{
......@@ -50,6 +58,7 @@ func NewServiceProviderJwt(servername string, dr *irmago.DisclosureRequest) *Ser
}
}
// NewSignatureRequestorJwt returns a new SignatureRequestorJwt.
func NewSignatureRequestorJwt(servername string, sr *irmago.SignatureRequest) *SignatureRequestorJwt {
return &SignatureRequestorJwt{
ServerJwt: ServerJwt{
......@@ -61,6 +70,7 @@ func NewSignatureRequestorJwt(servername string, sr *irmago.SignatureRequest) *S
}
}
// NewIdentityProviderJwt returns a new IdentityProviderJwt.
func NewIdentityProviderJwt(servername string, ir *irmago.IssuanceRequest) *IdentityProviderJwt {
return &IdentityProviderJwt{
ServerJwt: ServerJwt{
......@@ -72,10 +82,16 @@ func NewIdentityProviderJwt(servername string, ir *irmago.IssuanceRequest) *Iden
}
}
// A RequestorJwt contains an IRMA session object.
type RequestorJwt interface {
IrmaSession() irmago.Session
}
func (jwt *ServiceProviderJwt) IrmaSession() irmago.Session { return jwt.Request.Request }
// IrmaSession returns an IRMA session object.
func (jwt *ServiceProviderJwt) IrmaSession() irmago.Session { return jwt.Request.Request }
// IrmaSession returns an IRMA session object.
func (jwt *SignatureRequestorJwt) IrmaSession() irmago.Session { return jwt.Request.Request }
func (jwt *IdentityProviderJwt) IrmaSession() irmago.Session { return jwt.Request.Request }
// IrmaSession returns an IRMA session object.
func (jwt *IdentityProviderJwt) IrmaSession() irmago.Session { return jwt.Request.Request }
package protocol
// StartSession starts an IRMA session by posting the request,
// and retrieving the QR contents from the specified url.
func StartSession(request interface{}, url string) (*Qr, error) {
server := NewHTTPTransport(url)
var response Qr
......
......@@ -13,6 +13,8 @@ import (
"github.com/mhe/gabi"
)
// PermissionHandler is a callback for providing permission for an IRMA session
// and specifying the attributes to be disclosed.
type PermissionHandler func(proceed bool, choice *irmago.DisclosureChoice)
// A Handler contains callbacks for communication to the user.
......
......@@ -10,11 +10,13 @@ import (
"time"
)
// HTTPTransport sends and receives JSON messages to a HTTP server.
type HTTPTransport struct {
Server string
client *http.Client
}
// ApiError is an error message returned by the API server on errors.
type ApiError struct {
Status int `json:"status"`
ErrorName string `json:"error"`
......@@ -23,6 +25,7 @@ type ApiError struct {
Stacktrace string `json:"stacktrace"`
}
// TransportError is an error occuring during HTTP traffic.
type TransportError struct {
Err string
Status int
......@@ -33,6 +36,7 @@ func (te TransportError) Error() string {
return te.Err
}
// NewHTTPTransport returns a new HTTPTransport.
func NewHTTPTransport(serverURL string) *HTTPTransport {
url := serverURL
if !strings.HasSuffix(url, "/") {
......@@ -112,14 +116,17 @@ func (transport *HTTPTransport) request(url string, method string, result interf
return nil
}
// Post sends the object to the server and parses its response into result.
func (transport *HTTPTransport) Post(url string, result interface{}, object interface{}) error {
return transport.request(url, http.MethodPost, result, object)
}
// Get performs a GET request and parses the server's response into result.
func (transport *HTTPTransport) Get(url string, result interface{}) error {
return transport.request(url, http.MethodGet, result, nil)
}
// Delete performs a DELETE.
func (transport *HTTPTransport) Delete(url string) {
// TODO
}
......@@ -13,22 +13,27 @@ import (
"github.com/mhe/gabi"
)
// SessionRequest contains the context and nonce for an IRMA session.
type SessionRequest struct {
Context *big.Int `json:"nonce"`
Nonce *big.Int `json:"context"`
}
// A DisclosureRequest is a request to disclose certain attributes.
type DisclosureRequest struct {
SessionRequest
Content AttributeDisjunctionList `json:"content"`
}
// A SignatureRequest is a a request to sign a message with certain attributes.
type SignatureRequest struct {
DisclosureRequest
Message string `json:"message"`
MessageType string `json:"messageType"`
}
// An IssuanceRequest is a request to issue certain credentials,
// optionally also asking for certain attributes to be simultaneously disclosed.
type IssuanceRequest struct {
SessionRequest
Credentials []*CredentialRequest `json:"credentials"`
......@@ -37,6 +42,8 @@ type IssuanceRequest struct {
state *issuanceState
}
// A CredentialRequest contains the attributes and metadata of a credential
// that will be issued in an IssuanceRequest.
type CredentialRequest struct {
Validity *Timestamp `json:"validity"`
KeyCounter int `json:"keyCounter"`
......@@ -52,6 +59,7 @@ type issuanceState struct {
builders []*gabi.CredentialBuilder
}
// AttributeList returns the list of attributes from this credential request.
func (cr *CredentialRequest) AttributeList() (*AttributeList, error) {
meta := NewMetadataAttribute()
meta.setKeyCounter(cr.KeyCounter)
......@@ -94,20 +102,50 @@ func newIssuanceState(request *IssuanceRequest) (*issuanceState, error) {
}, nil
}
func (ir *IssuanceRequest) DisjunctionList() AttributeDisjunctionList { return ir.Disclose }
func (ir *IssuanceRequest) GetContext() *big.Int { return ir.Context }
func (ir *IssuanceRequest) SetContext(context *big.Int) { ir.Context = context }
func (ir *IssuanceRequest) GetNonce() *big.Int { return ir.Nonce }
func (ir *IssuanceRequest) SetNonce(nonce *big.Int) { ir.Nonce = nonce }
// DisjunctionList returns the attributes that must be disclosed in this issuance session.
func (ir *IssuanceRequest) DisjunctionList() AttributeDisjunctionList { return ir.Disclose }
// GetContext returns the context of this session.
func (ir *IssuanceRequest) GetContext() *big.Int { return ir.Context }
// SetContext sets the context of this session.
func (ir *IssuanceRequest) SetContext(context *big.Int) { ir.Context = context }
// GetNonce returns the nonce of this session.
func (ir *IssuanceRequest) GetNonce() *big.Int { return ir.Nonce }
// SetNonce sets the nonce of this session.
func (ir *IssuanceRequest) SetNonce(nonce *big.Int) { ir.Nonce = nonce }
// DisjunctionList returns the attributes to be disclosed in this session.
func (dr *DisclosureRequest) DisjunctionList() AttributeDisjunctionList { return dr.Content }
func (dr *DisclosureRequest) GetContext() *big.Int { return dr.Context }
func (dr *DisclosureRequest) SetContext(context *big.Int) { dr.Context = context }
func (dr *DisclosureRequest) GetNonce() *big.Int { return dr.Nonce }
func (dr *DisclosureRequest) SetNonce(nonce *big.Int) { dr.Nonce = nonce }
func (sr *SignatureRequest) DisjunctionList() AttributeDisjunctionList { return sr.Content }
func (sr *SignatureRequest) GetContext() *big.Int { return sr.Context }
func (sr *SessionRequest) SetContext(context *big.Int) { sr.Context = context }
func (sr *SessionRequest) SetNonce(nonce *big.Int) { sr.Nonce = nonce }
// GetContext returns the context of this session.
func (dr *DisclosureRequest) GetContext() *big.Int { return dr.Context }
// SetContext sets the context of this session.
func (dr *DisclosureRequest) SetContext(context *big.Int) { dr.Context = context }
// GetNonce returns the nonce of this session.
func (dr *DisclosureRequest) GetNonce() *big.Int { return dr.Nonce }
// SetNonce sets the nonce of this session.
func (dr *DisclosureRequest) SetNonce(nonce *big.Int) { dr.Nonce = nonce }
// DisjunctionList returns the attributes with which the message must be signed.
func (sr *SignatureRequest) DisjunctionList() AttributeDisjunctionList { return sr.Content }
// GetContext returns the context of this session.
func (sr *SignatureRequest) GetContext() *big.Int { return sr.Context }
// SetContext sets the context of this session.
func (sr *SessionRequest) SetContext(context *big.Int) { sr.Context = context }
// SetNonce sets the nonce of this session.
func (sr *SessionRequest) SetNonce(nonce *big.Int) { sr.Nonce = nonce }
// GetNonce returns the nonce of this signature session
// (with the message already hashed into it).
func (sr *SignatureRequest) GetNonce() *big.Int {
hashbytes := sha256.Sum256([]byte(sr.Message))
hashint := new(big.Int).SetBytes(hashbytes[:])
......
......@@ -23,6 +23,7 @@ const (
cardemuXML = "../cardemu.xml"
)
// PathExists checks if the specified path exists.
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
......
......@@ -186,6 +186,7 @@ func pathToDescription(path string, description interface{}) (bool, error) {
return true, nil
}
// Contains checks if the store contains the specified credential type.
func (store *ConfigurationStore) Contains(cred CredentialTypeIdentifier) bool {
return store.SchemeManagers[cred.IssuerIdentifier().SchemeManagerIdentifier()] != nil &&
store.Issuers[cred.IssuerIdentifier()] != 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