Commit 12301e6b authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Renaming, 2: Moving Client to new irmaclient subpackage

parent a2f3c61d
...@@ -40,7 +40,7 @@ type metadataField struct { ...@@ -40,7 +40,7 @@ type metadataField struct {
type MetadataAttribute struct { type MetadataAttribute struct {
Int *big.Int Int *big.Int
pk *gabi.PublicKey pk *gabi.PublicKey
store *ConfigurationStore Store *ConfigurationStore
} }
// AttributeList contains attributes, excluding the secret key, // AttributeList contains attributes, excluding the secret key,
...@@ -63,12 +63,12 @@ func NewAttributeListFromInts(ints []*big.Int, store *ConfigurationStore) *Attri ...@@ -63,12 +63,12 @@ func NewAttributeListFromInts(ints []*big.Int, store *ConfigurationStore) *Attri
func (al *AttributeList) Info() *CredentialInfo { func (al *AttributeList) Info() *CredentialInfo {
if al.info == nil { if al.info == nil {
al.info = NewCredentialInfo(al.Ints, al.store) al.info = NewCredentialInfo(al.Ints, al.Store)
} }
return al.info return al.info
} }
func (al *AttributeList) hash() string { func (al *AttributeList) Hash() string {
if al.h == "" { if al.h == "" {
bytes := []byte{} bytes := []byte{}
for _, i := range al.Ints { for _, i := range al.Ints {
...@@ -91,7 +91,7 @@ func (al *AttributeList) Strings() []TranslatedString { ...@@ -91,7 +91,7 @@ func (al *AttributeList) Strings() []TranslatedString {
return al.strings return al.strings
} }
func (al *AttributeList) untranslatedAttribute(identifier AttributeTypeIdentifier) string { func (al *AttributeList) UntranslatedAttribute(identifier AttributeTypeIdentifier) string {
if al.CredentialType().Identifier() != identifier.CredentialTypeIdentifier() { if al.CredentialType().Identifier() != identifier.CredentialTypeIdentifier() {
return "" return ""
} }
...@@ -118,7 +118,7 @@ func (al *AttributeList) Attribute(identifier AttributeTypeIdentifier) Translate ...@@ -118,7 +118,7 @@ func (al *AttributeList) Attribute(identifier AttributeTypeIdentifier) Translate
// MetadataFromInt wraps the given Int // MetadataFromInt wraps the given Int
func MetadataFromInt(i *big.Int, store *ConfigurationStore) *MetadataAttribute { func MetadataFromInt(i *big.Int, store *ConfigurationStore) *MetadataAttribute {
return &MetadataAttribute{Int: i, store: store} return &MetadataAttribute{Int: i, Store: store}
} }
// NewMetadataAttribute constructs a new instance containing the default values: // NewMetadataAttribute constructs a new instance containing the default values:
...@@ -149,7 +149,7 @@ func (attr *MetadataAttribute) Bytes() []byte { ...@@ -149,7 +149,7 @@ func (attr *MetadataAttribute) Bytes() []byte {
func (attr *MetadataAttribute) PublicKey() (*gabi.PublicKey, error) { func (attr *MetadataAttribute) PublicKey() (*gabi.PublicKey, error) {
if attr.pk == nil { if attr.pk == nil {
var err error var err error
attr.pk, err = attr.store.PublicKey(attr.CredentialType().IssuerIdentifier(), attr.KeyCounter()) attr.pk, err = attr.Store.PublicKey(attr.CredentialType().IssuerIdentifier(), attr.KeyCounter())
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -206,7 +206,7 @@ func (attr *MetadataAttribute) setExpiryDate(timestamp *Timestamp) error { ...@@ -206,7 +206,7 @@ func (attr *MetadataAttribute) setExpiryDate(timestamp *Timestamp) error {
// CredentialType returns the credential type of the current instance // CredentialType returns the credential type of the current instance
// using the MetaStore. // using the MetaStore.
func (attr *MetadataAttribute) CredentialType() *CredentialType { func (attr *MetadataAttribute) CredentialType() *CredentialType {
return attr.store.hashToCredentialType(attr.field(credentialID)) return attr.Store.hashToCredentialType(attr.field(credentialID))
} }
func (attr *MetadataAttribute) setCredentialTypeIdentifier(id string) { func (attr *MetadataAttribute) setCredentialTypeIdentifier(id string) {
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"strings" "strings"
"github.com/credentials/irmago/internal/fs"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/mhe/gabi" "github.com/mhe/gabi"
) )
...@@ -38,7 +39,7 @@ func NewConfigurationStore(path string, assets string) (store *ConfigurationStor ...@@ -38,7 +39,7 @@ func NewConfigurationStore(path string, assets string) (store *ConfigurationStor
path: path, path: path,
} }
if err = ensureDirectoryExists(store.path); err != nil { if err = fs.EnsureDirectoryExists(store.path); err != nil {
return nil, err return nil, err
} }
if assets != "" { if assets != "" {
...@@ -226,7 +227,7 @@ func (store *ConfigurationStore) Contains(cred CredentialTypeIdentifier) bool { ...@@ -226,7 +227,7 @@ func (store *ConfigurationStore) Contains(cred CredentialTypeIdentifier) bool {
} }
func (store *ConfigurationStore) Copy(source string, parse bool) error { func (store *ConfigurationStore) Copy(source string, parse bool) error {
if err := ensureDirectoryExists(store.path); err != nil { if err := fs.EnsureDirectoryExists(store.path); err != nil {
return err return err
} }
...@@ -237,7 +238,7 @@ func (store *ConfigurationStore) Copy(source string, parse bool) error { ...@@ -237,7 +238,7 @@ func (store *ConfigurationStore) Copy(source string, parse bool) error {
} }
subpath := path[len(source):] subpath := path[len(source):]
if info.IsDir() { if info.IsDir() {
if err := ensureDirectoryExists(store.path + subpath); err != nil { if err := fs.EnsureDirectoryExists(store.path + subpath); err != nil {
return err return err
} }
} else { } else {
...@@ -250,7 +251,7 @@ func (store *ConfigurationStore) Copy(source string, parse bool) error { ...@@ -250,7 +251,7 @@ func (store *ConfigurationStore) Copy(source string, parse bool) error {
if err != nil { if err != nil {
return err return err
} }
if err := saveFile(store.path+subpath, bytes); err != nil { if err := fs.SaveFile(store.path+subpath, bytes); err != nil {
return err return err
} }
} }
...@@ -314,14 +315,14 @@ func (store *ConfigurationStore) RemoveSchemeManager(id SchemeManagerIdentifier) ...@@ -314,14 +315,14 @@ func (store *ConfigurationStore) RemoveSchemeManager(id SchemeManagerIdentifier)
func (store *ConfigurationStore) AddSchemeManager(manager *SchemeManager) error { func (store *ConfigurationStore) AddSchemeManager(manager *SchemeManager) error {
name := manager.ID name := manager.ID
if err := ensureDirectoryExists(fmt.Sprintf("%s/%s", store.path, name)); err != nil { if err := fs.EnsureDirectoryExists(fmt.Sprintf("%s/%s", store.path, name)); err != nil {
return err return err
} }
b, err := xml.Marshal(manager) b, err := xml.Marshal(manager)
if err != nil { if err != nil {
return err return err
} }
if err := saveFile(fmt.Sprintf("%s/%s/description.xml", store.path, name), b); err != nil { if err := fs.SaveFile(fmt.Sprintf("%s/%s/description.xml", store.path, name), b); err != nil {
return err return err
} }
store.SchemeManagers[NewSchemeManagerIdentifier(name)] = manager store.SchemeManagers[NewSchemeManagerIdentifier(name)] = manager
...@@ -378,7 +379,7 @@ func (store *ConfigurationStore) Download(set *IrmaIdentifierSet) (*IrmaIdentifi ...@@ -378,7 +379,7 @@ func (store *ConfigurationStore) Download(set *IrmaIdentifierSet) (*IrmaIdentifi
issuer := credid.IssuerIdentifier() issuer := credid.IssuerIdentifier()
manager := issuer.SchemeManagerIdentifier() manager := issuer.SchemeManagerIdentifier()
local := fmt.Sprintf("%s/%s/%s/Issues", store.path, manager.Name(), issuer.Name()) local := fmt.Sprintf("%s/%s/%s/Issues", store.path, manager.Name(), issuer.Name())
if err := ensureDirectoryExists(local); err != nil { if err := fs.EnsureDirectoryExists(local); err != nil {
return nil, err return nil, err
} }
if transport.GetFile( if transport.GetFile(
......
package irmago package irmago
import ( import (
"strings"
"math/big"
"fmt" "fmt"
"math/big"
"strings"
"github.com/mhe/gabi" "github.com/credentials/irmago/internal/fs"
) )
// credential represents an IRMA credential, whose zeroth attribute
// is always the secret key and the first attribute the metadata attribute.
type credential struct {
*gabi.Credential
*MetadataAttribute
attrs *AttributeList
}
// CredentialInfo contains all information of an IRMA credential. // CredentialInfo contains all information of an IRMA credential.
type CredentialInfo struct { type CredentialInfo struct {
CredentialTypeID string // e.g., "irma-demo.RU.studentCard" CredentialTypeID string // e.g., "irma-demo.RU.studentCard"
...@@ -46,7 +36,7 @@ func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialIn ...@@ -46,7 +36,7 @@ func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialIn
} }
path := fmt.Sprintf("%s/%s/%s/Issues/%s/logo.png", store.path, credtype.SchemeManagerID, credtype.IssuerID, credtype.ID) path := fmt.Sprintf("%s/%s/%s/Issues/%s/logo.png", store.path, credtype.SchemeManagerID, credtype.IssuerID, credtype.ID)
exists, err := PathExists(path) exists, err := fs.PathExists(path)
if err != nil { if err != nil {
return nil return nil
} }
...@@ -64,29 +54,8 @@ func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialIn ...@@ -64,29 +54,8 @@ func NewCredentialInfo(ints []*big.Int, store *ConfigurationStore) *CredentialIn
Expires: Timestamp(meta.Expiry()), Expires: Timestamp(meta.Expiry()),
Attributes: attrs, Attributes: attrs,
Logo: path, Logo: path,
Hash: NewAttributeListFromInts(ints, store).hash(), Hash: NewAttributeListFromInts(ints, store).Hash(),
}
}
func newCredential(gabicred *gabi.Credential, store *ConfigurationStore) (*credential, error) {
meta := MetadataFromInt(gabicred.Attributes[1], store)
cred := &credential{
Credential: gabicred,
MetadataAttribute: meta,
}
var err error
cred.Pk, err = store.PublicKey(meta.CredentialType().IssuerIdentifier(), cred.KeyCounter())
if err != nil {
return nil, err
}
return cred, nil
}
func (cred *credential) AttributeList() *AttributeList {
if cred.attrs == nil {
cred.attrs = NewAttributeListFromInts(cred.Credential.Attributes[1:], cred.MetadataAttribute.store)
} }
return cred.attrs
} }
// Len implements sort.Interface. // Len implements sort.Interface.
...@@ -101,6 +70,6 @@ func (cl CredentialInfoList) Swap(i, j int) { ...@@ -101,6 +70,6 @@ func (cl CredentialInfoList) Swap(i, j int) {
// Less implements sort.Interface. // Less implements sort.Interface.
func (cl CredentialInfoList) Less(i, j int) bool { func (cl CredentialInfoList) Less(i, j int) bool {
// TODO Decide on sorting, and if it depends on a TranslatedString, allow language choosing // TODO Decide on sorting, and if it depends on a irmago.TranslatedString, allow language choosing
return strings.Compare(cl[i].Name, cl[j].Name) > 0 return strings.Compare(cl[i].Name, cl[j].Name) > 0
} }
package fs
import (
"crypto/rand"
"encoding/hex"
"io/ioutil"
"os"
"path"
"github.com/pkg/errors"
)
// AssertPathExists returns nil only if it has been successfully
// verified that the specified path exists.
func AssertPathExists(path string) error {
exist, err := PathExists(path)
if err != nil {
return err
}
if !exist {
return errors.Errorf("Path %s does not exist", path)
}
return nil
}
// PathExists checks if the specified path exists.
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return true, err
}
func EnsureDirectoryExists(path string) error {
exists, err := PathExists(path)
if err != nil {
return err
}
if exists {
return nil
}
return os.Mkdir(path, 0700)
}
// Save the filecontents at the specified path atomically:
// - first save the content in a temp file with a random filename in the same dir
// - then rename the temp file to the specified filepath, overwriting the old file
func SaveFile(filepath string, content []byte) (err error) {
dir := path.Dir(filepath)
// Read random data for filename and convert to hex
randBytes := make([]byte, 16)
_, err = rand.Read(randBytes)
if err != nil {
return
}
tempfilename := hex.EncodeToString(randBytes)
// Create temp file
err = ioutil.WriteFile(dir+"/"+tempfilename, content, 0600)
if err != nil {
return
}
// Rename, overwriting old file
return os.Rename(dir+"/"+tempfilename, filepath)
}
package irmago package irmaclient
import ( import (
"crypto/rand" "crypto/rand"
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"time" "time"
"github.com/credentials/go-go-gadget-paillier" "github.com/credentials/go-go-gadget-paillier"
"github.com/credentials/irmago"
"github.com/credentials/irmago/internal/fs"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/mhe/gabi" "github.com/mhe/gabi"
) )
...@@ -35,9 +37,9 @@ import ( ...@@ -35,9 +37,9 @@ import (
type Client struct { type Client struct {
// Stuff we manage on disk // Stuff we manage on disk
secretkey *secretKey secretkey *secretKey
attributes map[CredentialTypeIdentifier][]*AttributeList attributes map[irmago.CredentialTypeIdentifier][]*irmago.AttributeList
credentials map[CredentialTypeIdentifier]map[int]*credential credentials map[irmago.CredentialTypeIdentifier]map[int]*credential
keyshareServers map[SchemeManagerIdentifier]*keyshareServer keyshareServers map[irmago.SchemeManagerIdentifier]*keyshareServer
paillierKeyCache *paillierPrivateKey paillierKeyCache *paillierPrivateKey
logs []*LogEntry logs []*LogEntry
updates []update updates []update
...@@ -46,24 +48,25 @@ type Client struct { ...@@ -46,24 +48,25 @@ type Client struct {
storage storage storage storage
// Other state // Other state
ConfigurationStore *ConfigurationStore ConfigurationStore *irmago.ConfigurationStore
UnenrolledSchemeManagers []SchemeManagerIdentifier UnenrolledSchemeManagers []irmago.SchemeManagerIdentifier
irmaConfigurationPath string irmaConfigurationPath string
androidStoragePath string androidStoragePath string
handler ClientHandler handler ClientHandler
state *issuanceState
} }
// KeyshareHandler is used for asking the user for his email address and PIN, // KeyshareHandler is used for asking the user for his email address and PIN,
// for enrolling at a keyshare server. // for enrolling at a keyshare server.
type KeyshareHandler interface { type KeyshareHandler interface {
EnrollmentError(manager SchemeManagerIdentifier, err error) EnrollmentError(manager irmago.SchemeManagerIdentifier, err error)
EnrollmentSuccess(manager SchemeManagerIdentifier) EnrollmentSuccess(manager irmago.SchemeManagerIdentifier)
} }
type ClientHandler interface { type ClientHandler interface {
KeyshareHandler KeyshareHandler
UpdateConfigurationStore(new *IrmaIdentifierSet) UpdateConfigurationStore(new *irmago.IrmaIdentifierSet)
UpdateAttributes() UpdateAttributes()
} }
...@@ -90,23 +93,23 @@ func NewClient( ...@@ -90,23 +93,23 @@ func NewClient(
handler ClientHandler, handler ClientHandler,
) (*Client, error) { ) (*Client, error) {
var err error var err error
if err = AssertPathExists(storagePath); err != nil { if err = fs.AssertPathExists(storagePath); err != nil {
return nil, err return nil, err
} }
if err = AssertPathExists(irmaConfigurationPath); err != nil { if err = fs.AssertPathExists(irmaConfigurationPath); err != nil {
return nil, err return nil, err
} }
cm := &Client{ cm := &Client{
credentials: make(map[CredentialTypeIdentifier]map[int]*credential), credentials: make(map[irmago.CredentialTypeIdentifier]map[int]*credential),
keyshareServers: make(map[SchemeManagerIdentifier]*keyshareServer), keyshareServers: make(map[irmago.SchemeManagerIdentifier]*keyshareServer),
attributes: make(map[CredentialTypeIdentifier][]*AttributeList), attributes: make(map[irmago.CredentialTypeIdentifier][]*irmago.AttributeList),
irmaConfigurationPath: irmaConfigurationPath, irmaConfigurationPath: irmaConfigurationPath,
androidStoragePath: androidStoragePath, androidStoragePath: androidStoragePath,
handler: handler, handler: handler,
} }
cm.ConfigurationStore, err = NewConfigurationStore(storagePath+"/irma_configuration", irmaConfigurationPath) cm.ConfigurationStore, err = irmago.NewConfigurationStore(storagePath+"/irma_configuration", irmaConfigurationPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -151,8 +154,8 @@ func NewClient( ...@@ -151,8 +154,8 @@ func NewClient(
} }
// CredentialInfoList returns a list of information of all contained credentials. // CredentialInfoList returns a list of information of all contained credentials.
func (client *Client) CredentialInfoList() CredentialInfoList { func (client *Client) CredentialInfoList() irmago.CredentialInfoList {
list := CredentialInfoList([]*CredentialInfo{}) list := irmago.CredentialInfoList([]*irmago.CredentialInfo{})
for _, attrlistlist := range client.attributes { for _, attrlistlist := range client.attributes {
for index, attrlist := range attrlistlist { for index, attrlist := range attrlistlist {
...@@ -174,7 +177,7 @@ func (client *Client) addCredential(cred *credential, storeAttributes bool) (err ...@@ -174,7 +177,7 @@ func (client *Client) addCredential(cred *credential, storeAttributes bool) (err
// Don't add duplicate creds // Don't add duplicate creds
for _, attrlistlist := range client.attributes { for _, attrlistlist := range client.attributes {
for _, attrs := range attrlistlist { for _, attrs := range attrlistlist {
if attrs.hash() == cred.AttributeList().hash() { if attrs.Hash() == cred.AttributeList().Hash() {
return nil return nil
} }
} }
...@@ -212,7 +215,7 @@ func generateSecretKey() (*secretKey, error) { ...@@ -212,7 +215,7 @@ func generateSecretKey() (*secretKey, error) {
// Removal methods // Removal methods
func (client *Client) remove(id CredentialTypeIdentifier, index int, storenow bool) error { func (client *Client) remove(id irmago.CredentialTypeIdentifier, index int, storenow bool) error {
// Remove attributes // Remove attributes
list, exists := client.attributes[id] list, exists := client.attributes[id]
if !exists || index >= len(list) { if !exists || index >= len(list) {
...@@ -239,20 +242,20 @@ func (client *Client) remove(id CredentialTypeIdentifier, index int, storenow bo ...@@ -239,20 +242,20 @@ func (client *Client) remove(id CredentialTypeIdentifier, index int, storenow bo
return err return err
} }
removed := map[CredentialTypeIdentifier][]TranslatedString{} removed := map[irmago.CredentialTypeIdentifier][]irmago.TranslatedString{}
removed[id] = attrs.Strings() removed[id] = attrs.Strings()
if storenow { if storenow {
return client.addLogEntry(&LogEntry{ return client.addLogEntry(&LogEntry{
Type: actionRemoval, Type: actionRemoval,
Time: Timestamp(time.Now()), Time: irmago.Timestamp(time.Now()),
Removed: removed, Removed: removed,
}) })
} }
return nil return nil
} }
func (client *Client) RemoveCredential(id CredentialTypeIdentifier, index int) error { func (client *Client) RemoveCredential(id irmago.CredentialTypeIdentifier, index int) error {
return client.remove(id, index, true) return client.remove(id, index, true)
} }
...@@ -265,7 +268,7 @@ func (client *Client) RemoveCredentialByHash(hash string) error { ...@@ -265,7 +268,7 @@ func (client *Client) RemoveCredentialByHash(hash string) error {
} }
func (client *Client) RemoveAllCredentials() error { func (client *Client) RemoveAllCredentials() error {
removed := map[CredentialTypeIdentifier][]TranslatedString{} removed := map[irmago.CredentialTypeIdentifier][]irmago.TranslatedString{}
for _, attrlistlist := range client.attributes { for _, attrlistlist := range client.attributes {
for _, attrs := range attrlistlist { for _, attrs := range attrlistlist {
if attrs.CredentialType() != nil { if attrs.CredentialType() != nil {
...@@ -274,14 +277,14 @@ func (client *Client) RemoveAllCredentials() error { ...@@ -274,14 +277,14 @@ func (client *Client) RemoveAllCredentials() error {
client.storage.DeleteSignature(attrs) client.storage.DeleteSignature(attrs)
} }
} }
client.attributes = map[CredentialTypeIdentifier][]*AttributeList{} client.attributes = map[irmago.CredentialTypeIdentifier][]*irmago.AttributeList{}
if err := client.storage.StoreAttributes(client.attributes); err != nil { if err := client.storage.StoreAttributes(client.attributes); err != nil {
return err return err
} }
logentry := &LogEntry{ logentry := &LogEntry{
Type: actionRemoval, Type: actionRemoval,
Time: Timestamp(time.Now()), Time: irmago.Timestamp(time.Now()),
Removed: removed, Removed: removed,
} }
if err := client.addLogEntry(logentry); err != nil { if err := client.addLogEntry(logentry); err != nil {
...@@ -293,17 +296,17 @@ func (client *Client) RemoveAllCredentials() error { ...@@ -293,17 +296,17 @@ func (client *Client) RemoveAllCredentials() error {
// Attribute and credential getter methods // Attribute and credential getter methods
// attrs returns cm.attributes[id], initializing it to an empty slice if neccesary // attrs returns cm.attributes[id], initializing it to an empty slice if neccesary
func (client *Client) attrs(id CredentialTypeIdentifier) []*AttributeList { func (client *Client) attrs(id irmago.CredentialTypeIdentifier) []*irmago.AttributeList {
list, exists := client.attributes[id] list, exists := client.attributes[id]
if !exists { if !exists {
list = make([]*AttributeList, 0, 1) list = make([]*irmago.AttributeList, 0, 1)
client.attributes[id] = list client.attributes[id] = list
} }
return list return list
} }
// creds returns cm.credentials[id], initializing it to an empty map if neccesary