tricrypt/tlep/monkeylang/dict.go
2024-06-04 19:19:11 +03:00

125 lines
2.8 KiB
Go

package monkeylang
import (
"crypto/rand"
"crypto/sha512"
"encoding/base32"
"fmt"
"git.qowevisa.me/Qowevisa/gotell/tlep/monkeylang/myerr"
"git.qowevisa.me/Qowevisa/gotell/tlep/shuffle"
"strings"
)
const (
VERSION_1 = 1 + iota
)
const LATEST_VERSION = VERSION_1
type WORD_VAL uint16
const DICT_LEN = 0x010000
type Dictionary struct {
Values [DICT_LEN]WORD_VAL
Words [DICT_LEN]string
}
func CreateNewDictionary() (*Dictionary, error) {
var d Dictionary
dummyKey := make([]byte, DICT_LEN)
n, err := rand.Read(dummyKey)
if err != nil {
return nil, err
}
if n != len(dummyKey) {
return nil, myerr.INTERNAL_ERROR
}
for i := 0; i < DICT_LEN; i++ {
d.Values[i] = WORD_VAL(i)
}
newVals := shuffle.Shuffle(d.Values[:], dummyKey)
if len(newVals) != len(d.Values) {
return nil, myerr.INTERNAL_ERROR
}
for i, nv := range newVals {
d.Values[i] = nv
}
words := GenerateStrongWords(DICT_LEN)
for i, word := range words {
d.Words[i] = word
}
return &d, nil
}
func (d *Dictionary) GetFirstWords(n int) []string {
return d.Words[:n]
}
func (d *Dictionary) GetFirstValues(n int) []WORD_VAL {
return d.Values[:n]
}
func allUniqueT[T comparable](strings []T) (int, bool) {
notUnique := 0
seen := make(map[T]struct{})
for _, s := range strings {
if _, ok := seen[s]; ok {
notUnique++
}
seen[s] = struct{}{}
}
return notUnique, notUnique == 0
}
func (d *Dictionary) GetStat() string {
stt := fmt.Sprintf("D Words Len : %d\n", len(d.Values))
mNU, mIAU := allUniqueT(d.Words[:])
stt += fmt.Sprintf("D Meanings Not Unique : %d ; %t\n", mNU, mIAU)
wNU, wIAU := allUniqueT(d.Values[:])
stt += fmt.Sprintf("D Words Not Unique : %d ; %t\n", wNU, wIAU)
return stt
}
func (d *Dictionary) GetFingerprint() string {
mm := strings.Join(d.Words[:], ".")
var ww []byte
for _, w := range d.Values {
ww = append(ww, byte(w>>8), byte(w))
}
ww = append(ww, []byte(mm)...)
hash := sha512.Sum512(ww)
fingerprint := make([]byte, base32.StdEncoding.EncodedLen(len(hash)))
base32.StdEncoding.Encode(fingerprint, hash[:])
return string(fingerprint[:])
}
func (d *Dictionary) GetFingerprintBytes() []byte {
mm := strings.Join(d.Words[:], ".")
var ww []byte
for _, w := range d.Values {
ww = append(ww, byte(w>>8), byte(w))
}
ww = append(ww, []byte(mm)...)
hash := sha512.Sum512(ww)
fingerprint := make([]byte, base32.StdEncoding.EncodedLen(len(hash)))
base32.StdEncoding.Encode(fingerprint, hash[:])
return fingerprint[:]
}
func (d *Dictionary) GetFingerprintWithInfo(info string) string {
mm := strings.Join(d.Words[:], ".")
var ww []byte
for _, w := range d.Values {
ww = append(ww, byte(w>>8), byte(w))
}
ww = append(ww, []byte(mm)...)
ww = append(ww, []byte(info)...)
hash := sha512.Sum512(ww)
fingerprint := make([]byte, base32.StdEncoding.EncodedLen(len(hash)))
base32.StdEncoding.Encode(fingerprint, hash[:])
return string(fingerprint[:])
}