implement api
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"go-nkode/hashset"
|
||||||
m "go-nkode/models"
|
m "go-nkode/models"
|
||||||
py "go-nkode/py-builtin"
|
py "go-nkode/py-builtin"
|
||||||
|
"go-nkode/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Customer struct {
|
type Customer struct {
|
||||||
@@ -128,16 +130,25 @@ func (c *Customer) IsValidNKode(passcodeAttrIdx []int) error {
|
|||||||
if !validIdx {
|
if !validIdx {
|
||||||
return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", c.Attributes.KeypadSize.TotalAttrs()-1))
|
return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", c.Attributes.KeypadSize.TotalAttrs()-1))
|
||||||
}
|
}
|
||||||
passcodeSetVals := make([]uint64, nkodeLen)
|
passcodeSetVals := make(hashset.Set[uint64])
|
||||||
var err error
|
passcodeAttrVals := make(hashset.Set[uint64])
|
||||||
for idx := range passcodeSetVals {
|
for idx := 0; idx < nkodeLen; idx++ {
|
||||||
attrVal := c.Attributes.AttrVals[passcodeAttrIdx[idx]]
|
attrVal := c.Attributes.AttrVals[passcodeAttrIdx[idx]]
|
||||||
passcodeSetVals[idx], err = c.Attributes.GetAttrSetVal(attrVal)
|
setVal, err := c.Attributes.GetAttrSetVal(attrVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
passcodeSetVals.Add(setVal)
|
||||||
|
passcodeAttrVals.Add(attrVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if passcodeSetVals.Size() < c.NKodePolicy.DistinctSets {
|
||||||
|
return errors.New(fmt.Sprintf("passcode has two few distinct sets min %d, has %d", c.NKodePolicy.DistinctSets, passcodeSetVals.Size()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if passcodeAttrVals.Size() < c.NKodePolicy.DistinctAttributes {
|
||||||
|
return errors.New(fmt.Sprintf("passcode has two few distinct attributes min %d, has %d", c.NKodePolicy.DistinctAttributes, passcodeAttrVals.Size()))
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,3 +165,30 @@ func (c *Customer) GetLoginInterface(username string) ([]int, error) {
|
|||||||
c.Users[username] = user
|
c.Users[username] = user
|
||||||
return user.Interface.IdxInterface, nil
|
return user.Interface.IdxInterface, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Customer) RenewKeys() error {
|
||||||
|
oldAttrs := make([]uint64, c.Attributes.KeypadSize.TotalAttrs())
|
||||||
|
oldSets := make([]uint64, c.Attributes.KeypadSize.AttrsPerKey)
|
||||||
|
copy(oldAttrs, c.Attributes.AttrVals)
|
||||||
|
copy(oldSets, c.Attributes.SetVals)
|
||||||
|
|
||||||
|
err := c.Attributes.Renew()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
attrsXor, err := util.XorLists(oldAttrs, c.Attributes.AttrVals)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
setXor, err := util.XorLists(oldSets, c.Attributes.SetVals)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, user := range c.Users {
|
||||||
|
err = user.RenewKeys(setXor, attrsXor)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -1,27 +1,11 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"go-nkode/models"
|
"go-nkode/models"
|
||||||
"go-nkode/util"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SelectKeyByAttrIdx(interfaceUser []int, passcodeIdxs []int, keypadSize models.KeypadSize) ([]int, error) {
|
|
||||||
selectedKeys := make([]int, len(passcodeIdxs))
|
|
||||||
for idx := range passcodeIdxs {
|
|
||||||
attrIdx := util.IndexOf[int](interfaceUser, passcodeIdxs[idx])
|
|
||||||
keyNumb := attrIdx / keypadSize.AttrsPerKey
|
|
||||||
if keyNumb < 0 || keyNumb >= keypadSize.NumbOfKeys {
|
|
||||||
return nil, errors.New(fmt.Sprintf("index key number: %d out of range 0-%d", keyNumb, keypadSize.NumbOfKeys-1))
|
|
||||||
}
|
|
||||||
selectedKeys[idx] = keyNumb
|
|
||||||
}
|
|
||||||
return selectedKeys, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewCustomerAttributes(t *testing.T) {
|
func TestNewCustomerAttributes(t *testing.T) {
|
||||||
keypad := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
keypad := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
||||||
_, nil := NewCustomerAttributes(keypad)
|
_, nil := NewCustomerAttributes(keypad)
|
||||||
140
core/api/nkode_api.go
Normal file
140
core/api/nkode_api.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go-nkode/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NKodeAPI struct {
|
||||||
|
Customers map[uuid.UUID]Customer
|
||||||
|
SignupSessions map[uuid.UUID]UserSignSession
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNKodeAPI() NKodeAPI {
|
||||||
|
return NKodeAPI{
|
||||||
|
Customers: make(map[uuid.UUID]Customer),
|
||||||
|
SignupSessions: make(map[uuid.UUID]UserSignSession),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) CreateNewCustomer(keypadSize models.KeypadSize, nkodePolicy models.NKodePolicy) (*uuid.UUID, error) {
|
||||||
|
newCustomer, err := NewCustomer(keypadSize, nkodePolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.Customers[newCustomer.CustomerId] = *newCustomer
|
||||||
|
return &newCustomer.CustomerId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) GenerateSignupInterface(customerId uuid.UUID) (*uuid.UUID, []int, error) {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return nil, nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
signupSession, err := NewSignupSession(customer.Attributes.KeypadSize, customer.CustomerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
n.SignupSessions[signupSession.SessionId] = *signupSession
|
||||||
|
return &signupSession.SessionId, signupSession.SetInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) SetNKode(username string, customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) ([]int, error) {
|
||||||
|
_, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
session, exists := n.SignupSessions[sessionId]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
|
||||||
|
}
|
||||||
|
confirmInterface, err := session.SetUserNKode(username, keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.SignupSessions[sessionId] = session
|
||||||
|
return confirmInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) ConfirmNKode(customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) error {
|
||||||
|
session, exists := n.SignupSessions[sessionId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
|
||||||
|
}
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
passcode, err := session.DeducePasscode(keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = customer.IsValidNKode(passcode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = customer.AddNewUser(session.Username, passcode, session.LoginInterface)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
delete(n.SignupSessions, session.SessionId)
|
||||||
|
n.Customers[customerId] = customer
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) GetLoginInterface(username string, customerId uuid.UUID) ([]int, error) {
|
||||||
|
err := n.customerUserExists(username, customerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
user := n.Customers[customerId].Users[username]
|
||||||
|
err = user.Interface.PartialInterfaceShuffle()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.Customers[customerId].Users[username] = user
|
||||||
|
return user.Interface.IdxInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) Login(customerId uuid.UUID, username string, keySelection []int) error {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
|
||||||
|
}
|
||||||
|
user, exists := customer.Users[username]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("user dne %s", username))
|
||||||
|
}
|
||||||
|
passcode, err := customer.ValidKeyEntry(username, keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if user.Renew {
|
||||||
|
err = user.RefreshPasscode(passcode, customer.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) customerUserExists(username string, customerId uuid.UUID) error {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
|
||||||
|
}
|
||||||
|
_, exists = customer.Users[username]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("user dne %s", username))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) RenewAttributes(customerId uuid.UUID) error {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("customer %s does not exist", customerId.String()))
|
||||||
|
}
|
||||||
|
return customer.RenewKeys()
|
||||||
|
}
|
||||||
159
core/api/nkode_api_handler.go
Normal file
159
core/api/nkode_api_handler.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go-nkode/models"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CreateNewCustomer = "/create-new-customer"
|
||||||
|
GenerateSignupInterface = "/generate-signup-interface"
|
||||||
|
SetNKode = "/set-nkode"
|
||||||
|
ConfirmNKode = "/confirm-nkode"
|
||||||
|
GetLoginInterface = "/get-login-interface"
|
||||||
|
Login = "/login"
|
||||||
|
RenewAttributes = "/renew-attributes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NKodeHandler struct {
|
||||||
|
Api NKodeAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewCustomerPost struct {
|
||||||
|
KeypadSize models.KeypadSize `json:"keypad_size"`
|
||||||
|
NKodePolicy models.NKodePolicy `json:"nkode_policy"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenerateSignupInterfacePost struct {
|
||||||
|
CustomerId uuid.UUID `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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfirmNKodePost struct {
|
||||||
|
CustomerId uuid.UUID `json:"customer_id"`
|
||||||
|
KeySelection []int `json:"key_selection"`
|
||||||
|
SessionId uuid.UUID `json:"session_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetLoginInterfacePost struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
CustomerId uuid.UUID `json:"customer_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginPost struct {
|
||||||
|
CustomerId uuid.UUID `json:"customer_id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
KeySelection []int `json:"key_selection"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenewAttributesPost struct {
|
||||||
|
CustomerId uuid.UUID `json:"customer_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.SetNKodeHandler(w, r)
|
||||||
|
case ConfirmNKode:
|
||||||
|
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case GetLoginInterface:
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case Login:
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case RenewAttributes:
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
w.Write([]byte("404 not found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func internalServerErrorHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte("500 Internal Server Error"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func methodNotAllowed(w http.ResponseWriter) {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
w.Write([]byte("405 method not allowed"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *NKodeHandler) CreateNewCustomerHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var customerPost NewCustomerPost
|
||||||
|
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&customerPost); err != nil {
|
||||||
|
internalServerErrorHandler(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
customerId, err := h.Api.CreateNewCustomer(customerPost.KeypadSize, customerPost.NKodePolicy)
|
||||||
|
if err != nil {
|
||||||
|
internalServerErrorHandler(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"customer_id": customerId,
|
||||||
|
}
|
||||||
|
jsonBytes, err := json.Marshal(data)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write(jsonBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *NKodeHandler) GenerateSignupInterfaceHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var signupPost GenerateSignupInterfacePost
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&signupPost); err != nil {
|
||||||
|
internalServerErrorHandler(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("Customer Id: ", signupPost.CustomerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *NKodeHandler) SetNKodeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
methodNotAllowed(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
48
core/api/nkode_api_test.go
Normal file
48
core/api/nkode_api_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"go-nkode/models"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNKodeAPI(t *testing.T) {
|
||||||
|
for idx := 0; idx < 10; idx++ {
|
||||||
|
username := "test_username"
|
||||||
|
passcodeLen := 4
|
||||||
|
nkodePolicy := models.NewDefaultNKodePolicy()
|
||||||
|
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
|
||||||
|
nkodeApi := NewNKodeAPI()
|
||||||
|
customerId, err := nkodeApi.CreateNewCustomer(keypadSize, nkodePolicy)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
sessionId, setInterface, err := nkodeApi.GenerateSignupInterface(*customerId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
keypadSize = models.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)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
confirmKeySelect, err := SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize)
|
||||||
|
err = nkodeApi.ConfirmNKode(*customerId, confirmKeySelect, *sessionId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
keypadSize = models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 3}
|
||||||
|
loginInterface, err := nkodeApi.GetLoginInterface(username, *customerId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
loginKeySelection, err := SelectKeyByAttrIdx(loginInterface, userPasscode, keypadSize)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = nkodeApi.Login(*customerId, username, loginKeySelection)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = nkodeApi.RenewAttributes(*customerId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
loginInterface, err = nkodeApi.GetLoginInterface(username, *customerId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
loginKeySelection, err = SelectKeyByAttrIdx(loginInterface, userPasscode, keypadSize)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = nkodeApi.Login(*customerId, username, loginKeySelection)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
core/api/test_helper.go
Normal file
21
core/api/test_helper.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go-nkode/models"
|
||||||
|
"go-nkode/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SelectKeyByAttrIdx(interfaceUser []int, passcodeIdxs []int, keypadSize models.KeypadSize) ([]int, error) {
|
||||||
|
selectedKeys := make([]int, len(passcodeIdxs))
|
||||||
|
for idx := range passcodeIdxs {
|
||||||
|
attrIdx := util.IndexOf[int](interfaceUser, passcodeIdxs[idx])
|
||||||
|
keyNumb := attrIdx / keypadSize.AttrsPerKey
|
||||||
|
if keyNumb < 0 || keyNumb >= keypadSize.NumbOfKeys {
|
||||||
|
return nil, errors.New(fmt.Sprintf("index key number: %d out of range 0-%d", keyNumb, keypadSize.NumbOfKeys-1))
|
||||||
|
}
|
||||||
|
selectedKeys[idx] = keyNumb
|
||||||
|
}
|
||||||
|
return selectedKeys, nil
|
||||||
|
}
|
||||||
46
core/api/user.go
Normal file
46
core/api/user.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
m "go-nkode/models"
|
||||||
|
"go-nkode/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Username string
|
||||||
|
EncipheredPasscode m.EncipheredNKode
|
||||||
|
UserKeys UserCipherKeys
|
||||||
|
Interface UserInterface
|
||||||
|
Renew bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) DecipherMask(setVals []uint64, passcodeLen int) ([]uint64, error) {
|
||||||
|
return u.UserKeys.DecipherMask(u.EncipheredPasscode.Mask, setVals, passcodeLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) RenewKeys(setXor []uint64, attrXor []uint64) error {
|
||||||
|
u.Renew = true
|
||||||
|
var err error
|
||||||
|
u.UserKeys.SetKey, err = util.XorLists(setXor, u.UserKeys.SetKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.UserKeys.AlphaKey, err = util.XorLists(attrXor, u.UserKeys.AlphaKey)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
|
||||||
|
newKeys, err := NewUserCipherKeys(customerAttributes.KeypadSize, customerAttributes.SetVals, u.UserKeys.MaxNKodeLen)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
encipheredPasscode, err := newKeys.EncipherNKode(passcodeAttrIdx, customerAttributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.UserKeys = *newKeys
|
||||||
|
u.EncipheredPasscode = *encipheredPasscode
|
||||||
|
u.Renew = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
@@ -32,7 +32,7 @@ func NewUserCipherKeys(keypadSize models.KeypadSize, setVals []uint64, maxNKodeL
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
alphakey, _ := util.GenerateRandomNonRepeatingUint64(keypadSize.AttrsPerKey)
|
alphakey, _ := util.GenerateRandomNonRepeatingUint64(keypadSize.TotalAttrs())
|
||||||
passKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
passKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
||||||
maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
||||||
salt, _ := util.RandomBytes(10)
|
salt, _ := util.RandomBytes(10)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -66,7 +66,7 @@ func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
|
|||||||
return nil, errors.New("signup session username is nil")
|
return nil, errors.New("signup session username is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(confirmKeyEntry) == len(s.SetKeyEntry) {
|
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)))
|
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeyEntry)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package main
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
22
main.go
22
main.go
@@ -1,9 +1,23 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go-nkode/core/api"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
a := 3
|
nkodeApi := api.NewNKodeAPI()
|
||||||
b := a / 2
|
handler := api.NKodeHandler{Api: nkodeApi}
|
||||||
fmt.Println(b)
|
mux := http.NewServeMux()
|
||||||
|
mux.Handle(api.CreateNewCustomer, &handler)
|
||||||
|
mux.Handle(api.GenerateSignupInterface, &handler)
|
||||||
|
mux.Handle(api.SetNKode, &handler)
|
||||||
|
mux.Handle(api.ConfirmNKode, &handler)
|
||||||
|
mux.Handle(api.GetLoginInterface, &handler)
|
||||||
|
mux.Handle(api.Login, &handler)
|
||||||
|
mux.Handle(api.RenewAttributes, &handler)
|
||||||
|
fmt.Println("Running on localhost:8080")
|
||||||
|
log.Fatal(http.ListenAndServe("localhost:8080", mux))
|
||||||
}
|
}
|
||||||
|
|||||||
14
main_test.go
Normal file
14
main_test.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-nkode/core/api"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(t *testing.T) {
|
||||||
|
base := "http://localhost:8080"
|
||||||
|
|
||||||
|
resp, err := http.Post(base+api.CreateNewCustomer, "application/json")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type KeypadSize struct {
|
type KeypadSize struct {
|
||||||
AttrsPerKey int
|
AttrsPerKey int `json:"attrs_per_key"`
|
||||||
NumbOfKeys int
|
NumbOfKeys int `json:"numb_of_keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kp *KeypadSize) TotalAttrs() int {
|
func (kp *KeypadSize) TotalAttrs() int {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
type NKodePolicy struct {
|
type NKodePolicy struct {
|
||||||
MaxNkodeLen int
|
MaxNkodeLen int `json:"max_nkode_len"`
|
||||||
MinNkodeLen int
|
MinNkodeLen int `json:"min_nkode_len"`
|
||||||
DistinctSets int
|
DistinctSets int `json:"distinct_sets"`
|
||||||
DistinctAttributes int
|
DistinctAttributes int `json:"distinct_attributes"`
|
||||||
LockOut int
|
LockOut int `json:"lock_out"`
|
||||||
Expiration int // seconds, -1 no expiration
|
Expiration int `json:"expiration"` // seconds, -1 no expiration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultNKodePolicy() NKodePolicy {
|
func NewDefaultNKodePolicy() NKodePolicy {
|
||||||
|
|||||||
66
nkode_api.go
66
nkode_api.go
@@ -1,66 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"go-nkode/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type NKodeAPI struct {
|
|
||||||
Customers map[uuid.UUID]Customer
|
|
||||||
SignupSessions map[uuid.UUID]UserSignSession
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewNKodeAPI() NKodeAPI {
|
|
||||||
return NKodeAPI{
|
|
||||||
Customers: make(map[uuid.UUID]Customer),
|
|
||||||
SignupSessions: make(map[uuid.UUID]UserSignSession),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeAPI) CreateNewCustomer(keypadSize models.KeypadSize, nkodePolicy models.NKodePolicy) (*uuid.UUID, error) {
|
|
||||||
newCustomer, err := NewCustomer(keypadSize, nkodePolicy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
n.Customers[newCustomer.CustomerId] = *newCustomer
|
|
||||||
return &newCustomer.CustomerId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeAPI) GenerateSignupInterface(customerId uuid.UUID) (*uuid.UUID, []int, error) {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return nil, nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
signupSession, err := NewSignupSession(customer.Attributes.KeypadSize, customer.CustomerId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
n.SignupSessions[signupSession.SessionId] = *signupSession
|
|
||||||
return &signupSession.SessionId, signupSession.SetInterface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeAPI) SetNKode(username string, customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) ([]int, error) {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId.String()))
|
|
||||||
}
|
|
||||||
_, exists = customer.Users[username]
|
|
||||||
if exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("user already exists %s", username))
|
|
||||||
}
|
|
||||||
|
|
||||||
session, exists := n.SignupSessions[sessionId]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
|
|
||||||
}
|
|
||||||
confirmInterface, err := session.SetUserNKode(username, keySelection)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return confirmInterface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeAPI) ConfirmNKode(username string, customerId uuid.UUID, confirmKeyEntry []int)
|
|
||||||
17
user.go
17
user.go
@@ -1,17 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
m "go-nkode/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Username string
|
|
||||||
EncipheredPasscode m.EncipheredNKode
|
|
||||||
UserKeys UserCipherKeys
|
|
||||||
Interface UserInterface
|
|
||||||
Renew bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) DecipherMask(setVals []uint64, passcodeLen int) ([]uint64, error) {
|
|
||||||
return u.UserKeys.DecipherMask(u.EncipheredPasscode.Mask, setVals, passcodeLen)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user