func signRequest(w http.ResponseWriter, r *http.Request) { if registration == nil { http.Error(w, "registration missing", http.StatusBadRequest) return } c, err := u2f.NewChallenge(appID, trustedFacets) if err != nil { log.Printf("u2f.NewChallenge error: %v", err) http.Error(w, "error", http.StatusInternalServerError) return } challenge = c var reg u2f.Registration if err := reg.UnmarshalBinary(registration); err != nil { log.Printf("reg.UnmarshalBinary error: %v", err) http.Error(w, "error", http.StatusInternalServerError) return } req := c.SignRequest(reg) log.Printf("signRequest: %+v", req) json.NewEncoder(w).Encode(req) }
func TestGoodRegistration(t *testing.T) { ctx, err := aetest.NewContext(nil) if err != nil { t.Fatal(err) } defer ctx.Close() var testID = "test-id-🔒" // Mimic NewChallenge ckey := makeKey(ctx, testID, "Challenge") _, err = datastore.Put(ctx, ckey, &fakeRegistrationChallenge) if err != nil { t.Fatalf("datastore.Put error: %v", err) } // log.Printf("Challenge: %+v", fakeRegistrationChallenge) if err := StoreResponse(ctx, testID, fakeRegistrationResponse); err != nil { t.Fatalf("StoreRegistration: %v", err) } // Load what was just saved and verify it. pkey := MakeParentKey(ctx) q := datastore.NewQuery("Registration"). Ancestor(pkey). Filter("UserIdentity =", testID) qt := q.Run(ctx) if count, err := q.Count(ctx); err != nil { t.Fatalf("Count error: %v", err) } else if count != 1 { t.Fatalf("Expected only 1 item to be found.") } var regi Registration if _, err = qt.Next(®i); err != nil { t.Fatalf("datastore.Get (%+v): %+v", qt, regi) } // Verify the stored info. if regi.Counter != 0 { t.Error("Expected Counter to be 0") } if regi.UserIdentity != testID { t.Error("Expected user identity %v to be %v", regi.UserIdentity, testID) } // TODO: Ensure we delete the challenge. u2fReg := new(u2f.Registration) if err := u2fReg.UnmarshalBinary(regi.U2FRegistrationBytes); err != nil { t.Fatalf("Unable to convert registration to struct: %+v", err) } }
func signChallengeRequest(c u2f.Challenge, regi Registration) (*u2f.SignRequest, error) { var reg u2f.Registration buf := regi.U2FRegistrationBytes if err := reg.UnmarshalBinary(buf); err != nil { return nil, fmt.Errorf("reg.UnmarshalBinary %v", err) } return c.SignRequest(reg), nil }
// --- testSignChallenge --- func testSignChallenge(challenge u2f.Challenge, regi Registration, signResp u2f.SignResponse) error { var reg u2f.Registration if err := reg.UnmarshalBinary(regi.U2FRegistrationBytes); err != nil { return fmt.Errorf("reg.UnmarshalBinary error: %v", err) } // The AppEngine datastore does not accept uint types, see: // https://github.com/golang/appengine/blob/master/datastore/save.go#L148 // So we cast int64 to uint32 when coming from the datastore, and back. newCounter, err := reg.Authenticate(signResp, challenge, uint32(regi.Counter)) if err != nil { return fmt.Errorf("VerifySignResponse error: %v", err) } // Update the counter for the next auth. regi.Counter = int64(newCounter) return nil }
func signResponse(w http.ResponseWriter, r *http.Request) { var signResp u2f.SignResponse if err := json.NewDecoder(r.Body).Decode(&signResp); err != nil { http.Error(w, "invalid response: "+err.Error(), http.StatusBadRequest) return } log.Printf("signResponse: %+v", signResp) if challenge == nil { http.Error(w, "challenge missing", http.StatusBadRequest) return } if registration == nil { http.Error(w, "registration missing", http.StatusBadRequest) return } var reg u2f.Registration if err := reg.UnmarshalBinary(registration); err != nil { log.Printf("reg.UnmarshalBinary error: %v", err) http.Error(w, "error", http.StatusInternalServerError) return } newCounter, err := reg.Authenticate(signResp, *challenge, counter) if err != nil { log.Printf("VerifySignResponse error: %v", err) http.Error(w, "error verifying response", http.StatusInternalServerError) return } log.Printf("newCounter: %d", newCounter) counter = newCounter w.Write([]byte("success")) }