Files
go-nkode/core/user.go
2024-10-06 09:57:29 -05:00

148 lines
3.7 KiB
Go

package core
import (
"errors"
"github.com/google/uuid"
"go-nkode/py-builtin"
"go-nkode/util"
)
type User struct {
Id UserId
CustomerId CustomerId
Email UserEmail
EncipheredPasscode EncipheredNKode
Kp KeypadDimension
CipherKeys UserCipherKeys
Interface UserInterface
Renew bool
RefreshToken string
}
func (u *User) DecipherMask(setVals []uint64, passcodeLen int) ([]uint64, error) {
return u.CipherKeys.DecipherMask(u.EncipheredPasscode.Mask, setVals, passcodeLen)
}
func (u *User) RenewKeys(setXor []uint64, attrXor []uint64) error {
u.Renew = true
var err error
u.CipherKeys.SetKey, err = util.XorLists(setXor[:u.Kp.AttrsPerKey], u.CipherKeys.SetKey)
if err != nil {
return err
}
u.CipherKeys.AlphaKey, err = util.XorLists(attrXor[:u.Kp.TotalAttrs()], u.CipherKeys.AlphaKey)
return err
}
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
setVals, err := customerAttributes.SetValsForKp(u.Kp)
newKeys, err := NewUserCipherKeys(&u.Kp, setVals, u.CipherKeys.MaxNKodeLen)
if err != nil {
return err
}
encipheredPasscode, err := newKeys.EncipherNKode(passcodeAttrIdx, customerAttributes)
if err != nil {
return err
}
u.CipherKeys = *newKeys
u.EncipheredPasscode = *encipheredPasscode
u.Renew = false
return nil
}
func (u *User) GetLoginInterface() ([]int, error) {
err := u.Interface.PartialInterfaceShuffle()
if err != nil {
return nil, err
}
return u.Interface.IdxInterface, nil
}
var KeyIndexOutOfRange = errors.New("one or more keys is out of range")
func ValidKeyEntry(user User, customer Customer, selectedKeys []int) ([]int, error) {
validKeys := py_builtin.All[int](selectedKeys, func(idx int) bool {
return 0 <= idx && idx < user.Kp.NumbOfKeys
})
if !validKeys {
panic(KeyIndexOutOfRange)
}
var err error
passcodeLen := len(selectedKeys)
err = customer.NKodePolicy.ValidLength(passcodeLen)
if err != nil {
return nil, err
}
setVals, err := customer.Attributes.SetValsForKp(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 := customer.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
}
err = customer.IsValidNKode(user.Kp, presumedAttrIdxVals)
if err != nil {
return nil, err
}
attrVals, err := customer.Attributes.AttrValsForKp(user.Kp)
if err != nil {
return nil, err
}
err = user.CipherKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
if err != nil {
return nil, err
}
return presumedAttrIdxVals, nil
}
func NewUser(customer Customer, userEmail string, passcodeIdx []int, ui UserInterface, kp KeypadDimension) (*User, error) {
_, err := ParseEmail(userEmail)
if err != nil {
return nil, err
}
setVals, err := customer.Attributes.SetValsForKp(kp)
if err != nil {
return nil, err
}
newKeys, err := NewUserCipherKeys(&kp, setVals, customer.NKodePolicy.MaxNkodeLen)
if err != nil {
return nil, err
}
encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, customer.Attributes)
if err != nil {
return nil, err
}
newUser := User{
Id: UserId(uuid.New()),
Email: UserEmail(userEmail),
EncipheredPasscode: *encipheredNKode,
CipherKeys: *newKeys,
Interface: ui,
Kp: kp,
CustomerId: customer.Id,
}
return &newUser, nil
}