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

More keyshare registration

parent f6ea152b
......@@ -27,7 +27,8 @@ func TestMain(m *testing.M) {
type IgnoringKeyshareHandler struct{}
func (i *IgnoringKeyshareHandler) StartKeyshareRegistration(m *SchemeManager) {}
func (i *IgnoringKeyshareHandler) StartKeyshareRegistration(m *SchemeManager, callback func(e, p string)) {
}
func parseMetaStore(t *testing.T) {
require.NoError(t, MetaStore.ParseFolder("testdata/irma_configuration"), "MetaStore.ParseFolder() failed")
......
......@@ -20,14 +20,16 @@ type keyshareRegistration struct {
}
type KeyshareHandler interface {
StartKeyshareRegistration(manager *SchemeManager)
StartKeyshareRegistration(manager *SchemeManager, registrationCallback func(email, pin string))
}
func newKeyshareServer(privatekey *paillierPrivateKey, url, email string) (ks *keyshareServer, err error) {
ks.Nonce = make([]byte, 0, 32)
ks.URL = url
ks.Username = email
ks.PrivateKey = privatekey
ks = &keyshareServer{
Nonce: make([]byte, 32),
URL: url,
Username: email,
PrivateKey: privatekey,
}
_, err = rand.Read(ks.Nonce)
return
}
......@@ -36,24 +38,3 @@ func (ks *keyshareServer) HashedPin(pin string) string {
hash := sha256.Sum256(append(ks.Nonce, []byte(pin)...))
return base64.RawStdEncoding.EncodeToString(hash[:])
}
func KeyshareEnroll(manager *SchemeManager, email, pin string) error {
transport := NewHTTPTransport(manager.KeyshareServer)
kss, err := newKeyshareServer(Manager.paillierKey(), manager.URL, email)
if err != nil {
return err
}
message := keyshareRegistration{
Username: email,
Pin: kss.HashedPin(pin),
PublicKey: (*paillierPublicKey)(&kss.PrivateKey.PublicKey),
}
// TODO: examine error returned by Post() to see if it tells us that the email address is already in use
result := &struct{}{}
err = transport.Post("/web/users/selfenroll", result, message)
if err != nil {
return err
}
return Manager.addKeyshareServer(manager, kss)
}
......@@ -323,7 +323,44 @@ func (cm *CredentialManager) unenrolledKeyshareServers() []*SchemeManager {
return list
}
func (cm *CredentialManager) addKeyshareServer(manager *SchemeManager, kss *keyshareServer) error {
cm.keyshareServers[manager.Identifier()] = kss
func (cm *CredentialManager) KeyshareEnroll(managerId SchemeManagerIdentifier, email, pin string) error {
manager, ok := MetaStore.SchemeManagers[managerId]
if !ok {
return errors.New("Unknown scheme manager")
}
if len(manager.KeyshareServer) == 0 {
return errors.New("Scheme manager has no keyshare server")
}
if len(pin) < 5 {
return errors.New("PIN too short, must be at least 5 characters")
}
transport := NewHTTPTransport(manager.KeyshareServer)
kss, err := newKeyshareServer(Manager.paillierKey(), manager.URL, email)
if err != nil {
return err
}
message := keyshareRegistration{
Username: email,
Pin: kss.HashedPin(pin),
PublicKey: (*paillierPublicKey)(&kss.PrivateKey.PublicKey),
}
// TODO: examine error returned by Post() to see if it tells us that the email address is already in use
result := &struct{}{}
err = transport.Post("web/users/selfenroll", result, message)
if err != nil {
return err
}
cm.keyshareServers[managerId] = kss
return cm.storeKeyshareServers()
}
func (cm *CredentialManager) KeyshareRemove(manager SchemeManagerIdentifier) error {
if _, contains := cm.keyshareServers[manager]; !contains {
return errors.New("Can't uninstall unknown keyshare server")
}
delete(cm.keyshareServers, manager)
return cm.storeKeyshareServers()
}
......@@ -128,7 +128,7 @@ func (session *session) start() {
info := &SessionInfo{}
Err := session.transport.Get("jwt", info)
if Err != nil {
session.Handler.Failure(session.Action, Err)
session.Handler.Failure(session.Action, Err.(*irmago.Error))
return
}
jwtparts := strings.Split(info.Jwt, ".")
......@@ -237,7 +237,7 @@ func (session *session) do(proceed bool, choice *irmago.DisclosureChoice) {
fallthrough
case ActionDisclosing:
response := ""
Err = session.transport.Post("proofs", &response, message)
Err = session.transport.Post("proofs", &response, message).(*irmago.Error)
if Err != nil {
session.Handler.Failure(session.Action, Err)
return
......@@ -248,7 +248,7 @@ func (session *session) do(proceed bool, choice *irmago.DisclosureChoice) {
}
case ActionIssuing:
response := []*gabi.IssueSignatureMessage{}
Err = session.transport.Post("commitments", &response, message)
Err = session.transport.Post("commitments", &response, message).(*irmago.Error)
if Err != nil {
session.Handler.Failure(session.Action, Err)
return
......
// +build integration
/// +build integration
package protocol
......@@ -9,6 +9,10 @@ import (
"os"
"testing"
"crypto/rand"
"encoding/hex"
"github.com/credentials/irmago"
"github.com/stretchr/testify/require"
)
......@@ -212,3 +216,19 @@ func sessionHelper(t *testing.T, jwtcontents interface{}, url string) {
teardown(t)
}
func TestKeyshareRegistration(t *testing.T) {
parseMetaStore(t)
parseStorage(t)
parseAndroidStorage(t)
test := irmago.NewSchemeManagerIdentifier("test")
err := irmago.Manager.KeyshareRemove(test)
require.NoError(t, err)
bytes := make([]byte, 8, 8)
rand.Read(bytes)
email := fmt.Sprintf("%s@example.com", hex.EncodeToString(bytes))
err = irmago.Manager.KeyshareEnroll(test, email, "12345")
require.NoError(t, err)
}
......@@ -40,7 +40,7 @@ func PathExists(path string) (bool, error) {
}
// Init deserializes the credentials from storage.
func (cm *CredentialManager) Init(path string, pinProvider KeyshareHandler) (err error) {
func (cm *CredentialManager) Init(path string, keyshareHandler KeyshareHandler) (err error) {
cm.storagePath = path
err = cm.ensureStorageExists()
......@@ -70,10 +70,12 @@ func (cm *CredentialManager) Init(path string, pinProvider KeyshareHandler) (err
case 0:
return
case 1:
if pinProvider == nil {
return errors.New("Keyshare server found but no PinPovider was given")
if keyshareHandler == nil {
return errors.New("Keyshare server found but no KeyshareHandler was given")
}
pinProvider.StartKeyshareRegistration(unenrolled[0])
keyshareHandler.StartKeyshareRegistration(unenrolled[0], func(email, pin string) {
cm.KeyshareEnroll(unenrolled[0].Identifier(), email, pin)
})
default:
return errors.New("Too many keyshare servers")
}
......
......@@ -77,7 +77,7 @@ func NewHTTPTransport(serverURL string) *HTTPTransport {
}
}
func (transport *HTTPTransport) request(url string, method string, result interface{}, object interface{}) *Error {
func (transport *HTTPTransport) request(url string, method string, result interface{}, object interface{}) error {
if method != http.MethodPost && method != http.MethodGet {
panic("Unsupported HTTP method " + method)
}
......@@ -145,12 +145,12 @@ func (transport *HTTPTransport) request(url string, method string, result interf
}
// Post sends the object to the server and parses its response into result.
func (transport *HTTPTransport) Post(url string, result interface{}, object interface{}) *Error {
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 {
func (transport *HTTPTransport) Get(url string, result interface{}) error {
return transport.request(url, http.MethodGet, result, 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