Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
IRMA
Github mirrors
irmago
Commits
3b7621ea
Commit
3b7621ea
authored
Sep 01, 2017
by
Sietse Ringers
Browse files
Documenting
parent
645b8397
Changes
12
Hide whitespace changes
Inline
Side-by-side
attributes.go
View file @
3b7621ea
...
...
@@ -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
""
...
...
descriptions.go
View file @
3b7621ea
...
...
@@ -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
{
...
...
identifiers.go
View file @
3b7621ea
...
...
@@ -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
)
...
...
manager.go
View file @
3b7621ea
...
...
@@ -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"
)
...
...
protocol/messages.go
View file @
3b7621ea
...
...
@@ -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
)
...
...
protocol/requests.go
View file @
3b7621ea
...
...
@@ -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
}
protocol/server.go
View file @
3b7621ea
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
...
...
protocol/session.go
View file @
3b7621ea
...
...
@@ -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.
...
...
protocol/transport.go
View file @
3b7621ea
...
...
@@ -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
}
requests.go
View file @
3b7621ea
...
...
@@ -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
[
:
])
...
...
storage.go
View file @
3b7621ea
...
...
@@ -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
{
...
...
store.go
View file @
3b7621ea
...
...
@@ -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
&&
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment