package nkode import ( "errors" "fmt" "github.com/google/uuid" m "go-nkode/core/model" "go-nkode/hashset" py "go-nkode/py-builtin" "go-nkode/util" ) type Customer struct { Id m.CustomerId NKodePolicy m.NKodePolicy Attributes CustomerAttributes } func NewCustomer(nkodePolicy m.NKodePolicy) (*Customer, error) { customerAttrs, err := NewCustomerAttributes() if err != nil { return nil, err } customer := Customer{ Id: m.CustomerId(uuid.New()), NKodePolicy: nkodePolicy, Attributes: *customerAttrs, } return &customer, nil } //func (c *Customer) AddNewUser(username m.Username, passcodeIdx []int, ui UserInterface, kp m.KeypadDimension) error { // _, exists := c.Users[username] // if exists { // return errors.New(fmt.Sprintf("User %s already exists for customer %+v exists", username, c.Id)) // } // setVals, err := c.Attributes.SetVals(kp) // if err != nil { // return err // } // newKeys, err := NewUserCipherKeys(&kp, setVals, c.NKodePolicy.MaxNkodeLen) // if err != nil { // return err // } // encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, c.Attributes) // if err != nil { // return err // } // newUser := User{ // Id: m.UserId(uuid.New()), // Username: username, // EncipheredPasscode: *encipheredNKode, // UserKeys: *newKeys, // Interface: ui, // Kp: kp, // } // c.Users[username] = newUser // return nil //} //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 %+v", username, c.Id)) // } // // validKeys := py.All[int](selectedKeys, func(idx int) bool { // return 0 <= idx && idx < user.Kp.NumbOfKeys // }) // if !validKeys { // return nil, errors.New(fmt.Sprintf("one or more keys not in range 0-%d", user.Kp.NumbOfKeys-1)) // } // presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys) // if err != nil { // return nil, err // } // err = c.IsValidNKode(user.Kp, presumedAttrIdxVals) // if err != nil { // return nil, err // } // attrVals, err := c.Attributes.AttrVals(user.Kp) // if err != nil { // return nil, err // } // err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals) // if err != nil { // return nil, err // } // // return presumedAttrIdxVals, 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)) // } // // setVals, err := c.Attributes.SetVals(user.Kp) // if err != nil { // return nil, err // } // passcodeSetVals, err := user.DecipherMask(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(kp m.KeypadDimension, 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)) } validIdx := py.All[int](passcodeAttrIdx, func(i int) bool { return i >= 0 && i < kp.TotalAttrs() }) if !validIdx { return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", kp.TotalAttrs()-1)) } passcodeSetVals := make(hashset.Set[uint64]) passcodeAttrVals := make(hashset.Set[uint64]) attrVals, err := c.Attributes.AttrVals(kp) if err != nil { return err } for idx := 0; idx < nkodeLen; idx++ { attrVal := attrVals[passcodeAttrIdx[idx]] setVal, err := c.Attributes.GetAttrSetVal(attrVal, kp) if err != nil { 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 } func (c *Customer) RenewKeys() ([]uint64, []uint64) { oldAttrs := make([]uint64, m.KeypadMax.TotalAttrs()) oldSets := make([]uint64, m.KeypadMax.AttrsPerKey) allAttrVals, err := c.Attributes.AttrVals(m.KeypadMax) if err != nil { panic(err) } allSetVals, err := c.Attributes.AttrVals(m.KeypadMax) if err != nil { panic(err) } copy(oldAttrs, allAttrVals) copy(oldSets, allSetVals) err = c.Attributes.Renew() if err != nil { panic(err) } allAttrVals, err = c.Attributes.AttrVals(m.KeypadMax) if err != nil { panic(err) } allSetVals, err = c.Attributes.SetVals(m.KeypadMax) if err != nil { panic(err) } attrsXor, err := util.XorLists(oldAttrs, allAttrVals) if err != nil { panic(err) } setXor, err := util.XorLists(oldSets, allSetVals) if err != nil { panic(err) } return setXor, attrsXor }