functional simple api

This commit is contained in:
2024-08-23 16:39:20 -05:00
parent f9354196dd
commit ae4f12c159
18 changed files with 234 additions and 216 deletions

View File

@@ -2,21 +2,19 @@ package api
import (
"encoding/json"
"go-nkode/core/model"
"go-nkode/core/nkode"
m "go-nkode/core/model"
"log"
"net/http"
)
type NKodeHandler struct {
Api nkode.NKodeAPI
Api m.NKodeAPIInterface
}
func (h *NKodeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case CreateNewCustomer:
h.CreateNewCustomerHandler(w, r)
return
case GenerateSignupInterface:
h.GenerateSignupInterfaceHandler(w, r)
case SetNKode:
@@ -31,8 +29,8 @@ func (h *NKodeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.RenewAttributesHandler(w, r)
default:
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("404 not found"))
log.Fatal(r.URL.Path, " not found")
_, err := w.Write([]byte("404 not found"))
log.Println(err)
}
}
@@ -41,31 +39,31 @@ func (h *NKodeHandler) CreateNewCustomerHandler(w http.ResponseWriter, r *http.R
methodNotAllowed(w)
return
}
var customerPost model.NewCustomerPost
var customerPost m.NewCustomerPost
err := decodeJson(w, r, &customerPost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
customerId, err := h.Api.CreateNewCustomer(customerPost.KeypadSize, customerPost.NKodePolicy)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
respBody := model.CreateNewCustomerResp{
respBody := m.CreateNewCustomerResp{
CustomerId: *customerId,
}
respBytes, err := json.Marshal(respBody)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
_, err = w.Write(respBytes)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -79,33 +77,29 @@ func (h *NKodeHandler) GenerateSignupInterfaceHandler(w http.ResponseWriter, r *
return
}
var signupPost model.GenerateSignupInterfacePost
var signupPost m.GenerateSignupInterfacePost
err := decodeJson(w, r, &signupPost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
sessionId, userInterface, err := h.Api.GenerateSignupInterface(signupPost.CustomerId)
resp, err := h.Api.GenerateSignupInterface(signupPost.CustomerId)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
respBody := model.GenerateSignupInterfaceResp{
SessionId: *sessionId,
UserInterface: userInterface,
}
respBytes, err := json.Marshal(respBody)
respBytes, err := json.Marshal(resp)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
_, err = w.Write(respBytes)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -118,31 +112,31 @@ func (h *NKodeHandler) SetNKodeHandler(w http.ResponseWriter, r *http.Request) {
methodNotAllowed(w)
return
}
var setNKodePost model.SetNKodePost
var setNKodePost m.SetNKodePost
err := decodeJson(w, r, &setNKodePost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
confirmInterface, err := h.Api.SetNKode(setNKodePost.Username, setNKodePost.CustomerId, setNKodePost.KeySelection, setNKodePost.SessionId)
confirmInterface, err := h.Api.SetNKode(setNKodePost.Username, setNKodePost.CustomerId, setNKodePost.SessionId, setNKodePost.KeySelection)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
respBody := model.SetNKodeResp{UserInterface: confirmInterface}
respBody := m.SetNKodeResp{UserInterface: confirmInterface}
respBytes, err := json.Marshal(respBody)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
_, err = w.Write(respBytes)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -156,16 +150,16 @@ func (h *NKodeHandler) ConfirmNKodeHandler(w http.ResponseWriter, r *http.Reques
return
}
var confirmNKodePost model.ConfirmNKodePost
var confirmNKodePost m.ConfirmNKodePost
err := decodeJson(w, r, &confirmNKodePost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
err = h.Api.ConfirmNKode(confirmNKodePost.CustomerId, confirmNKodePost.KeySelection, confirmNKodePost.SessionId)
err = h.Api.ConfirmNKode(confirmNKodePost.CustomerId, confirmNKodePost.SessionId, confirmNKodePost.KeySelection)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -179,30 +173,30 @@ func (h *NKodeHandler) GetLoginInterfaceHandler(w http.ResponseWriter, r *http.R
methodNotAllowed(w)
return
}
var loginInterfacePost model.GetLoginInterfacePost
var loginInterfacePost m.GetLoginInterfacePost
err := decodeJson(w, r, &loginInterfacePost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
loginInterface, err := h.Api.GetLoginInterface(loginInterfacePost.Username, loginInterfacePost.CustomerId)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
respBody := model.GetLoginInterfaceResp{UserInterface: loginInterface}
respBody := m.GetLoginInterfaceResp{UserInterface: loginInterface}
respBytes, err := json.Marshal(respBody)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
_, err = w.Write(respBytes)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -216,16 +210,16 @@ func (h *NKodeHandler) LoginHandler(w http.ResponseWriter, r *http.Request) {
methodNotAllowed(w)
return
}
var loginPost model.LoginPost
var loginPost m.LoginPost
err := decodeJson(w, r, &loginPost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
err = h.Api.Login(loginPost.CustomerId, loginPost.Username, loginPost.KeySelection)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -238,18 +232,18 @@ func (h *NKodeHandler) RenewAttributesHandler(w http.ResponseWriter, r *http.Req
methodNotAllowed(w)
return
}
var renewAttributesPost model.RenewAttributesPost
var renewAttributesPost m.RenewAttributesPost
err := decodeJson(w, r, &renewAttributesPost)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
err = h.Api.RenewAttributes(renewAttributesPost.CustomerId)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
log.Fatal(err)
return
}
@@ -260,14 +254,14 @@ func (h *NKodeHandler) RenewAttributesHandler(w http.ResponseWriter, r *http.Req
func decodeJson(w http.ResponseWriter, r *http.Request, post any) error {
err := json.NewDecoder(r.Body).Decode(&post)
if err != nil {
internalServerErrorHandler(w, r)
internalServerErrorHandler(w)
return err
}
return nil
}
func internalServerErrorHandler(w http.ResponseWriter, r *http.Request) {
func internalServerErrorHandler(w http.ResponseWriter) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("500 Internal Server Error"))
}

View File

@@ -1,4 +1,4 @@
package model
package m
type KeypadSize struct {
AttrsPerKey int `json:"attrs_per_key"`

View File

@@ -1,4 +1,4 @@
package model
package m
type NKodePolicy struct {
MaxNkodeLen int `json:"max_nkode_len"`

View File

@@ -1,6 +1,8 @@
package model
package m
import "github.com/google/uuid"
import (
"github.com/google/uuid"
)
type SetNKodeResp struct {
UserInterface []int `json:"user_interface"`
@@ -12,52 +14,62 @@ type NewCustomerPost struct {
}
type GenerateSignupInterfacePost struct {
CustomerId uuid.UUID `json:"customer_id"`
CustomerId CustomerId `json:"customer_id"`
}
type SetNKodePost struct {
Username string `json:"username"`
CustomerId uuid.UUID `json:"customer_id"`
KeySelection []int `json:"key_selection"`
SessionId uuid.UUID `json:"session_id"`
Username Username `json:"username"`
CustomerId CustomerId `json:"customer_id"`
KeySelection KeySelection `json:"key_selection"`
SessionId SessionId `json:"session_id"`
}
type ConfirmNKodePost struct {
CustomerId uuid.UUID `json:"customer_id"`
KeySelection []int `json:"key_selection"`
SessionId uuid.UUID `json:"session_id"`
CustomerId CustomerId `json:"customer_id"`
KeySelection KeySelection `json:"key_selection"`
SessionId SessionId `json:"session_id"`
}
type GetLoginInterfacePost struct {
Username string `json:"username"`
CustomerId uuid.UUID `json:"customer_id"`
Username Username `json:"username"`
CustomerId CustomerId `json:"customer_id"`
}
type LoginPost struct {
CustomerId uuid.UUID `json:"customer_id"`
Username string `json:"username"`
KeySelection []int `json:"key_selection"`
CustomerId CustomerId `json:"customer_id"`
Username Username `json:"username"`
KeySelection KeySelection `json:"key_selection"`
}
type RenewAttributesPost struct {
CustomerId uuid.UUID `json:"customer_id"`
CustomerId CustomerId `json:"customer_id"`
}
type CreateNewCustomerResp struct {
CustomerId uuid.UUID `json:"customer_id"`
CustomerId CustomerId `json:"customer_id"`
}
type GenerateSignupInterfaceResp struct {
SessionId uuid.UUID `json:"session_id"`
UserInterface []int `json:"user_interface"`
SessionId SessionId `json:"session_id"`
UserInterface IdxInterface `json:"user_interface"`
}
type GetLoginInterfaceResp struct {
UserInterface []int `json:"user_interface"`
UserInterface IdxInterface `json:"user_interface"`
}
type KeySelection []int
type CustomerId uuid.UUID
type SessionId uuid.UUID
type Username string
type UserInterface []int
type IdxInterface []int
type NKodeAPIInterface interface {
CreateNewCustomer(KeypadSize, NKodePolicy) (*CustomerId, error)
GenerateSignupInterface(CustomerId) (*GenerateSignupInterfaceResp, error)
SetNKode(Username, CustomerId, SessionId, KeySelection) (IdxInterface, error)
ConfirmNKode(CustomerId, SessionId, KeySelection) error
GetLoginInterface(username Username, customerId CustomerId) (IdxInterface, error)
Login(customerId CustomerId, username Username, keySelection KeySelection) error
RenewAttributes(customerId CustomerId) error
}

View File

@@ -4,20 +4,20 @@ import (
"errors"
"fmt"
"github.com/google/uuid"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/hashset"
py "go-nkode/py-builtin"
"go-nkode/util"
)
type Customer struct {
CustomerId uuid.UUID
NKodePolicy model.NKodePolicy
CustomerId m.CustomerId
NKodePolicy m.NKodePolicy
Attributes CustomerAttributes
Users map[string]User
Users map[m.Username]User
}
func NewCustomer(keypadSize model.KeypadSize, nkodePolicy model.NKodePolicy) (*Customer, error) {
func NewCustomer(keypadSize m.KeypadSize, nkodePolicy m.NKodePolicy) (*Customer, error) {
if keypadSize.TotalAttrs() < nkodePolicy.DistinctAttributes {
return nil, errors.New(fmt.Sprintf("incompadible nkode policy and keypad size TotalAttrs: %d < DistinctAttributes: %d", keypadSize.TotalAttrs(), nkodePolicy.DistinctAttributes))
}
@@ -30,19 +30,19 @@ func NewCustomer(keypadSize model.KeypadSize, nkodePolicy model.NKodePolicy) (*C
return nil, err
}
customer := Customer{
CustomerId: uuid.New(),
CustomerId: m.CustomerId(uuid.New()),
NKodePolicy: nkodePolicy,
Attributes: *customerAttrs,
Users: make(map[string]User),
Users: make(map[m.Username]User),
}
return &customer, nil
}
func (c *Customer) AddNewUser(username string, passcodeIdx []int, userInterface UserInterface) error {
func (c *Customer) AddNewUser(username m.Username, passcodeIdx []int, userInterface UserInterface) error {
_, exists := c.Users[username]
if exists {
return errors.New(fmt.Sprintf("User %s already exists for customer %s exists", username, c.CustomerId.String()))
return errors.New(fmt.Sprintf("User %s already exists for customer %+v exists", username, c.CustomerId))
}
newKeys, err := NewUserCipherKeys(c.Attributes.KeypadSize, c.Attributes.SetVals, c.NKodePolicy.MaxNkodeLen)
if err != nil {
@@ -62,10 +62,10 @@ func (c *Customer) AddNewUser(username string, passcodeIdx []int, userInterface
return nil
}
func (c *Customer) ValidKeyEntry(username string, selectedKeys []int) ([]int, error) {
func (c *Customer) ValidKeyEntry(username m.Username, selectedKeys []int) ([]int, error) {
user, exists := c.Users[username]
if !exists {
return nil, errors.New(fmt.Sprintf("user %s does not exist for customer %s", username, c.CustomerId.String()))
return nil, errors.New(fmt.Sprintf("user %s does not exist for customer %+v", username, c.CustomerId))
}
validKeys := py.All[int](selectedKeys, func(idx int) bool {
@@ -152,10 +152,10 @@ func (c *Customer) IsValidNKode(passcodeAttrIdx []int) error {
return nil
}
func (c *Customer) GetLoginInterface(username string) ([]int, error) {
func (c *Customer) GetLoginInterface(username m.Username) ([]int, error) {
user, exists := c.Users[username]
if !exists {
return nil, errors.New(fmt.Sprintf("can't get login interface for non-existant user %s in customer %s", username, c.CustomerId.String()))
return nil, errors.New(fmt.Sprintf("can't get login interface for non-existant user %s in customer %s", username, c.CustomerId))
}
err := user.Interface.PartialInterfaceShuffle()

View File

@@ -11,10 +11,10 @@ import (
type CustomerAttributes struct {
AttrVals []uint64
SetVals []uint64
KeypadSize model.KeypadSize
KeypadSize m.KeypadSize
}
func NewCustomerAttributes(keypadSize model.KeypadSize) (*CustomerAttributes, error) {
func NewCustomerAttributes(keypadSize m.KeypadSize) (*CustomerAttributes, error) {
if keypadSize.IsDispersable() {
return nil, errors.New("number of keys must be less than the number of attributes per key to be dispersion resistant")
}

View File

@@ -2,24 +2,30 @@ package nkode
import (
"github.com/stretchr/testify/assert"
model2 "go-nkode/core/model"
m "go-nkode/core/model"
"testing"
)
func TestNewCustomerAttributes(t *testing.T) {
keypad := model2.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
func TestCustomer(t *testing.T) {
testNewCustomerAttributes(t)
testCustomerValidKeyEntry(t)
testCustomerIsValidNKode(t)
}
func testNewCustomerAttributes(t *testing.T) {
keypad := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
_, nil := NewCustomerAttributes(keypad)
assert.NoError(t, nil)
}
func TestCustomer_ValidKeyEntry(t *testing.T) {
keypadSize := model2.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := model2.NewDefaultNKodePolicy()
func testCustomerValidKeyEntry(t *testing.T) {
keypadSize := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := m.NewDefaultNKodePolicy()
customer, err := NewCustomer(keypadSize, nkodePolicy)
assert.NoError(t, err)
newUserInterface, err := NewUserInterface(customer.Attributes.KeypadSize)
assert.NoError(t, err)
username := "testing123"
username := m.Username("testing123")
passcodeIdx := []int{0, 1, 2, 3}
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface)
assert.NoError(t, err)
@@ -35,14 +41,14 @@ func TestCustomer_ValidKeyEntry(t *testing.T) {
}
}
func TestCustomer_IsValidNKode(t *testing.T) {
keypadSize := model2.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := model2.NewDefaultNKodePolicy()
func testCustomerIsValidNKode(t *testing.T) {
keypadSize := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := m.NewDefaultNKodePolicy()
customer, err := NewCustomer(keypadSize, nkodePolicy)
assert.NoError(t, err)
newUserInterface, err := NewUserInterface(customer.Attributes.KeypadSize)
assert.NoError(t, err)
username := "testing123"
username := m.Username("testing123")
passcodeIdx := []int{0, 1, 2, 3}
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface)
assert.NoError(t, err)

View File

@@ -3,23 +3,22 @@ package nkode
import (
"errors"
"fmt"
"github.com/google/uuid"
"go-nkode/core/model"
m "go-nkode/core/model"
)
type NKodeAPI struct {
Customers map[uuid.UUID]Customer
SignupSessions map[uuid.UUID]UserSignSession
type NKodeInMemory struct {
Customers map[m.CustomerId]Customer
SignupSessions map[m.SessionId]UserSignSession
}
func NewNKodeAPI() NKodeAPI {
return NKodeAPI{
Customers: make(map[uuid.UUID]Customer),
SignupSessions: make(map[uuid.UUID]UserSignSession),
func NewNKodeInMemory() NKodeInMemory {
return NKodeInMemory{
Customers: make(map[m.CustomerId]Customer),
SignupSessions: make(map[m.SessionId]UserSignSession),
}
}
func (n *NKodeAPI) CreateNewCustomer(keypadSize model.KeypadSize, nkodePolicy model.NKodePolicy) (*uuid.UUID, error) {
func (n *NKodeInMemory) CreateNewCustomer(keypadSize m.KeypadSize, nkodePolicy m.NKodePolicy) (*m.CustomerId, error) {
newCustomer, err := NewCustomer(keypadSize, nkodePolicy)
if err != nil {
return nil, err
@@ -28,29 +27,33 @@ func (n *NKodeAPI) CreateNewCustomer(keypadSize model.KeypadSize, nkodePolicy mo
return &newCustomer.CustomerId, nil
}
func (n *NKodeAPI) GenerateSignupInterface(customerId uuid.UUID) (*uuid.UUID, []int, error) {
func (n *NKodeInMemory) GenerateSignupInterface(customerId m.CustomerId) (*m.GenerateSignupInterfaceResp, error) {
customer, exists := n.Customers[customerId]
if !exists {
return nil, nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId.String()))
return nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId))
}
signupSession, err := NewSignupSession(customer.Attributes.KeypadSize, customer.CustomerId)
if err != nil {
return nil, nil, err
return nil, err
}
n.SignupSessions[signupSession.SessionId] = *signupSession
return &signupSession.SessionId, signupSession.SetInterface, nil
resp := m.GenerateSignupInterfaceResp{
UserInterface: signupSession.SetIdxInterface,
SessionId: signupSession.SessionId,
}
return &resp, nil
}
func (n *NKodeAPI) SetNKode(username string, customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) ([]int, error) {
func (n *NKodeInMemory) SetNKode(username m.Username, customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) (m.IdxInterface, error) {
_, exists := n.Customers[customerId]
if !exists {
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId.String()))
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId))
}
session, exists := n.SignupSessions[sessionId]
if !exists {
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
}
confirmInterface, err := session.SetUserNKode(username, keySelection)
if err != nil {
@@ -60,10 +63,10 @@ func (n *NKodeAPI) SetNKode(username string, customerId uuid.UUID, keySelection
return confirmInterface, nil
}
func (n *NKodeAPI) ConfirmNKode(customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) error {
func (n *NKodeInMemory) ConfirmNKode(customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) error {
session, exists := n.SignupSessions[sessionId]
if !exists {
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
}
customer, exists := n.Customers[customerId]
passcode, err := session.DeducePasscode(keySelection)
@@ -74,7 +77,7 @@ func (n *NKodeAPI) ConfirmNKode(customerId uuid.UUID, keySelection []int, sessio
if err != nil {
return err
}
err = customer.AddNewUser(session.Username, passcode, session.LoginInterface)
err = customer.AddNewUser(session.Username, passcode, session.LoginUserInterface)
if err != nil {
return err
}
@@ -83,7 +86,7 @@ func (n *NKodeAPI) ConfirmNKode(customerId uuid.UUID, keySelection []int, sessio
return nil
}
func (n *NKodeAPI) GetLoginInterface(username string, customerId uuid.UUID) ([]int, error) {
func (n *NKodeInMemory) GetLoginInterface(username m.Username, customerId m.CustomerId) (m.IdxInterface, error) {
err := n.customerUserExists(username, customerId)
if err != nil {
return nil, err
@@ -97,10 +100,10 @@ func (n *NKodeAPI) GetLoginInterface(username string, customerId uuid.UUID) ([]i
return user.Interface.IdxInterface, nil
}
func (n *NKodeAPI) Login(customerId uuid.UUID, username string, keySelection []int) error {
func (n *NKodeInMemory) Login(customerId m.CustomerId, username m.Username, keySelection m.KeySelection) error {
customer, exists := n.Customers[customerId]
if !exists {
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
}
user, exists := customer.Users[username]
if !exists {
@@ -119,10 +122,10 @@ func (n *NKodeAPI) Login(customerId uuid.UUID, username string, keySelection []i
return nil
}
func (n *NKodeAPI) customerUserExists(username string, customerId uuid.UUID) error {
func (n *NKodeInMemory) customerUserExists(username m.Username, customerId m.CustomerId) error {
customer, exists := n.Customers[customerId]
if !exists {
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
}
_, exists = customer.Users[username]
if !exists {
@@ -131,10 +134,10 @@ func (n *NKodeAPI) customerUserExists(username string, customerId uuid.UUID) err
return nil
}
func (n *NKodeAPI) RenewAttributes(customerId uuid.UUID) error {
func (n *NKodeInMemory) RenewAttributes(customerId m.CustomerId) error {
customer, exists := n.Customers[customerId]
if !exists {
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
}
return customer.RenewKeys()
}

View File

@@ -2,32 +2,34 @@ package nkode
import (
"github.com/stretchr/testify/assert"
"go-nkode/core/model"
m "go-nkode/core/model"
"testing"
)
func TestNKodeAPI(t *testing.T) {
for idx := 0; idx < 10; idx++ {
username := "test_username"
username := m.Username("test_username")
passcodeLen := 4
nkodePolicy := model.NewDefaultNKodePolicy()
keypadSize := model.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
nkodeApi := NewNKodeAPI()
nkodePolicy := m.NewDefaultNKodePolicy()
keypadSize := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
nkodeApi := NewNKodeInMemory()
customerId, err := nkodeApi.CreateNewCustomer(keypadSize, nkodePolicy)
assert.NoError(t, err)
sessionId, setInterface, err := nkodeApi.GenerateSignupInterface(*customerId)
signupResponse, err := nkodeApi.GenerateSignupInterface(*customerId)
assert.NoError(t, err)
keypadSize = model.KeypadSize{AttrsPerKey: 3, NumbOfKeys: 3}
setInterface := signupResponse.UserInterface
sessionId := signupResponse.SessionId
keypadSize = m.KeypadSize{AttrsPerKey: 3, NumbOfKeys: 3}
userPasscode := setInterface[:passcodeLen]
setKeySelect, err := SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize)
assert.NoError(t, err)
confirmInterface, err := nkodeApi.SetNKode(username, *customerId, setKeySelect, *sessionId)
confirmInterface, err := nkodeApi.SetNKode(username, *customerId, sessionId, setKeySelect)
assert.NoError(t, err)
confirmKeySelect, err := SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize)
err = nkodeApi.ConfirmNKode(*customerId, confirmKeySelect, *sessionId)
err = nkodeApi.ConfirmNKode(*customerId, sessionId, confirmKeySelect)
assert.NoError(t, err)
keypadSize = model.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
keypadSize = m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
loginInterface, err := nkodeApi.GetLoginInterface(username, *customerId)
assert.NoError(t, err)
loginKeySelection, err := SelectKeyByAttrIdx(loginInterface, userPasscode, keypadSize)

View File

@@ -0,0 +1 @@
package nkode

View File

@@ -3,11 +3,11 @@ package nkode
import (
"errors"
"fmt"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/util"
)
func SelectKeyByAttrIdx(interfaceUser []int, passcodeIdxs []int, keypadSize model.KeypadSize) ([]int, error) {
func SelectKeyByAttrIdx(interfaceUser []int, passcodeIdxs []int, keypadSize m.KeypadSize) ([]int, error) {
selectedKeys := make([]int, len(passcodeIdxs))
for idx := range passcodeIdxs {
attrIdx := util.IndexOf[int](interfaceUser, passcodeIdxs[idx])

View File

@@ -6,7 +6,7 @@ import (
)
type User struct {
Username string
Username m.Username
EncipheredPasscode m.EncipheredNKode
UserKeys UserCipherKeys
Interface UserInterface

View File

@@ -4,7 +4,7 @@ import (
"crypto/sha256"
"errors"
"fmt"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/util"
"golang.org/x/crypto/bcrypt"
)
@@ -18,7 +18,7 @@ type UserCipherKeys struct {
MaxNKodeLen int
}
func NewUserCipherKeys(keypadSize model.KeypadSize, setVals []uint64, maxNKodeLen int) (*UserCipherKeys, error) {
func NewUserCipherKeys(keypadSize m.KeypadSize, setVals []uint64, maxNKodeLen int) (*UserCipherKeys, error) {
if len(setVals) != keypadSize.AttrsPerKey {
return nil, errors.New(fmt.Sprintf("setVals len != attrsPerKey, %d, %d", len(setVals), keypadSize.AttrsPerKey))
}
@@ -165,7 +165,7 @@ func (u *UserCipherKeys) DecipherMask(mask string, setVals []uint64, passcodeLen
return passcodeSet, nil
}
func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (*model.EncipheredNKode, error) {
func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (*m.EncipheredNKode, error) {
code, err := u.EncipherSaltHashCode(passcodeAttrIdx, customerAttrs)
if err != nil {
return nil, err
@@ -180,7 +180,7 @@ func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs Cust
}
}
mask, err := u.EncipherMask(passcodeSet, customerAttrs)
encipheredCode := model.EncipheredNKode{
encipheredCode := m.EncipheredNKode{
Code: code,
Mask: mask,
}

View File

@@ -3,17 +3,17 @@ package nkode
import (
"errors"
"fmt"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/hashset"
"go-nkode/util"
)
type UserInterface struct {
IdxInterface []int
KeypadSize model.KeypadSize
IdxInterface m.IdxInterface
KeypadSize m.KeypadSize
}
func NewUserInterface(keypadSize model.KeypadSize) (*UserInterface, error) {
func NewUserInterface(keypadSize m.KeypadSize) (*UserInterface, error) {
idxInterface := util.IdentityArray(keypadSize.TotalAttrs())
userInterface := UserInterface{
IdxInterface: idxInterface,

View File

@@ -4,61 +4,61 @@ import (
"errors"
"fmt"
"github.com/google/uuid"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/hashset"
py_builtin "go-nkode/py-builtin"
py "go-nkode/py-builtin"
"go-nkode/util"
)
type UserSignSession struct {
SessionId uuid.UUID
CustomerId uuid.UUID
LoginInterface UserInterface
KeypadSize model.KeypadSize
SetInterface []int
ConfirmInterface []int
SetKeyEntry []int
Username string
SessionId m.SessionId
CustomerId m.CustomerId
LoginUserInterface UserInterface
Keypad m.KeypadSize
SetIdxInterface m.IdxInterface
ConfirmIdxInterface m.IdxInterface
SetKeySelection m.KeySelection
Username m.Username
}
func NewSignupSession(keypadSize model.KeypadSize, customerId uuid.UUID) (*UserSignSession, error) {
func NewSignupSession(keypadSize m.KeypadSize, customerId m.CustomerId) (*UserSignSession, error) {
loginInterface, err := NewUserInterface(keypadSize)
if err != nil {
return nil, err
}
signupInter, err := signupInterface(*loginInterface)
session := UserSignSession{
SessionId: uuid.New(),
SessionId: m.SessionId(uuid.New()),
CustomerId: customerId,
LoginInterface: *loginInterface,
SetInterface: signupInter.IdxInterface,
ConfirmInterface: nil,
SetKeyEntry: nil,
LoginUserInterface: *loginInterface,
SetIdxInterface: signupInter.IdxInterface,
ConfirmIdxInterface: nil,
SetKeySelection: nil,
Username: "",
KeypadSize: signupInter.KeypadSize,
Keypad: signupInter.KeypadSize,
}
return &session, nil
}
func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
validEntry := py_builtin.All[int](confirmKeyEntry, func(i int) bool {
return 0 <= i && i < s.LoginInterface.KeypadSize.NumbOfKeys
func (s *UserSignSession) DeducePasscode(confirmKeyEntry m.KeySelection) ([]int, error) {
validEntry := py.All[int](confirmKeyEntry, func(i int) bool {
return 0 <= i && i < s.LoginUserInterface.KeypadSize.NumbOfKeys
})
if !validEntry {
return nil, errors.New(fmt.Sprintf("Invalid Key entry. One or more key index: %#v, not in range 0-%d", confirmKeyEntry, s.LoginInterface.KeypadSize.NumbOfKeys))
return nil, errors.New(fmt.Sprintf("Invalid Key entry. One or more key index: %#v, not in range 0-%d", confirmKeyEntry, s.LoginUserInterface.KeypadSize.NumbOfKeys))
}
if s.SetInterface == nil {
if s.SetIdxInterface == nil {
return nil, errors.New("signup session set interface is nil")
}
if s.ConfirmInterface == nil {
if s.ConfirmIdxInterface == nil {
return nil, errors.New("signup session confirm interface is nil")
}
if s.SetKeyEntry == nil {
if s.SetKeySelection == nil {
return nil, errors.New("signup session set key entry is nil")
}
@@ -66,16 +66,16 @@ func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
return nil, errors.New("signup session username is nil")
}
if len(confirmKeyEntry) != len(s.SetKeyEntry) {
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeyEntry)))
if len(confirmKeyEntry) != len(s.SetKeySelection) {
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeySelection)))
}
passcodeLen := len(confirmKeyEntry)
setKeyVals, err := s.getSelectedKeyVals(s.SetKeyEntry, s.SetInterface)
setKeyVals, err := s.getSelectedKeyVals(s.SetKeySelection, s.SetIdxInterface)
if err != nil {
return nil, err
}
confirmKeyVals, err := s.getSelectedKeyVals(confirmKeyEntry, s.ConfirmInterface)
confirmKeyVals, err := s.getSelectedKeyVals(confirmKeyEntry, s.ConfirmIdxInterface)
passcode := make([]int, passcodeLen)
for idx := 0; idx < passcodeLen; idx++ {
@@ -94,28 +94,28 @@ func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
return passcode, nil
}
func (s *UserSignSession) SetUserNKode(username string, keySelection []int) ([]int, error) {
validKeySelection := py_builtin.All[int](keySelection, func(i int) bool {
return 0 <= i && i < s.KeypadSize.NumbOfKeys
func (s *UserSignSession) SetUserNKode(username m.Username, keySelection m.KeySelection) (m.IdxInterface, error) {
validKeySelection := py.All[int](keySelection, func(i int) bool {
return 0 <= i && i < s.Keypad.NumbOfKeys
})
if !validKeySelection {
return nil, errors.New(fmt.Sprintf("one or key selection is out of range 0-%d", s.KeypadSize.NumbOfKeys-1))
return nil, errors.New(fmt.Sprintf("one or key selection is out of range 0-%d", s.Keypad.NumbOfKeys-1))
}
s.SetKeyEntry = keySelection
s.SetKeySelection = keySelection
s.Username = username
setInterface := UserInterface{IdxInterface: s.SetInterface, KeypadSize: s.KeypadSize}
setInterface := UserInterface{IdxInterface: s.SetIdxInterface, KeypadSize: s.Keypad}
err := setInterface.DisperseInterface()
if err != nil {
return nil, err
}
s.ConfirmInterface = setInterface.IdxInterface
return s.ConfirmInterface, nil
s.ConfirmIdxInterface = setInterface.IdxInterface
return s.ConfirmIdxInterface, nil
}
func (s *UserSignSession) getSelectedKeyVals(keySelections []int, userInterface []int) ([][]int, error) {
keypadInterface, err := util.ListToMatrix(userInterface, s.KeypadSize.AttrsPerKey)
func (s *UserSignSession) getSelectedKeyVals(keySelections m.KeySelection, userInterface []int) ([][]int, error) {
keypadInterface, err := util.ListToMatrix(userInterface, s.Keypad.AttrsPerKey)
if err != nil {
return nil, err
}
@@ -155,7 +155,7 @@ func signupInterface(baseUserInterface UserInterface) (*UserInterface, error) {
}
signupUserInterface := UserInterface{
IdxInterface: util.MatrixToList(attrSetView),
KeypadSize: model.KeypadSize{
KeypadSize: m.KeypadSize{
AttrsPerKey: numbOfKeys,
NumbOfKeys: numbOfKeys,
},

View File

@@ -2,13 +2,13 @@ package nkode
import (
"github.com/stretchr/testify/assert"
"go-nkode/core/model"
py_builtin "go-nkode/py-builtin"
m "go-nkode/core/model"
py "go-nkode/py-builtin"
"testing"
)
func TestUserCipherKeys_EncipherSaltHashCode(t *testing.T) {
keypadSize := model.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
keypadSize := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
maxNKodeLen := 10
customerAttrs, err := NewCustomerAttributes(keypadSize)
assert.NoError(t, err)
@@ -22,7 +22,7 @@ func TestUserCipherKeys_EncipherSaltHashCode(t *testing.T) {
}
func TestUserCipherKeys_EncipherDecipherMask(t *testing.T) {
keypadSize := model.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
keypadSize := m.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
maxNKodeLen := 10
customerAttrs, err := NewCustomerAttributes(keypadSize)
@@ -48,7 +48,7 @@ func TestUserCipherKeys_EncipherDecipherMask(t *testing.T) {
}
func TestUserInterface_RandomShuffle(t *testing.T) {
keypadSize := model.KeypadSize{
keypadSize := m.KeypadSize{
AttrsPerKey: 10,
NumbOfKeys: 5,
}
@@ -73,7 +73,7 @@ func TestUserInterface_RandomShuffle(t *testing.T) {
func TestUserInterface_DisperseInterface(t *testing.T) {
for idx := 0; idx < 10000; idx++ {
keypadSize := model.KeypadSize{AttrsPerKey: 7, NumbOfKeys: 10}
keypadSize := m.KeypadSize{AttrsPerKey: 7, NumbOfKeys: 10}
userInterface, err := NewUserInterface(keypadSize)
assert.NoError(t, err)
@@ -92,7 +92,7 @@ func TestUserInterface_DisperseInterface(t *testing.T) {
}
func TestUserInterface_PartialInterfaceShuffle(t *testing.T) {
keypadSize := model.KeypadSize{AttrsPerKey: 7, NumbOfKeys: 10}
keypadSize := m.KeypadSize{AttrsPerKey: 7, NumbOfKeys: 10}
userInterface, err := NewUserInterface(keypadSize)
assert.NoError(t, err)
preShuffle := userInterface.IdxInterface
@@ -105,12 +105,12 @@ func TestUserInterface_PartialInterfaceShuffle(t *testing.T) {
shuffleCompare[idx] = val == postShuffle[idx]
}
allTrue := py_builtin.All[bool](shuffleCompare, func(n bool) bool {
allTrue := py.All[bool](shuffleCompare, func(n bool) bool {
return n == true
})
assert.False(t, allTrue)
allFalse := py_builtin.All[bool](shuffleCompare, func(n bool) bool {
allFalse := py.All[bool](shuffleCompare, func(n bool) bool {
return n == false
})

View File

@@ -9,8 +9,8 @@ import (
)
func main() {
nkodeApi := nkode.NewNKodeAPI()
handler := api.NKodeHandler{Api: nkodeApi}
nkodeApi := nkode.NewNKodeInMemory()
handler := api.NKodeHandler{Api: &nkodeApi}
mux := http.NewServeMux()
mux.Handle(api.CreateNewCustomer, &handler)
mux.Handle(api.GenerateSignupInterface, &handler)
@@ -19,6 +19,6 @@ func main() {
mux.Handle(api.GetLoginInterface, &handler)
mux.Handle(api.Login, &handler)
mux.Handle(api.RenewAttributes, &handler)
fmt.Println("Running on localhost:8080")
fmt.Println("Running on localhost:8080...")
log.Fatal(http.ListenAndServe("localhost:8080", mux))
}

View File

@@ -5,7 +5,7 @@ import (
"encoding/json"
"github.com/stretchr/testify/assert"
"go-nkode/core/api"
"go-nkode/core/model"
m "go-nkode/core/model"
"go-nkode/core/nkode"
"io"
"net/http"
@@ -14,55 +14,55 @@ import (
func TestApi(t *testing.T) {
base := "http://localhost:8080"
newCustomerBody := model.NewCustomerPost{
KeypadSize: model.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 10},
NKodePolicy: model.NewDefaultNKodePolicy(),
newCustomerBody := m.NewCustomerPost{
KeypadSize: m.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 10},
NKodePolicy: m.NewDefaultNKodePolicy(),
}
var customerResp model.CreateNewCustomerResp
var customerResp m.CreateNewCustomerResp
testApiCall(t, base+api.CreateNewCustomer, newCustomerBody, &customerResp)
signupInterfaceBody := model.GetLoginInterfacePost{CustomerId: customerResp.CustomerId}
var signupInterfaceResp model.GenerateSignupInterfaceResp
signupInterfaceBody := m.GetLoginInterfacePost{CustomerId: customerResp.CustomerId}
var signupInterfaceResp m.GenerateSignupInterfaceResp
testApiCall(t, base+api.GenerateSignupInterface, signupInterfaceBody, &signupInterfaceResp)
username := "test_username"
username := m.Username("test_username")
passcodeLen := 4
setInterface := signupInterfaceResp.UserInterface
userPasscode := setInterface[:passcodeLen]
keypadSize := model.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 5}
keypadSize := m.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 5}
setKeySelection, err := nkode.SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize)
assert.NoError(t, err)
setNKodeBody := model.SetNKodePost{
setNKodeBody := m.SetNKodePost{
CustomerId: customerResp.CustomerId,
Username: username,
SessionId: signupInterfaceResp.SessionId,
KeySelection: setKeySelection,
}
var setNKodeResp model.SetNKodeResp
var setNKodeResp m.SetNKodeResp
testApiCall(t, base+api.SetNKode, setNKodeBody, &setNKodeResp)
confirmInterface := setNKodeResp.UserInterface
confirmKeySelection, err := nkode.SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize)
assert.NoError(t, err)
confirmNKodeBody := model.ConfirmNKodePost{
confirmNKodeBody := m.ConfirmNKodePost{
CustomerId: customerResp.CustomerId,
KeySelection: confirmKeySelection,
SessionId: signupInterfaceResp.SessionId,
}
testApiCall(t, base+api.ConfirmNKode, confirmNKodeBody, nil)
loginInterfaceBody := model.GetLoginInterfacePost{
loginInterfaceBody := m.GetLoginInterfacePost{
CustomerId: customerResp.CustomerId,
Username: username,
}
var loginInterfaceResp model.GetLoginInterfaceResp
var loginInterfaceResp m.GetLoginInterfaceResp
testApiCall(t, base+api.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp)
keypadSize = model.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 10}
keypadSize = m.KeypadSize{NumbOfKeys: 5, AttrsPerKey: 10}
loginKeySelection, err := nkode.SelectKeyByAttrIdx(loginInterfaceResp.UserInterface, userPasscode, keypadSize)
assert.NoError(t, err)
loginBody := model.LoginPost{
loginBody := m.LoginPost{
CustomerId: customerResp.CustomerId,
Username: username,
KeySelection: loginKeySelection,
@@ -70,12 +70,12 @@ func TestApi(t *testing.T) {
testApiCall(t, base+api.Login, loginBody, nil)
renewBody := model.RenewAttributesPost{CustomerId: customerResp.CustomerId}
renewBody := m.RenewAttributesPost{CustomerId: customerResp.CustomerId}
testApiCall(t, base+api.RenewAttributes, renewBody, nil)
loginKeySelection, err = nkode.SelectKeyByAttrIdx(loginInterfaceResp.UserInterface, userPasscode, keypadSize)
assert.NoError(t, err)
loginBody = model.LoginPost{
loginBody = m.LoginPost{
CustomerId: customerResp.CustomerId,
Username: username,
KeySelection: loginKeySelection,