move user and customer files
This commit is contained in:
111
customer.go
Normal file
111
customer.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
m "go-nkode/models"
|
||||||
|
py "go-nkode/py-builtin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Customer struct {
|
||||||
|
CustomerId uuid.UUID
|
||||||
|
NKodePolicy m.NKodePolicy
|
||||||
|
Attributes CustomerAttributes
|
||||||
|
Users map[string]User
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
if keypadSize.AttrsPerKey < nkodePolicy.DistinctSets {
|
||||||
|
return nil, errors.New(fmt.Sprintf("incompadible nkode policy and keypad size AttrPerKey: %d < DistinctSets: %d", keypadSize.AttrsPerKey, nkodePolicy.DistinctSets))
|
||||||
|
}
|
||||||
|
customerAttrs, err := NewCustomerAttributes(keypadSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
customer := Customer{
|
||||||
|
CustomerId: uuid.New(),
|
||||||
|
NKodePolicy: nkodePolicy,
|
||||||
|
Attributes: *customerAttrs,
|
||||||
|
Users: make(map[string]User),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &customer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Customer) AddNewUser(user User) error {
|
||||||
|
_, exists := c.Users[user.Username]
|
||||||
|
if exists {
|
||||||
|
return errors.New(fmt.Sprintf("user: %s exists", user.Username))
|
||||||
|
}
|
||||||
|
c.Users[user.Username] = user
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Customer) ValidKeyEntryAndRenew(username string, selectedKeys []int) error {
|
||||||
|
user, exists := c.Users[username]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("user %s does not exist for customer %s", username, c.CustomerId.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
validKeys := py.All[int](selectedKeys, func(idx int) bool {
|
||||||
|
return 0 <= idx && idx < c.Attributes.keypadSize.NumbOfKeys
|
||||||
|
})
|
||||||
|
if !validKeys {
|
||||||
|
return errors.New(fmt.Sprintf("one or more keys not in range 0-%d", c.Attributes.keypadSize.NumbOfKeys-1))
|
||||||
|
}
|
||||||
|
presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, c.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Renew {
|
||||||
|
// renew
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
|
||||||
|
|
||||||
|
passcodeLen := len(selectedKeys)
|
||||||
|
if passcodeLen < c.NKodePolicy.MinNkodeLen || passcodeLen > c.NKodePolicy.MaxNkodeLen {
|
||||||
|
return nil, errors.New(fmt.Sprintf("Invalid passcode length of %d. Passcode length must be in range %d-%d", passcodeLen, c.NKodePolicy.MinNkodeLen, c.NKodePolicy.MaxNkodeLen))
|
||||||
|
}
|
||||||
|
passcodeSetVals, err := user.DecipherMask(c.Attributes.SetVals, passcodeLen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
presumedAttrIdxVals := make([]int, passcodeLen)
|
||||||
|
|
||||||
|
for idx := range presumedAttrIdxVals {
|
||||||
|
keyNumb := selectedKeys[idx]
|
||||||
|
setIdx, err := c.Attributes.IndexOfSet(passcodeSetVals[idx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
selectedAttrIdx, err := user.Interface.GetAttrIdxByKeyNumbSetIdx(setIdx, keyNumb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
presumedAttrIdxVals[idx] = selectedAttrIdx
|
||||||
|
}
|
||||||
|
return presumedAttrIdxVals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Customer) IsValidNKode(passcodeAttrIdx []int) error {
|
||||||
|
nkodeLen := len(passcodeAttrIdx)
|
||||||
|
if nkodeLen < c.NKodePolicy.MinNkodeLen {
|
||||||
|
return errors.New(fmt.Sprintf("NKode length %d is too short. Minimum nKode length is %d", nkodeLen, c.NKodePolicy.MinNkodeLen))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
package customer
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package customer
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -55,9 +55,13 @@ func (c *CustomerAttributes) IndexOfAttr(attrVal uint64) int {
|
|||||||
return util.IndexOf[uint64](c.AttrVals, attrVal)
|
return util.IndexOf[uint64](c.AttrVals, attrVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CustomerAttributes) IndexOfSet(setVal uint64) int {
|
func (c *CustomerAttributes) IndexOfSet(setVal uint64) (int, error) {
|
||||||
// TODO: should this be mapped instead?
|
// TODO: should this be mapped instead?
|
||||||
return util.IndexOf[uint64](c.SetVals, setVal)
|
idx := util.IndexOf[uint64](c.SetVals, setVal)
|
||||||
|
if idx == -1 {
|
||||||
|
return -1, errors.New(fmt.Sprintf("Set Val %d is invalid", setVal))
|
||||||
|
}
|
||||||
|
return idx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CustomerAttributes) GetAttrSetVal(attrVal uint64) (uint64, error) {
|
func (c *CustomerAttributes) GetAttrSetVal(attrVal uint64) (uint64, error) {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package customer
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
|
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
|
||||||
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
|||||||
17
user.go
Normal file
17
user.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
package users
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go-nkode/customer"
|
|
||||||
"go-nkode/models"
|
"go-nkode/models"
|
||||||
"go-nkode/util"
|
"go-nkode/util"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@@ -60,30 +59,35 @@ func (u *UserCipherKeys) PadUserMask(userMask []uint64, setVals []uint64) ([]uin
|
|||||||
return paddedUserMask, nil
|
return paddedUserMask, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserCipherKeys) ValidPassword(hashedPassword []byte, passcodeAttrIdx []int, customerAttrs customer.CustomerAttributes) error {
|
func (u *UserCipherKeys) ValidPassword(hashedPassword string, passcodeAttrIdx []int, customerAttrs CustomerAttributes) error {
|
||||||
|
hashBytes := []byte(hashedPassword)
|
||||||
passcodeCipher := u.encipherCode(passcodeAttrIdx, customerAttrs)
|
passcodeCipher := u.encipherCode(passcodeAttrIdx, customerAttrs)
|
||||||
passwordDigest, err := u.saltAndDigest(passcodeCipher)
|
passwordDigest, err := u.saltAndDigest(passcodeCipher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = bcrypt.CompareHashAndPassword(hashedPassword, passwordDigest)
|
err = bcrypt.CompareHashAndPassword(hashBytes, passwordDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserCipherKeys) EncipherSaltHashCode(passcodeAttrIdx []int, customerAttrs customer.CustomerAttributes) ([]byte, error) {
|
func (u *UserCipherKeys) EncipherSaltHashCode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (string, error) {
|
||||||
passcodeCipher := u.encipherCode(passcodeAttrIdx, customerAttrs)
|
passcodeCipher := u.encipherCode(passcodeAttrIdx, customerAttrs)
|
||||||
|
|
||||||
passcodeDigest, err := u.saltAndDigest(passcodeCipher)
|
passcodeDigest, err := u.saltAndDigest(passcodeCipher)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
return u.hashPasscode(passcodeDigest)
|
passcodeBytes, err := u.hashPasscode(passcodeDigest)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(passcodeBytes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserCipherKeys) encipherCode(passcodeAttrIdx []int, customerAttrs customer.CustomerAttributes) []uint64 {
|
func (u *UserCipherKeys) encipherCode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) []uint64 {
|
||||||
passcodeLen := len(passcodeAttrIdx)
|
passcodeLen := len(passcodeAttrIdx)
|
||||||
|
|
||||||
passcodeCipher := make([]uint64, u.MaxNKodeLen)
|
passcodeCipher := make([]uint64, u.MaxNKodeLen)
|
||||||
@@ -118,7 +122,7 @@ func (u *UserCipherKeys) hashPasscode(passcodeDigest []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return hashedPassword, nil
|
return hashedPassword, nil
|
||||||
}
|
}
|
||||||
func (u *UserCipherKeys) EncipherMask(passcodeSet []uint64, customerAttrs customer.CustomerAttributes) (string, error) {
|
func (u *UserCipherKeys) EncipherMask(passcodeSet []uint64, customerAttrs CustomerAttributes) (string, error) {
|
||||||
paddedPasscodeSets, err := u.PadUserMask(passcodeSet, customerAttrs.SetVals)
|
paddedPasscodeSets, err := u.PadUserMask(passcodeSet, customerAttrs.SetVals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -126,7 +130,10 @@ func (u *UserCipherKeys) EncipherMask(passcodeSet []uint64, customerAttrs custom
|
|||||||
|
|
||||||
cipheredMask := make([]uint64, len(paddedPasscodeSets))
|
cipheredMask := make([]uint64, len(paddedPasscodeSets))
|
||||||
for idx := range paddedPasscodeSets {
|
for idx := range paddedPasscodeSets {
|
||||||
setIdx := customerAttrs.IndexOfSet(paddedPasscodeSets[idx])
|
setIdx, err := customerAttrs.IndexOfSet(paddedPasscodeSets[idx])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
setKeyVal := u.SetKey[setIdx]
|
setKeyVal := u.SetKey[setIdx]
|
||||||
maskKeyVal := u.MaskKey[idx]
|
maskKeyVal := u.MaskKey[idx]
|
||||||
setVal := paddedPasscodeSets[idx]
|
setVal := paddedPasscodeSets[idx]
|
||||||
@@ -158,7 +165,7 @@ func (u *UserCipherKeys) DecipherMask(mask string, setVals []uint64, passcodeLen
|
|||||||
return passcodeSet, nil
|
return passcodeSet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs customer.CustomerAttributes) (*models.EncipheredNKode, error) {
|
func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (*models.EncipheredNKode, error) {
|
||||||
code, err := u.EncipherSaltHashCode(passcodeAttrIdx, customerAttrs)
|
code, err := u.EncipherSaltHashCode(passcodeAttrIdx, customerAttrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -174,7 +181,7 @@ func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs cust
|
|||||||
}
|
}
|
||||||
mask, err := u.EncipherMask(passcodeSet, customerAttrs)
|
mask, err := u.EncipherMask(passcodeSet, customerAttrs)
|
||||||
encipheredCode := models.EncipheredNKode{
|
encipheredCode := models.EncipheredNKode{
|
||||||
Code: string(code),
|
Code: code,
|
||||||
Mask: mask,
|
Mask: mask,
|
||||||
}
|
}
|
||||||
return &encipheredCode, nil
|
return &encipheredCode, nil
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package users
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"go-nkode/hashset"
|
"go-nkode/hashset"
|
||||||
"go-nkode/models"
|
"go-nkode/models"
|
||||||
"go-nkode/util"
|
"go-nkode/util"
|
||||||
@@ -174,3 +175,18 @@ func (u *UserInterface) PartialInterfaceShuffle() error {
|
|||||||
u.IdxInterface = util.MatrixToList(keypadView)
|
u.IdxInterface = util.MatrixToList(keypadView)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserInterface) GetAttrIdxByKeyNumbSetIdx(setIdx int, keyNumb int) (int, error) {
|
||||||
|
if keyNumb < 0 || u.KeypadSize.NumbOfKeys <= keyNumb {
|
||||||
|
return -1, errors.New(fmt.Sprintf("keyNumb %d is out of range 0-%d", keyNumb, u.KeypadSize.NumbOfKeys))
|
||||||
|
}
|
||||||
|
|
||||||
|
if setIdx < 0 || u.KeypadSize.AttrsPerKey <= setIdx {
|
||||||
|
return -1, errors.New(fmt.Sprintf("setIdx %d is out of range 0-%d", setIdx, u.KeypadSize.AttrsPerKey))
|
||||||
|
}
|
||||||
|
keypadView, err := u.InterfaceMatrix()
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return keypadView[keyNumb][setIdx], nil
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
package users
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"go-nkode/customer"
|
|
||||||
"go-nkode/models"
|
"go-nkode/models"
|
||||||
py_builtin "go-nkode/py-builtin"
|
py_builtin "go-nkode/py-builtin"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -11,7 +10,7 @@ import (
|
|||||||
func TestUserCipherKeys_EncipherSaltHashCode(t *testing.T) {
|
func TestUserCipherKeys_EncipherSaltHashCode(t *testing.T) {
|
||||||
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
||||||
maxNKodeLen := 10
|
maxNKodeLen := 10
|
||||||
customerAttrs, err := customer.NewCustomerAttributes(keypadSize)
|
customerAttrs, err := NewCustomerAttributes(keypadSize)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
newUser, err := NewUserCipherKeys(keypadSize, customerAttrs.SetVals, maxNKodeLen)
|
newUser, err := NewUserCipherKeys(keypadSize, customerAttrs.SetVals, maxNKodeLen)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -26,7 +25,7 @@ func TestUserCipherKeys_EncipherDecipherMask(t *testing.T) {
|
|||||||
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
||||||
maxNKodeLen := 10
|
maxNKodeLen := 10
|
||||||
|
|
||||||
customerAttrs, err := customer.NewCustomerAttributes(keypadSize)
|
customerAttrs, err := NewCustomerAttributes(keypadSize)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
newUser, err := NewUserCipherKeys(keypadSize, customerAttrs.SetVals, maxNKodeLen)
|
newUser, err := NewUserCipherKeys(keypadSize, customerAttrs.SetVals, maxNKodeLen)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -1 +0,0 @@
|
|||||||
package users
|
|
||||||
Reference in New Issue
Block a user