Commit 8c057616 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Polish keyshare code

parent e121d72f
......@@ -13,9 +13,13 @@ import (
"github.com/mhe/gabi"
)
type KeyshareSessionHandler interface {
AskPin(remainingAttempts int, callback func(pin string))
type KeysharePinRequestor interface {
AskPin(remainingAttempts int, callback func(proceed bool, pin string))
}
type keyshareSessionHandler interface {
KeyshareDone(message interface{})
KeyshareCancelled()
KeyshareBlocked(duration int)
KeyshareError(err error)
}
......@@ -24,7 +28,8 @@ type keyshareSession struct {
session Session
builders []gabi.ProofBuilder
transports map[SchemeManagerIdentifier]*HTTPTransport
sessionHandler KeyshareSessionHandler
sessionHandler keyshareSessionHandler
pinRequestor KeysharePinRequestor
keyshareServer *keyshareServer
}
......@@ -108,10 +113,16 @@ func (ks *keyshareServer) HashedPin(pin string) string {
return base64.RawStdEncoding.EncodeToString(hash[:])
}
func StartKeyshareSession(
// startKeyshareSession starts and completes the entire keyshare protocol with all involved keyshare servers
// for the specified session, merging the keyshare proofs into the specified ProofBuilder's.
// The user's pin is retrieved using the KeysharePinRequestor, repeatedly, until either it is correct; or the
// user cancels; or one of the keyshare servers blocks us.
// Error, blocked or success of the keyshare session is reported back to the keyshareSessionHandler.
func startKeyshareSession(
session Session,
builders []gabi.ProofBuilder,
sessionHandler KeyshareSessionHandler,
sessionHandler keyshareSessionHandler,
pin KeysharePinRequestor,
) {
ksscount := 0
for _, managerId := range session.SchemeManagers() {
......@@ -135,6 +146,7 @@ func StartKeyshareSession(
builders: builders,
sessionHandler: sessionHandler,
transports: map[SchemeManagerIdentifier]*HTTPTransport{},
pinRequestor: pin,
}
askPin := false
......@@ -174,12 +186,15 @@ func StartKeyshareSession(
// Ask for a pin, repeatedly if necessary, and either continue the keyshare protocol
// with authorization, or stop the keyshare protocol and inform of failure.
func (ks *keyshareSession) VerifyPin(attempts int) {
ks.sessionHandler.AskPin(attempts, func(pin string) {
ks.pinRequestor.AskPin(attempts, func(proceed bool, pin string) {
success, attemptsRemaining, blocked, err := ks.verifyPinAttempt(pin)
if err != nil {
ks.sessionHandler.KeyshareError(err)
return
}
if !proceed {
ks.sessionHandler.KeyshareCancelled()
}
if blocked != 0 {
ks.sessionHandler.KeyshareBlocked(blocked)
return
......@@ -194,14 +209,11 @@ func (ks *keyshareSession) VerifyPin(attempts int) {
}
// Verify the specified pin at each of the keyshare servers involved in the specified session.
//
// - If the pin did not verify at one of the keyshare servers but there are attempts remaining,
// the amount of remaining attempts is returned as the second return value.
//
// - If the pin did not verify at one of the keyshare servers and there are no attempts remaining,
// the amount of time for which we are blocked at the keyshare server is returned as the third
// parameter.
//
// - If this or anything else (specified in err) goes wrong, success will be false.
// If all is ok, success will be true.
func (ks *keyshareSession) verifyPinAttempt(pin string) (success bool, tries int, blocked int, err error) {
......@@ -353,7 +365,7 @@ func (ks *keyshareSession) Finish(challenge *big.Int, responses map[SchemeManage
msg := struct {
ProofP *gabi.ProofP
}{}
_, err := JwtDecode(responses[managerId], msg)
_, err := jwtDecode(responses[managerId], msg)
if err != nil {
ks.sessionHandler.KeyshareError(err)
return
......
......@@ -107,8 +107,10 @@ const (
// Server rejected our response (second IRMA message)
ErrorRejected = ErrorCode("rejectedByServer")
// (De)serializing of a message failed
ErrorSerialization = ErrorCode("serializationError")
ErrorKeyshare = ErrorCode("keyshare")
ErrorSerialization = ErrorCode("serializationError")
// Error in keyshare protocol
ErrorKeyshare = ErrorCode("keyshare")
// Keyshare server has blocked us
ErrorKeyshareBlocked = ErrorCode("keyshareBlocked")
)
......@@ -119,7 +121,7 @@ func (e *Error) Error() string {
return string(e.ErrorCode)
}
func JwtDecode(jwt string, body interface{}) (string, error) {
func jwtDecode(jwt string, body interface{}) (string, error) {
jwtparts := strings.Split(jwt, ".")
if jwtparts == nil || len(jwtparts) < 2 {
return "", errors.New("Not a JWT")
......
......@@ -25,7 +25,7 @@ type Handler interface {
AskVerificationPermission(request DisclosureRequest, ServerName string, callback PermissionHandler)
AskSignaturePermission(request SignatureRequest, ServerName string, callback PermissionHandler)
AskPin(remainingAttempts int, callback func(pin string))
AskPin(remainingAttempts int, callback func(proceed bool, pin string))
}
// A session is an IRMA session.
......@@ -141,7 +141,7 @@ func (session *session) start() {
default:
panic("Invalid session type") // does not happen, session.Action has been checked earlier
}
server, err := JwtDecode(info.Jwt, session.jwt)
server, err := jwtDecode(info.Jwt, session.jwt)
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT, Err: err})
return
......@@ -219,18 +219,18 @@ func (session *session) do(proceed bool) {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorCrypto, Err: err})
}
StartKeyshareSession(session.irmaSession, builders, session)
startKeyshareSession(session.irmaSession, builders, session, session.Handler)
}
}
func (session *session) AskPin(remainingAttempts int, callback func(pin string)) {
session.Handler.AskPin(remainingAttempts, callback)
}
func (session *session) KeyshareDone(message interface{}) {
session.sendResponse(message)
}
func (session *session) KeyshareCancelled() {
session.Handler.Cancelled(session.Action)
}
func (session *session) KeyshareBlocked(duration int) {
session.Handler.Failure(
session.Action,
......
......@@ -54,8 +54,8 @@ func (th TestHandler) AskIssuancePermission(request IssuanceRequest, ServerName
func (th TestHandler) AskSignaturePermission(request SignatureRequest, ServerName string, callback PermissionHandler) {
th.AskVerificationPermission(request.DisclosureRequest, ServerName, callback)
}
func (th TestHandler) AskPin(remainingAttempts int, callback func(pin string)) {
callback("12345")
func (th TestHandler) AskPin(remainingAttempts int, callback func(proceed bool, pin string)) {
callback(true, "12345")
}
func getDisclosureJwt(name string, id AttributeTypeIdentifier) interface{} {
......
......@@ -18,6 +18,8 @@ type HTTPTransport struct {
headers map[string]string
}
const verbose = false
// NewHTTPTransport returns a new HTTPTransport.
func NewHTTPTransport(serverURL string) *HTTPTransport {
url := serverURL
......@@ -50,7 +52,9 @@ func (transport *HTTPTransport) request(url string, method string, result interf
if object != nil {
var objstr string
if objstr, isstr = object.(string); isstr {
fmt.Printf("GET %s\n", url)
if verbose {
fmt.Printf("GET %s\n", url)
}
reader = bytes.NewBuffer([]byte(objstr))
} else {
marshaled, err := json.Marshal(object)
......@@ -58,7 +62,9 @@ func (transport *HTTPTransport) request(url string, method string, result interf
return &Error{Err: err, ErrorCode: ErrorSerialization}
//return &TransportError{Err: err.Error()}
}
fmt.Printf("POST %s: %s\n", url, string(marshaled))
if verbose {
fmt.Printf("POST %s: %s\n", url, string(marshaled))
}
reader = bytes.NewBuffer(marshaled)
}
}
......@@ -95,11 +101,15 @@ func (transport *HTTPTransport) request(url string, method string, result interf
if apierr.ErrorName == "" { // Not an ApiErrorMessage
return &Error{ErrorCode: ErrorTransport, Status: res.StatusCode}
}
fmt.Printf("ERROR: %+v\n", apierr)
if verbose {
fmt.Printf("ERROR: %+v\n", apierr)
}
return &Error{ErrorCode: ErrorTransport, Status: res.StatusCode, ApiError: apierr}
}
fmt.Printf("RESPONSE: %s\n", string(body))
if verbose {
fmt.Printf("RESPONSE: %s\n", string(body))
}
err = json.Unmarshal(body, result)
if err != nil {
return &Error{Err: err, Status: res.StatusCode}
......
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