Author: Adam <git@apiote.xyz>
[NOPALOAD] embed will
decoder/joeblack.go | 24 encode | 2 encoder/joeblack.go | 103 ++- encoder/vendor/apiote.xyz/p/go-dirty/README | 1 encoder/vendor/apiote.xyz/p/go-dirty/array.go | 76 ++ encoder/vendor/apiote.xyz/p/go-dirty/const.go | 59 + encoder/vendor/apiote.xyz/p/go-dirty/errors.go | 95 ++ encoder/vendor/apiote.xyz/p/go-dirty/example.drt | 27 encoder/vendor/apiote.xyz/p/go-dirty/main.go | 72 ++ encoder/vendor/apiote.xyz/p/go-dirty/number.go | 180 +++++ encoder/vendor/apiote.xyz/p/go-dirty/string.go | 123 +++ encoder/vendor/apiote.xyz/p/go-dirty/struct.go | 202 ++++++ encoder/vendor/apiote.xyz/p/go-dirty/tokeniser.go | 270 ++++++++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.build.yml | 12 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.gitignore | 3 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/LICENSE | 13 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/README.md | 130 +++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/errors.go | 17 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/limit.go | 55 + encoder/vendor/git.sr.ht/~sircmpwn/go-bare/marshal.go | 308 +++++++++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/package.go | 8 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/reader.go | 188 +++++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unions.go | 76 ++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unmarshal.go | 359 +++++++++++ encoder/vendor/git.sr.ht/~sircmpwn/go-bare/varint.go | 27 encoder/vendor/git.sr.ht/~sircmpwn/go-bare/writer.go | 116 +++ encoder/vendor/github.com/codahale/sss/.gitignore | 1 encoder/vendor/github.com/codahale/sss/.travis.yml | 9 encoder/vendor/github.com/codahale/sss/LICENSE | 21 encoder/vendor/github.com/codahale/sss/README.md | 11 encoder/vendor/github.com/codahale/sss/gf256.go | 81 ++ encoder/vendor/github.com/codahale/sss/polynomial.go | 67 ++ encoder/vendor/github.com/codahale/sss/sss.go | 120 +++ encoder/vendor/modules.txt | 9 index.html | 41 payload | 1 shared/shared.go | 52 +
diff --git a/decoder/joeblack.go b/decoder/joeblack.go index 6072629ff187aec8225dee73201cded4e781f628..5a4b4df6283a2c99c7339a277f6de3c8e8ca676c 100644 --- a/decoder/joeblack.go +++ b/decoder/joeblack.go @@ -37,8 +37,8 @@ } // args:: shares :[sharesNum]string... func decodeSSS(this js.Value, args []js.Value) any { - if len(args) != sharesNum { - return fmt.Sprintf("ERR: Invalid number of arguments given %d, expected %d\n", len(args), sharesNum) + if len(args) != sharesNum { // +1 + return fmt.Sprintf("ERR: Invalid number of arguments given %d, expected %d\n", len(args), sharesNum) // +1 } shares := map[byte][]byte{} for i := 0; i < sharesNum; i++ { @@ -49,6 +49,7 @@ return fmt.Sprintf("ERR: while decoding words: %v", err) } shareNum := shareBytes[len(shareBytes)-1] shareBytes = shareBytes[:len(shareBytes)-1] + //todo last argument is burnt sha512sums of shares; if it matches any => return Err shares[shareNum] = shareBytes } return base64.StdEncoding.EncodeToString(sss.Combine(shares)) @@ -84,10 +85,10 @@ rawPayload, err := base64.StdEncoding.DecodeString(args[1].String()) if err != nil { return fmt.Sprintf("ERR: while decoding base64 payload: %v", err) } - payload := Payload{} - payload.Keys = make([][]byte, 2) - l1 := rawPayload[0] - l2 := rawPayload[l1+1] + payload, err := unmarshal(rawPayload) + if err != nil { + return fmt.Sprintf("ERR: while unmarshalling: %v", err) + } var key []byte var keyNum int if isPaperKey { @@ -96,13 +97,10 @@ } else { keyNum = 0 } - payload.Keys[0] = rawPayload[1 : l1+1] - payload.Keys[1] = rawPayload[l1+2 : l1+2+l2] key, err = decrypt(payload.Keys[keyNum], wordsKey) if err != nil { return fmt.Sprintf("ERR: while decrypting key: %v", err) } - payload.Secrets = rawPayload[l1+2+l2:] rawSecrets, err := decrypt(payload.Secrets, key) if err != nil { return fmt.Sprintf("ERR: while decrypting secrets: %v", err) @@ -113,6 +111,12 @@ if err != nil { return fmt.Sprintf("ERR: while unmarshalling secrets: %v", err) } + will, err := decrypt(payload.Will, key) + if err != nil { + return fmt.Sprintf("ERR: while decrypting will: %v", err) + } + willB64 := base64.StdEncoding.EncodeToString(will) + export := "" secretsLen := len(secrets) for i, secret := range secrets { @@ -130,5 +134,5 @@ if i+1 < secretsLen { export += fmt.Sprintln("---") } } - return export + return willB64 + "|" + export } diff --git a/encode b/encode index 57bed3045da6dcca1d57fecd09f188859d62c783..b32d50d97fc608206a328f8de74daedae74767d0 100755 --- a/encode +++ b/encode @@ -4,7 +4,7 @@ eeze -E >encoder/secrets.dirty mv payload encoder/payload cd encoder -joeblack -r +./joeblack -r shred -fuz secrets.dirty cd ../ mv encoder/payload . diff --git a/encoder/joeblack.go b/encoder/joeblack.go index c84275d6fc2c2b26d2213e78594cd478bd00eb42..2de225378b630aabb830e9ecfb2cc3a869174cf8 100644 --- a/encoder/joeblack.go +++ b/encoder/joeblack.go @@ -5,12 +5,13 @@ "bufio" "crypto/rand" "encoding/base64" "fmt" - "github.com/codahale/sss" "io" "os" + //"strconv" "apiote.xyz/p/go-dirty" "git.sr.ht/~sircmpwn/go-bare" + "github.com/codahale/sss" ) func main() { @@ -29,13 +30,31 @@ wordlistRev[wordlist[i]] = i } recreate := false + add := false + //var already int64 = 0 if len(os.Args) > 1 && os.Args[1] == "-r" { recreate = true } + if len(os.Args) > 2 && os.Args[1] == "-a" { + add = true + //already, _ = strconv.ParseInt(os.Args[2], 10, 8) + } payload := Payload{} key := [32]byte{} - if !recreate { + sssKey := [32]byte{} + paperKey := [32]byte{} + if !recreate && !add { + _, err = io.ReadFull(rand.Reader, sssKey[:]) + if err != nil { + fmt.Printf("while creating sss key: %v\n", err) + os.Exit(1) + } + _, err = io.ReadFull(rand.Reader, paperKey[:]) + if err != nil { + fmt.Printf("while creating paperkey: %v\n", err) + os.Exit(1) + } _, err = io.ReadFull(rand.Reader, key[:]) if err != nil { fmt.Printf("while creating key: %v\n", err) @@ -47,7 +66,7 @@ if err != nil { fmt.Printf("while reading paper key: %v\n", err) os.Exit(1) } - paperKey, err := fromWords(paperKeyWords, wordlistRev) + pK, err := fromWords(paperKeyWords, wordlistRev) if err != nil { fmt.Printf("while decoding paper key: %v\n", err) os.Exit(1) @@ -58,38 +77,38 @@ fmt.Printf("while opening payload: %v\n", err) os.Exit(1) } defer payloadFile.Close() - reader := base64.NewDecoder(base64.StdEncoding, payloadFile) - payload.Keys = make([][]byte, 2) - l := make([]byte, 1) - _, err = io.ReadFull(reader, l) + payloadB64, err := io.ReadAll(payloadFile) if err != nil { - fmt.Printf("while reading key[0] length: %v\n", err) + fmt.Printf("while reading payload: %v\n", err) os.Exit(1) } - payload.Keys[0] = make([]byte, l[0]) - _, err = io.ReadFull(reader, payload.Keys[0]) + + payloadBytes, err := base64.StdEncoding.DecodeString(string(payloadB64)) if err != nil { - fmt.Printf("while reading key[0]: %v\n", err) + fmt.Printf("while de-base64-ing payload: %v\n", err) os.Exit(1) } - _, err = io.ReadFull(reader, l) + + payload, err = unmarshal(payloadBytes) if err != nil { - fmt.Printf("while reading key[1] length: %v\n", err) + fmt.Printf("while unmarshaling payload: %v\n", err) os.Exit(1) } - payload.Keys[1] = make([]byte, l[0]) - _, err = io.ReadFull(reader, payload.Keys[1]) + + k, err := decrypt(payload.Keys[1], pK) if err != nil { - fmt.Printf("while reading key[1]: %v\n", err) + fmt.Printf("while decrypting paperKeyEnc: %v\n", err) os.Exit(1) } - k, err := decrypt(payload.Keys[1], paperKey) + sk, err := decrypt(payload.Keys[2], pK) if err != nil { fmt.Printf("while decrypting paperKeyEnc: %v\n", err) os.Exit(1) } copy(key[:], k) + copy(sssKey[:], sk) + copy(paperKey[:], pK) } secrets := []Secret{} @@ -112,46 +131,58 @@ fmt.Printf("while marshalling secrets: %v\n", err) os.Exit(1) } + will, err := os.Open("will.pdf") + if err != nil { + fmt.Printf("while opening will: %v\n", err) + os.Exit(1) + } + defer will.Close() + + willBytes, err := io.ReadAll(will) + if err != nil { + fmt.Printf("while reading will: %v\n", err) + os.Exit(1) + } + payload.Secrets, err = encrypt(bareSecrets, key[:]) + payload.Will, err = encrypt(willBytes, key[:]) - if !recreate { - sssKey := [32]byte{} - _, err = io.ReadFull(rand.Reader, sssKey[:]) + if add { + /* todo + shares, err := sss.Add(1, 3, byte(already), sssKey[:]) // for x =byte(1); x<=n+already; x++ if err != nil { - fmt.Printf("while creating sss key: %v\n", err) + fmt.Printf("while spliting: %v\n", err) os.Exit(1) } - paperKey := [32]byte{} - _, err = io.ReadFull(rand.Reader, paperKey[:]) - if err != nil { - fmt.Printf("while creating paperkey: %v\n", err) - os.Exit(1) - } + fmt.Println(toWords(shares[already], wordlist)) + */ + } else if !recreate { sssKeyEnc, err := encrypt(key[:], sssKey[:]) paperKeyEnc, err := encrypt(key[:], paperKey[:]) + sssKeyPaperEnc, err := encrypt(sssKey[:], paperKey[:]) + payload.Keys = [][]byte{} payload.Keys = append(payload.Keys, sssKeyEnc) payload.Keys = append(payload.Keys, paperKeyEnc) + payload.Keys = append(payload.Keys, sssKeyPaperEnc) shares, err := sss.Split(5, 3, sssKey[:]) if err != nil { fmt.Printf("while spliting: %v\n", err) os.Exit(1) } - for i, share := range shares { - share = append(share, byte(i)) + for x, share := range shares { + share = append(share, x) fmt.Println(toWords(share, wordlist)) } fmt.Println("") fmt.Println(toWords(paperKey[:], wordlist)) } - - payloadBytes := []byte{} - payloadBytes = append(payloadBytes, byte(len(payload.Keys[0]))) - payloadBytes = append(payloadBytes, payload.Keys[0]...) - payloadBytes = append(payloadBytes, byte(len(payload.Keys[1]))) - payloadBytes = append(payloadBytes, payload.Keys[1]...) - payloadBytes = append(payloadBytes, payload.Secrets...) + payloadBytes, err := bare.Marshal(&payload) + if err != nil { + fmt.Printf("while marshaling: %v\n", err) + os.Exit(1) + } payloadB64 := base64.StdEncoding.EncodeToString(payloadBytes) os.WriteFile("payload", []byte(payloadB64), 0o644) } diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/README b/encoder/vendor/apiote.xyz/p/go-dirty/README new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/README @@ -0,0 +1 @@ + diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/array.go b/encoder/vendor/apiote.xyz/p/go-dirty/array.go new file mode 100644 index 0000000000000000000000000000000000000000..76f9f224ab6a0fbb7e850096cca5d28815a7e872 --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/array.go @@ -0,0 +1,76 @@ +package dirty + +import ( + "bufio" +) + +type Array []Element + +func (Array) isElement() {} +func (Array) getType() ElementType { + return ElemArray +} + +type Element interface { + isElement() + getType() ElementType +} + +type ElementType int + +const ( + ElemArray ElementType = iota + ElemString + ElemConst + ElemInt + ElemFloat +) + +func loadArray(r *bufio.Reader) ([]Element, error) { + topArray := []Element{} + for { + t, err := nextToken(r) + if err != nil { + return []Element{}, err + } + //debugf("in LoadArray got %+v\n", t) + + switch t.ttype { + case LBRACKET: + //debugf("in LoadArray loading array\n") + array, err := loadArray(r) + if err != nil { + return []Element{}, err + } + topArray = append(topArray, Array(array)) + case RBRACKET: + //debugf("in LoadArray closing\n") + return topArray, nil + // todo atoms + case COMMENT: + continue + case STRING: + //debugf("in LoadArray adding string\n") + topArray = append(topArray, String(t.t)) + case STRING_RAW: + //debugf("in LoadArray adding raw string\n") + topArray = append(topArray, String(t.t)) + case CONST: + //debugf("in LoadArray adding const\n") + topArray = append(topArray, NewConst(t.t)) + case NUMBER: + //debugf("in LoadArray adding number %+v, %d\n", t, *t.i) + if t.i != nil { + topArray = append(topArray, Int(*t.i)) + } + case FLOAT: + //debugf("in LoadArray adding float %+v, %f\n", t, *t.f) + if t.f != nil { + topArray = append(topArray, Float(*t.f)) + } + default: + //debugln("loadArray") + return []Element{}, NewSyntaxError(t, []token{}) + } + } +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/const.go b/encoder/vendor/apiote.xyz/p/go-dirty/const.go new file mode 100644 index 0000000000000000000000000000000000000000..1712b7fc43a3e70830b957080846c8b5cd41fbc9 --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/const.go @@ -0,0 +1,59 @@ +package dirty + +import ( + "fmt" +) + +type Const int + +const ( + TRUE Const = iota + FALSE + NULL +) + +func NewConst(s string) Const { + if s == "true" { + return TRUE + } + if s == "false" { + return FALSE + } + if s == "null" { + return NULL + } + panic("invalid const " + s) +} + +func (Const) isElement() {} +func (Const) getType() ElementType { + return ElemConst +} +func (c Const) String() string { + if c == TRUE { + return "true" + } + if c == FALSE { + return "false" + } + if c == NULL { + return "null" + } + panic(fmt.Sprintf("invalid const %d", c)) +} +func (c Const) Bool() bool { + if c == TRUE { + return true + } else if c == FALSE { + return false + } else { + panic("Const is not bool") + } +} + +func parseConst(t token) (token, error) { + if t.t != "true" && t.t != "false" && t.t != "null" { + return token{}, NewConstError(t.t) + } + return t, nil +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/errors.go b/encoder/vendor/apiote.xyz/p/go-dirty/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..fc568d94db43b1ceb7317b827594eb0ae602bd1a --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/errors.go @@ -0,0 +1,95 @@ +package dirty + +import ( + "fmt" +) + +type SyntaxError struct { + found token + expected []token +} + +func NewSyntaxError(found token, expected []token) SyntaxError { + return SyntaxError{found: found, expected: expected} +} +func (se SyntaxError) Error() string { + return fmt.Sprintf("expected %v; got %v\n", se.expected, se.found) +} + +type UnterminatedError struct { + ttype string + t string +} + +func NewUnterminatedError(ttype string, t string) UnterminatedError { + return UnterminatedError{ttype: ttype, t: t} +} +func (e UnterminatedError) Error() string { + return fmt.Sprintf("unterminated %s ‘%s’\n", e.ttype, e.t) +} + +type InvalidCharError struct { + r rune +} + +func NewInvalidCharError(r rune) InvalidCharError { + return InvalidCharError{r: r} +} +func (e InvalidCharError) Error() string { + return fmt.Sprintf("invalid character ‘%d’\n", e.r) +} + +type CommaError struct { + s string +} + +func NewCommaError(s string) CommaError { + return CommaError{s: s} +} +func (e CommaError) Error() string { + return fmt.Sprintf("comma in wrong place in ‘%s’\n", e.s) +} + +type InvalidCodepointError struct { + c string +} + +func NewInvalidCodepointError(c string) InvalidCodepointError { + return InvalidCodepointError{c: c} +} +func (e InvalidCodepointError) Error() string { + return fmt.Sprintf("invalid codepoint ‘%s’\n", e.c) +} + +type ConstError struct { + t string +} + +func NewConstError(t string) ConstError { + return ConstError{t: t} +} +func (e ConstError) Error() string { + return fmt.Sprintf("malformed const ‘%s’\n", e.t) +} + +type EscapeError struct { + char rune +} + +func NewEscapeError(char rune) EscapeError { + return EscapeError{char: char} +} +func (e EscapeError) Error() string { + return fmt.Sprintf("invalid escape sequence \\%v\n", e.char) +} + +type RawStringError struct { + s string +} + +func NewRawStringError(s string) RawStringError { + return RawStringError{s: s} +} +func (e RawStringError) Error() string { + return e.s +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/example.drt b/encoder/vendor/apiote.xyz/p/go-dirty/example.drt new file mode 100644 index 0000000000000000000000000000000000000000..b91ea27c2ce4c6b707d552842542a756cf649cde --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/example.drt @@ -0,0 +1,27 @@ +( + ('map' # array of pairs + ( + ('π' 3.14) + ('e' 2.73) + ('h' 10,000·) # dozenal = 12^4 in decimal + ('one' 1) # decimal integer + ('positivity' true) + ('negativity' false) + ('i don’t know' null) + ('256' 0xff) + ('7' 0b111) + (7 'is not the same') + #(0b111 'but this would be') + ('execute' 0o755) + ('ice point' 16↋7·6) + ('dozenal digits' (1· 2· 3· 4· 5· 6· 7· 8· 9· ↊· ↋·)) + ('dozenal negative' -10·1) + ('escaped' 'i won\'t say but i will \tit\nand this will be in new line') + ('scientific' (7e27 7e-27)) + ('cold' -10) + ('imagine' (10+8i 8-10i ↊·+8·i 8·-↊·i)) + ) + ) + ('array' (1 2 3 'some text')) + ('mapception' (('one' 1) ('two' 2))) +) diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/main.go b/encoder/vendor/apiote.xyz/p/go-dirty/main.go new file mode 100644 index 0000000000000000000000000000000000000000..13a26554b376c2c710bc95c9541ab8dc3000c18a --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/main.go @@ -0,0 +1,72 @@ +package dirty + +import ( + "bufio" + "fmt" + "io" + "reflect" +) + +const DEBUG bool = true // build -X + +func debugf(format string, a ...interface{}) { + if DEBUG { + fmt.Printf(format, a...) + } +} +func debugln(a ...interface{}) { + if DEBUG { + fmt.Println(a...) + } +} + +// todo func LoadArray() +func Load(r io.Reader) (Array, error) { + scanner := bufio.NewReader(r) + array := []Element{} + comment := token{ttype: COMMENT} + lbrack := token{ttype: LBRACKET} + eof := token{ttype: EOF} + expected := lbrack + for { + t, err := nextToken(scanner) + //debugf("in Load got %+v\n", t) + if err != nil { + return []Element{}, err + } + if t == comment { + continue + } else if t == lbrack { + if expected != lbrack { + //debugln("expected lbrac") + return []Element{}, NewSyntaxError(t, []token{expected}) + } + //debugf("in Load loading array\n") + array, err = loadArray(scanner) + if err != nil { + return Array{}, err + } + expected = eof + } else if t == eof { + if expected != eof { + //debugln("expected eof") + return []Element{}, NewSyntaxError(t, []token{expected}) + } + //debugf("in Load eofing\n") + return array, nil + } else { + //debugln("garbage") + return []Element{}, NewSyntaxError(t, []token{expected}) + } + } +} + +// todo func Load() +func LoadStruct(r io.Reader, s interface{}) error { + array, err := Load(r) + if err != nil { + return err + } + v := reflect.ValueOf(s).Elem() + return convertStruct(array, v) +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/number.go b/encoder/vendor/apiote.xyz/p/go-dirty/number.go new file mode 100644 index 0000000000000000000000000000000000000000..0ebd92eccba900079e8821bb9b6de6c46214c718 --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/number.go @@ -0,0 +1,180 @@ +package dirty + +import ( + "math" + "strconv" + "strings" +) + +type Int int + +func (Int) isElement() {} +func (Int) getType() ElementType { + return ElemInt +} +func (i Int) String() string { + return strconv.FormatInt(int64(i), 10) +} + +type Float float64 + +func (Float) isElement() {} +func (Float) getType() ElementType { + return ElemFloat +} +func (i Float) String() string { + return strconv.FormatFloat(float64(i), 'f', -1, 64) +} + +func convertDozenal(d string) string { + result := "" + for _, c := range d { + if c == '↊' { + result += "a" + } else if c == '↋' { + result += "b" + } else if c == '·' { + result += "." + } else { + result += string(c) + } + } + return result +} + +func parseNumber(t token) (token, error) { + l := len(t.t) + if (in('.', []rune(t.t)) && t.t[l-1] != '.') || (in('·', []rune(t.t)) && t.t[l-1] != '·') { + return parseFloat(t) + } else if in('e', []rune(t.t)) && t.t[0] != '0' { + return parseEngFloat(t) + } else { + return parseInt(t) + } +} + +func parseFloat(t token) (token, error) { + t.ttype = FLOAT + if in('·', []rune(t.t)) { + number := strings.SplitN(convertDozenal(t.t), ".", 2) + whole, err := strconv.ParseInt(number[0], 12, 64) + if err != nil { + return token{}, err + } + fraction, err := strconv.ParseUint(number[1], 12, 64) + if err != nil { + return token{}, err + } + + t.t = "" + w := float64(whole) + if fraction != 0 { + var sign float64 + if w < 0 { + sign = -1.0 + } else { + sign = 1.0 + } + l := math.Floor(math.Log10((float64(fraction))/math.Log10(12)) + 1) + w += (float64(fraction) / math.Pow(12, l)) * sign + } + t.f = &w + return t, nil + } else { + f, err := strconv.ParseFloat(t.t, 64) + t.t = "" + t.f = &f + return t, err + } +} + +func parseEngFloat(t token) (token, error) { + t.ttype = FLOAT + number := strings.SplitN(t.t, "e", 2) + a, err := strconv.ParseFloat(number[0], 64) + if err != nil { + return token{}, err + } + b, err := strconv.ParseInt(number[1], 10, 64) + if err != nil { + return token{}, err + } + num := a * math.Pow10(int(b)) + t.t = "" + t.f = &num + return t, nil +} + +func parseComma(num string, z int) (string, error) { + num2 := "" + prevIsComma := false + lastComma := -1 + zeroes := "" + for i := 0; i < z; i++ { + zeroes += "0" + } + for i, d := range num { + if d == ',' { + if prevIsComma { + num2 += zeroes + } else if !((i-lastComma) == z+1 || lastComma == -1) { + return "", NewCommaError(num) + } + lastComma = i + } else { + num2 += string(d) + } + prevIsComma = d == ',' + } + return num2, nil +} + +func parseInt(t token) (token, error) { + num2 := t.t + base := 10 + + if t.t[0] == '0' && t.t[1] == 'b' { + num := t.t[2:] + if num[0] == ',' { + num = "1" + num + } + + var err error = nil + num2, err = parseComma(num, 8) + if err != nil { + return token{}, err + } + + num2 = "0b" + num2 + base = 0 + } + if t.t[0] == '0' && t.t[1] == 'o' { + num2 = t.t + base = 0 + } + if t.t[0] == '0' && t.t[1] == 'x' { + num2 = t.t + base = 0 + } + if in('·', []rune(t.t)) { + num, err := parseComma(t.t, 3) // 4? + if err != nil { + return token{}, err + } + num2 = convertDozenal(num) + num2 = num2[:len(num2)-1] + base = 12 + } + if in('.', []rune(t.t)) { + num2 = t.t[:len(t.t)-1] + var err error = nil + parseComma(num2, 3) + if err != nil { + return token{}, err + } + base = 10 + } + result, err := strconv.ParseInt(num2, base, 64) + t.i = &result + return t, err +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/string.go b/encoder/vendor/apiote.xyz/p/go-dirty/string.go new file mode 100644 index 0000000000000000000000000000000000000000..f951eb0e8f8341be44abd531ac5a82fd64d25131 --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/string.go @@ -0,0 +1,123 @@ +package dirty + +import ( + "strconv" + "unicode/utf8" +) + +type String string + +func (String) isElement() {} +func (String) getType() ElementType { + return ElemString +} +func (s String) String() string { + return "‘" + string(s) + "’" +} + +func parseString(t token) (token, error) { + result := "" + ucode := "" + mode := 0 + for _, r := range t.t { + if mode == 0 { + if r < 0x20 || r == 0x7f || (r >= 0x80 && r <= 0x9f) { + return token{}, NewInvalidCharError(rune(r)) + } + if r == '\\' { + mode = '\\' + continue + } + result += string(rune(r)) + } else if mode == '\\' { + switch r { + case 'n': + result += "\n" + mode = 0 + case '\'': + result += "'" + mode = 0 + case 'r': + result += "\r" + mode = 0 + case 't': + result += "\t" + mode = 0 + case '\\': + result += "\\" + mode = 0 + case 'u': + mode = 'u' + case 'U': + mode = 'U' + default: + return token{}, NewEscapeError(r) + } + } else if mode == 'u' { + ucode += string(rune(r)) + if len(ucode) == 4 { + mode = 0 + char, err := parseUnicode(ucode) + ucode = "" + if err != nil { + return token{}, err + } + result += char + } + } else if mode == 'U' { + ucode += string(rune(r)) + if len(ucode) == 8 { + mode = 0 + char, err := parseUnicode(ucode) + ucode = "" + if err != nil { + return token{}, err + } + result += char + } + } + } + t.t = result + return t, nil +} + +func parseUnicode(ucode string) (string, error) { + var ( + b []byte + r rune + ) + codepoint, err := strconv.ParseInt(ucode, 16, 64) + if err != nil { + return "", err + } + switch { + case codepoint < 0x7f: + b = []byte{byte(codepoint)} + // todo check r, s for error + r, _ = utf8.DecodeRune(b) + case codepoint < 0x7ff: + b = []byte{ + byte((codepoint>>6)&0b00011111 | 0b11000000), + byte(codepoint&0b00111111 | 0b10000000), + } + r, _ = utf8.DecodeRune(b) + case codepoint < 0xffff: + b = []byte{ + byte((codepoint>>12)&0b00001111 | 0b11100000), + byte((codepoint>>6)&0b00111111 | 0b10000000), + byte(codepoint&0b00111111 | 0b10000000), + } + r, _ = utf8.DecodeRune(b) + case codepoint < 0x1fffff: + b = []byte{ + byte((codepoint>>18)&0b00000111 | 0b11110000), + byte((codepoint>>12)&0b00111111 | 0b10000000), + byte((codepoint>>6)&0b00111111 | 0b10000000), + byte(codepoint&0b00111111 | 0b10000000), + } + r, _ = utf8.DecodeRune(b) + default: + return "", InvalidCodepointError{ucode} + } + return string(r), nil +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/struct.go b/encoder/vendor/apiote.xyz/p/go-dirty/struct.go new file mode 100644 index 0000000000000000000000000000000000000000..661ba1d3117d22586eed1ed33588f01b8d6593ce --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/struct.go @@ -0,0 +1,202 @@ +package dirty + +import ( + "fmt" + "reflect" + "unicode" +) + +func getStructPair(e Element) Array { + if e.getType() != ElemArray && len(e.(Array)) != 2 { + // todo error: not a pair + fmt.Println("not a pair") + return nil + } + return e.(Array) +} + +func getStructFieldName(pair Array) string { + k := reflect.TypeOf(pair[0]).Kind() + if k != reflect.String { + // todo error: name not string + fmt.Println("name not string") + return "" + } + fieldName := string(pair[0].(String)) + runes := []rune(fieldName) + runes[0] = unicode.ToUpper(runes[0]) + fieldName = string(runes) + return fieldName +} + +func getStructMapKey(pair Array, mk reflect.Kind) reflect.Value { + sk := reflect.ValueOf(pair[0]).Type().String() + if (sk == "dirty.String" && mk != reflect.String) || + (sk == "dirty.Int" && mk != reflect.Int && mk != reflect.Int8 && + mk != reflect.Int16 && mk != reflect.Int32 && mk != reflect.Int64 && + mk != reflect.Uint && mk != reflect.Uint8 && + mk != reflect.Uint16 && mk != reflect.Uint32 && mk != reflect.Uint64) || + (sk == "dirty.Const" && mk != reflect.Bool) /*test sk ==dirty.Const but not dirty::Bool */ { + // todo error + fmt.Printf("pair[0] (%v) not map key (%v)\n", sk, mk) + return reflect.ValueOf(nil) + } + switch mk { + case reflect.String: + return reflect.ValueOf(string(pair[0].(String))) + case reflect.Bool: + return reflect.ValueOf(pair[0].(Const).Bool()) + case reflect.Uint: + return reflect.ValueOf(uint(pair[0].(Int))) + case reflect.Uint8: + return reflect.ValueOf(uint8(pair[0].(Int))) + case reflect.Uint16: + return reflect.ValueOf(uint16(pair[0].(Int))) + case reflect.Uint32: + return reflect.ValueOf(uint32(pair[0].(Int))) + case reflect.Uint64: + return reflect.ValueOf(uint64(pair[0].(Int))) + case reflect.Int: + return reflect.ValueOf(int(pair[0].(Int))) + case reflect.Int8: + return reflect.ValueOf(int8(pair[0].(Int))) + case reflect.Int16: + return reflect.ValueOf(int16(pair[0].(Int))) + case reflect.Int32: + return reflect.ValueOf(int32(pair[0].(Int))) + case reflect.Int64: + return reflect.ValueOf(int64(pair[0].(Int))) + default: + return reflect.ValueOf(nil) + } +} + +func setStructValue(value Element, f reflect.Value) error { + switch value.getType() { + case ElemArray: + err := convertStruct(value.(Array), f) + if err != nil { + return err + } + case ElemConst: + if value == NULL && f.Kind() == reflect.Ptr { + // do nothing; default value is nil + } else if (value == TRUE || value == FALSE) && f.Kind() == reflect.Bool { + f.SetBool(value.(Const).Bool()) + } else { + // todo error: type mismatch + fmt.Println("type mismatch") + return nil + } + case ElemFloat: + if f.Kind() == reflect.Float64 || f.Kind() == reflect.Float32 { + f.SetFloat(float64(value.(Float))) + } else { + // todo error: type mismatch + fmt.Println("type mismatch") + return nil + } + case ElemInt: + if f.Kind() == reflect.Int || f.Kind() == reflect.Int8 || f.Kind() == reflect.Int16 || f.Kind() == reflect.Int32 || f.Kind() == reflect.Int64 { + f.SetInt(int64(value.(Int))) + } else { + // todo error: type mismatch + fmt.Println("type mismatch") + return nil + } + case ElemString: + if f.Kind() == reflect.String { + f.SetString(string(value.(String))) + } else { + // todo error: type mismatch + fmt.Println("type mismatch") + return nil + } + default: + // todo error: unknown type + fmt.Println("unknown type") + return nil + } + return nil +} + +func convertStruct(array Array, s reflect.Value) error { + kind := s.Kind() + if kind == reflect.Struct { + for _, e := range array { + pair := getStructPair(e) + fieldName := getStructFieldName(pair) + + f := s.FieldByName(fieldName) + if !f.IsValid() { + // todo error no such field + fmt.Println("no such field", fieldName) + return nil + } + if f.Kind() == reflect.Ptr && pair[1] != NULL { + f.Set(reflect.New(f.Type().Elem())) + f = f.Elem() + } + setStructValue(pair[1], f) + } + //fmt.Printf("%+v\n", s) + return nil + } + if kind == reflect.Slice { + elemType := s.Type().Elem() + if s.Len() != 0 { + // todo error slice not empty + fmt.Println("slice len != 0") + return nil + } + capacity := s.Cap() + s.SetLen(capacity) + s2 := s + for i, e := range array { + if i < capacity { + f := s2.Index(i) + setStructValue(e, f) + } else { + f := reflect.New(elemType).Elem() + setStructValue(e, f) + s2 = reflect.Append(s2, f) + } + } + s.Set(s2) + //fmt.Printf("%+v\n", s) + return nil + } + if kind == reflect.Array { + if s.Len() != len(array) { + // todo error array len not Array len + fmt.Println("array len not length of Array") + return nil + } + for i, e := range array { + f := s.Index(i) + setStructValue(e, f) + } + //fmt.Printf("%+v\n", s) + return nil + } + if kind == reflect.Map { + keyType := s.Type().Key() + keyKind := keyType.Kind() + valueType := s.Type().Elem() + for _, e := range array { + pair := getStructPair(e) + k := getStructMapKey(pair, keyKind) + v := reflect.New(valueType).Elem() + setStructValue(pair[1], v) + if s.IsNil() { + var mapType = reflect.MapOf(keyType, valueType) + s.Set(reflect.MakeMapWithSize(mapType, 0)) + } + s.SetMapIndex(k, v) + } + //fmt.Printf("%+v\n", s) + return nil + } + //fmt.Println(kind) + return nil +} diff --git a/encoder/vendor/apiote.xyz/p/go-dirty/tokeniser.go b/encoder/vendor/apiote.xyz/p/go-dirty/tokeniser.go new file mode 100644 index 0000000000000000000000000000000000000000..30b8c54627e720b2c99febbc9eeb96623d89a913 --- /dev/null +++ b/encoder/vendor/apiote.xyz/p/go-dirty/tokeniser.go @@ -0,0 +1,270 @@ +package dirty + +import ( + "bufio" + "fmt" + "io" +) + +// todo use reader.Peek() +var skipped rune = 0 + +type tokenType int + +const ( + UNKNOWN tokenType = iota + LBRACKET + RBRACKET + STRING + STRING_RAW + NUMBER + FLOAT + CONST + COMMENT + EOF +) + +type token struct { + ttype tokenType + t string + i *int64 + f *float64 +} + +func nextToken(reader *bufio.Reader) (token, error) { + t, finished, e := nextToken_initial(reader) + if finished || e != nil { + return t, e + } + t, e = nextToken_rest(reader, t) + return t, e +} +func nextToken_initial(reader *bufio.Reader) (token, bool, error) { + var ( + r rune = 0 + err error = nil + t token + ) + +initialTokenLoop: + for { + if skipped != 0 { + r = skipped + skipped = 0 + } else { + r, _, err = reader.ReadRune() + } + //debugf("%c\n", r) + if err != nil { + if err == io.EOF { + t := token{ttype: EOF} + return t, true, nil + } + return token{}, true, fmt.Errorf("while reading: %w", err) + } + switch { + case r == '(': + return token{ttype: LBRACKET}, true, nil + case r == ')': + return token{ttype: RBRACKET}, true, nil + case r == '#': + t = token{ttype: COMMENT} + break initialTokenLoop + case r == '`': + t = token{ttype: STRING_RAW} + break initialTokenLoop + case r == '\'': + t = token{ttype: STRING} + break initialTokenLoop + case r == 't': + t = token{ttype: CONST, t: "t"} + break initialTokenLoop + case r == 'f': + t = token{ttype: CONST, t: "f"} + break initialTokenLoop + case r == 'n': + t = token{ttype: CONST, t: "n"} + break initialTokenLoop + case in(r, []rune{'1', '2', '3', '4', '5', '6', '7', '8', '9', '↊', '↋', '-', '.', '·', ','}): + t = token{ttype: NUMBER, t: string(r)} + break initialTokenLoop + case r == '0': + r, _, err = reader.ReadRune() + //debugf("%c\n", r) + if err != nil { + if err == io.EOF { + t := token{ttype: EOF} + return t, true, nil + } + return token{}, true, fmt.Errorf("while reading: %w", err) + } + switch r { + case 'b': + t = token{ttype: NUMBER, t: "0b"} + break initialTokenLoop + case 'o': + t = token{ttype: NUMBER, t: "0o"} + break initialTokenLoop + case 'x': + t = token{ttype: NUMBER, t: "0x"} + break initialTokenLoop + default: + skipped = r + var zero int64 = 0 + return token{ttype: NUMBER, i: &zero}, true, nil + } + case in(r, []rune{' ', '\t', '\n', '\r'}): + continue + default: + return token{}, true, nil + } + } + return t, false, err +} + +func nextToken_rest(reader *bufio.Reader, t token) (token, error) { + var ( + r rune + err error = nil + escaping bool = false + stringRawIndent string = "" + stringRawIndentSkip string = "" + stringRawState int = 0 // todo enum + ) + +tokenLoop: + for { + if skipped != 0 { + r = skipped + skipped = 0 + } else { + r, _, err = reader.ReadRune() + } + //debugf("%c\n", r) + // todo line, column + if err != nil { + if err == io.EOF { + if t.ttype == STRING || t.ttype == STRING_RAW { + return token{}, NewUnterminatedError("string", t.t) + } else { + return token{ttype: EOF}, nil + } + } + return token{}, fmt.Errorf("while reading: %w", err) + } + + switch t.ttype { + case COMMENT: + if r != '\n' { + t.t += string(r) + } else { + break tokenLoop + } + case STRING: + if !escaping && r == '\'' { + t, err = parseString(t) + if err != nil { + return token{}, err + } + break tokenLoop + } else if r == '\n' { + return token{}, NewUnterminatedError("string", t.t) + } else { + t.t += string(r) + } + if escaping { + escaping = false + } else if r == '\\' { + escaping = true + } + case STRING_RAW: + if stringRawState == 0 { + if r != '\n' { + return token{}, NewRawStringError("missing new line after opening `") + } else { + stringRawState = 1 + continue + } + } + if stringRawState == 1 { + if r == ' ' || r == '\t' { + stringRawIndent += string(r) + } else { + stringRawState = 2 + t.t += string(r) + } + continue + } + if stringRawState == 2 { + // fixme assumes lines ending with \n; get to end of line + if r == '\n' { + stringRawState = 3 + stringRawIndentSkip = "" + } + t.t += string(r) + continue + } + if stringRawState == 3 { + if len(stringRawIndentSkip) == 0 && r == '`' { + break tokenLoop + } + if len(stringRawIndentSkip) < len(stringRawIndent) { + stringRawIndentSkip += string(r) + } else { + if stringRawIndent != stringRawIndentSkip { + // todo convert whitespace to escape codes + return token{}, NewRawStringError("Indent ‘" + stringRawIndent + "’ does not begin with ‘" + stringRawIndentSkip + "’") + } + skipped = r + stringRawState = 2 + } + } + case CONST: + if t.t[0] == 't' && in(r, []rune{'r', 'u', 'e'}) && len(t.t) < 4 { + t.t += string(r) + continue + } + if t.t[0] == 'f' && in(r, []rune{'a', 'l', 's', 'e'}) && len(t.t) < 5 { + t.t += string(r) + continue + } + if in(r, []rune{'u', 'l'}) && len(t.t) < 4 { + t.t += string(r) + continue + } + skipped = r + t, err = parseConst(t) + break tokenLoop + case NUMBER: + if t.t[0] == '0' && t.t[1] == 'b' && in(r, []rune{'0', '1', ','}) { + t.t += string(r) + continue + } + if t.t[0] == '0' && t.t[1] == 'o' && in(r, []rune{'0', '1', '2', '3', '4', '5', '6', '7'}) { + t.t += string(r) + continue + } + if t.t[0] == '0' && t.t[1] == 'x' && in(r, []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'}) { + t.t += string(r) + continue + } + if in(r, []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '↊', '↋', ',', '.', '·', 'e', '-'}) { + t.t += string(r) + continue + } + skipped = r + t, err = parseNumber(t) // todo errors that are not CommaError <- NumberError + break tokenLoop + } + } + return t, err +} + +func in(c rune, expected []rune) bool { + for _, e := range expected { + if c == e { + return true + } + } + return false +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.build.yml b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.build.yml new file mode 100644 index 0000000000000000000000000000000000000000..deb41fba899c2f8289b8d3bdbff9c1478c41703b --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.build.yml @@ -0,0 +1,12 @@ +image: alpine/edge +packages: +- go +sources: +- https://git.sr.ht/~sircmpwn/go-bare +tasks: +- gen: | + cd go-bare + go generate ./... +- test: | + cd go-bare + go test ./... diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.gitignore b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4a99827bd09c3743a43edc030083daf71aea8afa --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/.gitignore @@ -0,0 +1,3 @@ +*.test +*.prof +*.log \ No newline at end of file diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/LICENSE b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..39354f5f05c4ebe0c4214d6ecbd98ac4a130ca88 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/LICENSE @@ -0,0 +1,13 @@ +Copyright 2020 Drew DeVault + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/README.md b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7739ac00fbc55fb4afa7f6532ace925180a97752 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/README.md @@ -0,0 +1,130 @@ +# go-bare [![godocs.io](https://godocs.io/git.sr.ht/~sircmpwn/go-bare?status.svg)](https://godocs.io/git.sr.ht/~sircmpwn/go-bare) [![builds.sr.ht status](https://builds.sr.ht/~sircmpwn/go-bare.svg)](https://builds.sr.ht/~sircmpwn/go-bare?) + +An implementation of the [BARE](https://baremessages.org) message format +for Go. + +**Status** + +This mostly works, but you may run into some edge cases with union types. + +## Code generation + +An example is provided in the `examples` directory. Here is a basic +introduction: + +``` +$ cat schema.bare +type Address { + address: [4]string + city: string + state: string + country: string +} +$ go run git.sr.ht/~sircmpwn/go-bare/cmd/gen -p models schema.bare models/gen.go +``` + +Then you can write something like the following: + +```go +import "models" + +/* ... */ + +bytes := []byte{ /* ... */ } +var addr Address +err := addr.Decode(bytes) +``` + +You can also add custom types and skip generating them by passing the `-s +TypeName` flag to gen, then providing your own implementation. For example, to +rig up time.Time with a custom "Time" BARE type, add this to your BARE schema: + +``` +type Time string +``` + +Then pass `-s Time` to gen, and provide your own implementation of Time in the +same package. See `examples/time.go` for an example of such an implementation. + +## Marshal usage + +For many use-cases, it may be more convenient to write your types manually and +use Marshal and Unmarshal directly. If you choose this approach, you may also +use `git.sr.ht/~sircmpwn/go-bare/schema.SchemaFor` to generate a BARE schema +language document describing your structs. + +```go +package main + +import ( + "fmt" + "git.sr.ht/~sircmpwn/go-bare" +) + +// type Coordinates { +// x: int +// y: int +// z: int +// q: optional<int> +// } +type Coordinates struct { + X uint + Y uint + Z uint + Q *uint +} + +func main() { + var coords Coordinates + payload := []byte{0x01, 0x02, 0x03, 0x01, 0x04} + err := bare.Unmarshal(payload, &coords) + if err != nil { + panic(err) + } + fmt.Printf("coords: %d, %d, %d (%d)\n", + coords.X, coords.Y, coords.Z, *coords.Q) /* coords: 1, 2, 3 (4) */ +} +``` + +### Unions + +To use union types, you need to define an interface to represent the union of +possible values, and this interface needs to implement `bare.Union`: + +```go +type Person interface { + Union +} +``` + +Then, for each possible union type, implement the interface: + +```go +type Employee struct { /* ... */ } +func (e Employee) IsUnion() {} + +type Customer struct { /* ... */ } +func (c Customer) IsUnion() {} +``` + +The IsUnion function is necessary to make the type compatible with the Union +interface. Then, to marshal and unmarshal using this union type, you need to +tell go-bare about your union: + +```go +func init() { + // The first argument is a pointer of the union interface, and the + // subsequent arguments are values of each possible subtype, in ascending + // order of union tag: + bare.RegisterUnion((*Person)(nil)). + Member(*new(Employee), 0). + Member(*new(Customer), 1) +} +``` + +This is all done for you if you use code generation. + +## Contributing, getting help + +Send patches and questions to +[~sircmpwn/public-inbox@lists.sr.ht](mailto:~sircmpwn/public-inbox@lists.sr.ht) diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/errors.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/errors.go new file mode 100644 index 0000000000000000000000000000000000000000..f2c406c189e1db325dc0eb7c922e601af5ba0bc6 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/errors.go @@ -0,0 +1,17 @@ +package bare + +import ( + "errors" + "fmt" + "reflect" +) + +var ErrInvalidStr = errors.New("String contains invalid UTF-8 sequences") + +type UnsupportedTypeError struct { + Type reflect.Type +} + +func (e *UnsupportedTypeError) Error() string { + return fmt.Sprintf("Unsupported type for marshaling: %s\n", e.Type.String()) +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/limit.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/limit.go new file mode 100644 index 0000000000000000000000000000000000000000..6024745f3f067acb124a7e147ad6beffbb011ad2 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/limit.go @@ -0,0 +1,55 @@ +package bare + +import ( + "errors" + "io" +) + +var ( + maxUnmarshalBytes uint64 = 1024 * 1024 * 32 /* 32 MiB */ + maxArrayLength uint64 = 1024 * 4 /* 4096 elements */ + maxMapSize uint64 = 1024 +) + +// MaxUnmarshalBytes sets the maximum size of a message decoded by unmarshal. +// By default, this is set to 32 MiB. +func MaxUnmarshalBytes(bytes uint64) { + maxUnmarshalBytes = bytes +} + +// MaxArrayLength sets maximum number of elements in array. Defaults to 4096 elements +func MaxArrayLength(length uint64) { + maxArrayLength = length +} + +// MaxMapSize sets maximum size of map. Defaults to 1024 key/value pairs +func MaxMapSize(size uint64) { + maxMapSize = size +} + +// Use MaxUnmarshalBytes to prevent this error from occuring on messages which +// are large by design. +var ErrLimitExceeded = errors.New("Maximum message size exceeded") + +// Identical to io.LimitedReader, except it returns our custom error instead of +// EOF if the limit is reached. +type limitedReader struct { + R io.Reader + N uint64 +} + +func (l *limitedReader) Read(p []byte) (n int, err error) { + if l.N <= 0 { + return 0, ErrLimitExceeded + } + if uint64(len(p)) > l.N { + p = p[0:l.N] + } + n, err = l.R.Read(p) + l.N -= uint64(n) + return +} + +func newLimitedReader(r io.Reader) *limitedReader { + return &limitedReader{r, maxUnmarshalBytes} +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/marshal.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/marshal.go new file mode 100644 index 0000000000000000000000000000000000000000..03467700bc73222971f86f5ab2fac85654f243a7 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/marshal.go @@ -0,0 +1,308 @@ +package bare + +import ( + "bytes" + "errors" + "fmt" + "reflect" + "sync" +) + +// A type which implements this interface will be responsible for marshaling +// itself when encountered. +type Marshalable interface { + Marshal(w *Writer) error +} + +var encoderBufferPool = sync.Pool{ + New: func() interface{} { + buf := &bytes.Buffer{} + buf.Grow(32) + return buf + }, +} + +// Marshals a value (val, which must be a pointer) into a BARE message. +// +// The encoding of each struct field can be customized by the format string +// stored under the "bare" key in the struct field's tag. +// +// As a special case, if the field tag is "-", the field is always omitted. +func Marshal(val interface{}) ([]byte, error) { + // reuse buffers from previous serializations + b := encoderBufferPool.Get().(*bytes.Buffer) + defer func() { + b.Reset() + encoderBufferPool.Put(b) + }() + + w := NewWriter(b) + err := MarshalWriter(w, val) + + msg := make([]byte, b.Len()) + copy(msg, b.Bytes()) + + return msg, err +} + +// Marshals a value (val, which must be a pointer) into a BARE message and +// writes it to a Writer. See Marshal for details. +func MarshalWriter(w *Writer, val interface{}) error { + t := reflect.TypeOf(val) + v := reflect.ValueOf(val) + if t.Kind() != reflect.Ptr { + return errors.New("Expected val to be pointer type") + } + + return getEncoder(t.Elem())(w, v.Elem()) +} + +type encodeFunc func(w *Writer, v reflect.Value) error + +var encodeFuncCache sync.Map // map[reflect.Type]encodeFunc + +// get decoder from cache +func getEncoder(t reflect.Type) encodeFunc { + if f, ok := encodeFuncCache.Load(t); ok { + return f.(encodeFunc) + } + + f := encoderFunc(t) + encodeFuncCache.Store(t, f) + return f +} + +var marshalableInterface = reflect.TypeOf((*Unmarshalable)(nil)).Elem() + +func encoderFunc(t reflect.Type) encodeFunc { + if reflect.PtrTo(t).Implements(marshalableInterface) { + return func(w *Writer, v reflect.Value) error { + uv := v.Addr().Interface().(Marshalable) + return uv.Marshal(w) + } + } + + if t.Kind() == reflect.Interface && t.Implements(unionInterface) { + return encodeUnion(t) + } + + switch t.Kind() { + case reflect.Ptr: + return encodeOptional(t.Elem()) + case reflect.Struct: + return encodeStruct(t) + case reflect.Array: + return encodeArray(t) + case reflect.Slice: + return encodeSlice(t) + case reflect.Map: + return encodeMap(t) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return encodeUint + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return encodeInt + case reflect.Float32, reflect.Float64: + return encodeFloat + case reflect.Bool: + return encodeBool + case reflect.String: + return encodeString + } + + return func(w *Writer, v reflect.Value) error { + return &UnsupportedTypeError{v.Type()} + } +} + +func encodeOptional(t reflect.Type) encodeFunc { + return func(w *Writer, v reflect.Value) error { + if v.IsNil() { + return w.WriteBool(false) + } + + if err := w.WriteBool(true); err != nil { + return err + } + + return getEncoder(t)(w, v.Elem()) + } +} + +func encodeStruct(t reflect.Type) encodeFunc { + n := t.NumField() + encoders := make([]encodeFunc, n) + for i := 0; i < n; i++ { + field := t.Field(i) + if field.Tag.Get("bare") == "-" { + continue + } + encoders[i] = getEncoder(field.Type) + } + + return func(w *Writer, v reflect.Value) error { + for i := 0; i < n; i++ { + if encoders[i] == nil { + continue + } + err := encoders[i](w, v.Field(i)) + if err != nil { + return err + } + } + return nil + } +} + +func encodeArray(t reflect.Type) encodeFunc { + f := getEncoder(t.Elem()) + len := t.Len() + + return func(w *Writer, v reflect.Value) error { + for i := 0; i < len; i++ { + if err := f(w, v.Index(i)); err != nil { + return err + } + } + return nil + } +} + +func encodeSlice(t reflect.Type) encodeFunc { + elem := t.Elem() + f := getEncoder(elem) + + return func(w *Writer, v reflect.Value) error { + if err := w.WriteUint(uint64(v.Len())); err != nil { + return err + } + + for i := 0; i < v.Len(); i++ { + if err := f(w, v.Index(i)); err != nil { + return err + } + } + return nil + } +} + +func encodeMap(t reflect.Type) encodeFunc { + keyType := t.Key() + keyf := getEncoder(keyType) + + valueType := t.Elem() + valf := getEncoder(valueType) + + return func(w *Writer, v reflect.Value) error { + if err := w.WriteUint(uint64(v.Len())); err != nil { + return err + } + + iter := v.MapRange() + for iter.Next() { + if err := keyf(w, iter.Key()); err != nil { + return err + } + if err := valf(w, iter.Value()); err != nil { + return err + } + } + return nil + } +} + +func encodeUnion(t reflect.Type) encodeFunc { + ut, ok := unionRegistry[t] + if !ok { + return func(w *Writer, v reflect.Value) error { + return fmt.Errorf("Union type %s is not registered", t.Name()) + } + } + + encoders := make(map[uint64]encodeFunc) + for tag, t := range ut.types { + encoders[tag] = getEncoder(t) + } + + return func(w *Writer, v reflect.Value) error { + t := v.Elem().Type() + if t.Kind() == reflect.Ptr { + // If T is a valid union value type, *T is valid too. + t = t.Elem() + v = v.Elem() + } + tag, ok := ut.tags[t] + if !ok { + return fmt.Errorf("Invalid union value: %s", v.Elem().String()) + } + + if err := w.WriteUint(tag); err != nil { + return err + } + + return encoders[tag](w, v.Elem()) + } +} + +func encodeUint(w *Writer, v reflect.Value) error { + switch getIntKind(v.Type()) { + case reflect.Uint: + return w.WriteUint(v.Uint()) + + case reflect.Uint8: + return w.WriteU8(uint8(v.Uint())) + + case reflect.Uint16: + return w.WriteU16(uint16(v.Uint())) + + case reflect.Uint32: + return w.WriteU32(uint32(v.Uint())) + + case reflect.Uint64: + return w.WriteU64(uint64(v.Uint())) + } + + panic("not uint") +} + +func encodeInt(w *Writer, v reflect.Value) error { + switch getIntKind(v.Type()) { + case reflect.Int: + return w.WriteInt(v.Int()) + + case reflect.Int8: + return w.WriteI8(int8(v.Int())) + + case reflect.Int16: + return w.WriteI16(int16(v.Int())) + + case reflect.Int32: + return w.WriteI32(int32(v.Int())) + + case reflect.Int64: + return w.WriteI64(int64(v.Int())) + } + + panic("not int") +} + +func encodeFloat(w *Writer, v reflect.Value) error { + switch v.Type().Kind() { + case reflect.Float32: + return w.WriteF32(float32(v.Float())) + case reflect.Float64: + return w.WriteF64(v.Float()) + } + + panic("not float") +} + +func encodeBool(w *Writer, v reflect.Value) error { + return w.WriteBool(v.Bool()) +} + +func encodeString(w *Writer, v reflect.Value) error { + if v.Kind() != reflect.String { + panic("not string") + } + return w.WriteString(v.String()) +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/package.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/package.go new file mode 100644 index 0000000000000000000000000000000000000000..3851c539124d15a0a94e5677cf3c056c090b7652 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/package.go @@ -0,0 +1,8 @@ +// An implementation of the BARE message format for Go. +// +// https://git.sr.ht/~sircmpwn/bare +// +// See the git repository for usage examples: +// +// https://git.sr.ht/~sircmpwn/go-bare +package bare diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/reader.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/reader.go new file mode 100644 index 0000000000000000000000000000000000000000..6186373926c697b4efaa227789e3f582839ea4be --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/reader.go @@ -0,0 +1,188 @@ +package bare + +import ( + "encoding/binary" + "fmt" + "io" + "math" + "unicode/utf8" +) + +type byteReader interface { + io.Reader + io.ByteReader +} + +// A Reader for BARE primitive types. +type Reader struct { + base byteReader + scratch [8]byte +} + +type simpleByteReader struct { + io.Reader + scratch [1]byte +} + +func (r simpleByteReader) ReadByte() (byte, error) { + // using reference type here saves us allocations + _, err := r.Read(r.scratch[:]) + return r.scratch[0], err +} + +// Returns a new BARE primitive reader wrapping the given io.Reader. +func NewReader(base io.Reader) *Reader { + br, ok := base.(byteReader) + if !ok { + br = simpleByteReader{Reader: base} + } + return &Reader{base: br} +} + +func (r *Reader) ReadUint() (uint64, error) { + x, err := binary.ReadUvarint(r.base) + if err != nil { + return x, err + } + return x, nil +} + +func (r *Reader) ReadU8() (uint8, error) { + return r.base.ReadByte() +} + +func (r *Reader) ReadU16() (uint16, error) { + var i uint16 + if _, err := io.ReadAtLeast(r.base, r.scratch[:2], 2); err != nil { + return i, err + } + return binary.LittleEndian.Uint16(r.scratch[:]), nil +} + +func (r *Reader) ReadU32() (uint32, error) { + var i uint32 + if _, err := io.ReadAtLeast(r.base, r.scratch[:4], 4); err != nil { + return i, err + } + return binary.LittleEndian.Uint32(r.scratch[:]), nil +} + +func (r *Reader) ReadU64() (uint64, error) { + var i uint64 + if _, err := io.ReadAtLeast(r.base, r.scratch[:8], 8); err != nil { + return i, err + } + return binary.LittleEndian.Uint64(r.scratch[:]), nil +} + +func (r *Reader) ReadInt() (int64, error) { + return binary.ReadVarint(r.base) +} + +func (r *Reader) ReadI8() (int8, error) { + b, err := r.base.ReadByte() + return int8(b), err +} + +func (r *Reader) ReadI16() (int16, error) { + var i int16 + if _, err := io.ReadAtLeast(r.base, r.scratch[:2], 2); err != nil { + return i, err + } + return int16(binary.LittleEndian.Uint16(r.scratch[:])), nil +} + +func (r *Reader) ReadI32() (int32, error) { + var i int32 + if _, err := io.ReadAtLeast(r.base, r.scratch[:4], 4); err != nil { + return i, err + } + return int32(binary.LittleEndian.Uint32(r.scratch[:])), nil +} + +func (r *Reader) ReadI64() (int64, error) { + var i int64 + if _, err := io.ReadAtLeast(r.base, r.scratch[:], 8); err != nil { + return i, err + } + return int64(binary.LittleEndian.Uint64(r.scratch[:])), nil +} + +func (r *Reader) ReadF32() (float32, error) { + u, err := r.ReadU32() + f := math.Float32frombits(u) + if math.IsNaN(float64(f)) { + return 0.0, fmt.Errorf("NaN is not permitted in BARE floats") + } + return f, err +} + +func (r *Reader) ReadF64() (float64, error) { + u, err := r.ReadU64() + f := math.Float64frombits(u) + if math.IsNaN(f) { + return 0.0, fmt.Errorf("NaN is not permitted in BARE floats") + } + return f, err +} + +func (r *Reader) ReadBool() (bool, error) { + b, err := r.ReadU8() + if err != nil { + return false, err + } + + if b > 1 { + return false, fmt.Errorf("Invalid bool value: %#x", b) + } + + return b == 1, nil +} + +func (r *Reader) ReadString() (string, error) { + buf, err := r.ReadData() + if err != nil { + return "", err + } + if !utf8.Valid(buf) { + return "", ErrInvalidStr + } + return string(buf), nil +} + +// Reads a fixed amount of arbitrary data, defined by the length of the slice. +func (r *Reader) ReadDataFixed(dest []byte) error { + var amt int = 0 + for amt < len(dest) { + n, err := r.base.Read(dest[amt:]) + if err != nil { + return err + } + amt += n + } + return nil +} + +// Reads arbitrary data whose length is read from the message. +func (r *Reader) ReadData() ([]byte, error) { + l, err := r.ReadUint() + if err != nil { + return nil, err + } + if l >= maxUnmarshalBytes { + return nil, ErrLimitExceeded + } + buf := make([]byte, l) + var amt uint64 = 0 + for amt < l { + n, err := r.base.Read(buf[amt:]) + amt += uint64(n) + if amt == l { + break + } + if err != nil { + return nil, err + } + } + return buf, nil +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unions.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unions.go new file mode 100644 index 0000000000000000000000000000000000000000..a9f624c73819455d1c73acf2e3efd4b04b42a347 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unions.go @@ -0,0 +1,76 @@ +package bare + +import ( + "fmt" + "reflect" +) + +// Any type which is a union member must implement this interface. You must +// also call RegisterUnion for go-bare to marshal or unmarshal messages which +// utilize your union type. +type Union interface { + IsUnion() +} + +type UnionTags struct { + iface reflect.Type + tags map[reflect.Type]uint64 + types map[uint64]reflect.Type +} + +var unionInterface = reflect.TypeOf((*Union)(nil)).Elem() +var unionRegistry map[reflect.Type]*UnionTags + +func init() { + unionRegistry = make(map[reflect.Type]*UnionTags) +} + +// Registers a union type in this context. Pass the union interface and the +// list of types associated with it, sorted ascending by their union tag. +func RegisterUnion(iface interface{}) *UnionTags { + ity := reflect.TypeOf(iface).Elem() + if _, ok := unionRegistry[ity]; ok { + panic(fmt.Errorf("Type %s has already been registered", ity.Name())) + } + + if !ity.Implements(reflect.TypeOf((*Union)(nil)).Elem()) { + panic(fmt.Errorf("Type %s does not implement bare.Union", ity.Name())) + } + + utypes := &UnionTags{ + iface: ity, + tags: make(map[reflect.Type]uint64), + types: make(map[uint64]reflect.Type), + } + unionRegistry[ity] = utypes + return utypes +} + +func (ut *UnionTags) Member(t interface{}, tag uint64) *UnionTags { + ty := reflect.TypeOf(t) + if !ty.AssignableTo(ut.iface) { + panic(fmt.Errorf("Type %s does not implement interface %s", + ty.Name(), ut.iface.Name())) + } + if _, ok := ut.tags[ty]; ok { + panic(fmt.Errorf("Type %s is already registered for union %s", + ty.Name(), ut.iface.Name())) + } + if _, ok := ut.types[tag]; ok { + panic(fmt.Errorf("Tag %d is already registered for union %s", + tag, ut.iface.Name())) + } + ut.tags[ty] = tag + ut.types[tag] = ty + return ut +} + +func (ut *UnionTags) TagFor(v interface{}) (uint64, bool) { + tag, ok := ut.tags[reflect.TypeOf(v)] + return tag, ok +} + +func (ut *UnionTags) TypeFor(tag uint64) (reflect.Type, bool) { + t, ok := ut.types[tag] + return t, ok +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unmarshal.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unmarshal.go new file mode 100644 index 0000000000000000000000000000000000000000..614cecaae2ea0a9d77c6aa2c8589362ea7f9de34 --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/unmarshal.go @@ -0,0 +1,359 @@ +package bare + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + "sync" +) + +// A type which implements this interface will be responsible for unmarshaling +// itself when encountered. +type Unmarshalable interface { + Unmarshal(r *Reader) error +} + +// Unmarshals a BARE message into val, which must be a pointer to a value of +// the message type. +func Unmarshal(data []byte, val interface{}) error { + b := bytes.NewReader(data) + r := NewReader(b) + return UnmarshalBareReader(r, val) +} + +// Unmarshals a BARE message into value (val, which must be a pointer), from a +// reader. See Unmarshal for details. +func UnmarshalReader(r io.Reader, val interface{}) error { + r = newLimitedReader(r) + return UnmarshalBareReader(NewReader(r), val) +} + +type decodeFunc func(r *Reader, v reflect.Value) error + +var decodeFuncCache sync.Map // map[reflect.Type]decodeFunc + +func UnmarshalBareReader(r *Reader, val interface{}) error { + t := reflect.TypeOf(val) + v := reflect.ValueOf(val) + if t.Kind() != reflect.Ptr { + return errors.New("Expected val to be pointer type") + } + + return getDecoder(t.Elem())(r, v.Elem()) +} + +// get decoder from cache +func getDecoder(t reflect.Type) decodeFunc { + if f, ok := decodeFuncCache.Load(t); ok { + return f.(decodeFunc) + } + + f := decoderFunc(t) + decodeFuncCache.Store(t, f) + return f +} + +var unmarshalableInterface = reflect.TypeOf((*Unmarshalable)(nil)).Elem() + +func decoderFunc(t reflect.Type) decodeFunc { + if reflect.PtrTo(t).Implements(unmarshalableInterface) { + return func(r *Reader, v reflect.Value) error { + uv := v.Addr().Interface().(Unmarshalable) + return uv.Unmarshal(r) + } + } + + if t.Kind() == reflect.Interface && t.Implements(unionInterface) { + return decodeUnion(t) + } + + switch t.Kind() { + case reflect.Ptr: + return decodeOptional(t.Elem()) + case reflect.Struct: + return decodeStruct(t) + case reflect.Array: + return decodeArray(t) + case reflect.Slice: + return decodeSlice(t) + case reflect.Map: + return decodeMap(t) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return decodeUint + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return decodeInt + case reflect.Float32, reflect.Float64: + return decodeFloat + case reflect.Bool: + return decodeBool + case reflect.String: + return decodeString + } + + return func(r *Reader, v reflect.Value) error { + return &UnsupportedTypeError{v.Type()} + } +} + +func decodeOptional(t reflect.Type) decodeFunc { + return func(r *Reader, v reflect.Value) error { + s, err := r.ReadU8() + if err != nil { + return err + } + + if s > 1 { + return fmt.Errorf("Invalid optional value: %#x", s) + } + + if s == 0 { + return nil + } + + v.Set(reflect.New(t)) + return getDecoder(t)(r, v.Elem()) + } +} + +func decodeStruct(t reflect.Type) decodeFunc { + n := t.NumField() + decoders := make([]decodeFunc, n) + for i := 0; i < n; i++ { + field := t.Field(i) + if field.Tag.Get("bare") == "-" { + continue + } + decoders[i] = getDecoder(field.Type) + } + + return func(r *Reader, v reflect.Value) error { + for i := 0; i < n; i++ { + if decoders[i] == nil { + continue + } + err := decoders[i](r, v.Field(i)) + if err != nil { + return err + } + } + return nil + } +} + +func decodeArray(t reflect.Type) decodeFunc { + f := getDecoder(t.Elem()) + len := t.Len() + + return func(r *Reader, v reflect.Value) error { + for i := 0; i < len; i++ { + err := f(r, v.Index(i)) + if err != nil { + return err + } + } + return nil + } +} + +func decodeSlice(t reflect.Type) decodeFunc { + elem := t.Elem() + f := getDecoder(elem) + + return func(r *Reader, v reflect.Value) error { + len, err := r.ReadUint() + if err != nil { + return err + } + + if len > maxArrayLength { + return fmt.Errorf("Array length %d exceeds configured limit of %d", len, maxArrayLength) + } + + v.Set(reflect.MakeSlice(t, int(len), int(len))) + + for i := 0; i < int(len); i++ { + if err := f(r, v.Index(i)); err != nil { + return err + } + } + return nil + } +} + +func decodeMap(t reflect.Type) decodeFunc { + keyType := t.Key() + keyf := getDecoder(keyType) + + valueType := t.Elem() + valf := getDecoder(valueType) + + return func(r *Reader, v reflect.Value) error { + size, err := r.ReadUint() + if err != nil { + return err + } + + if size > maxMapSize { + return fmt.Errorf("Map size %d exceeds configured limit of %d", size, maxMapSize) + } + + v.Set(reflect.MakeMapWithSize(t, int(size))) + + key := reflect.New(keyType).Elem() + value := reflect.New(valueType).Elem() + + for i := uint64(0); i < size; i++ { + if err := keyf(r, key); err != nil { + return err + } + + if v.MapIndex(key).Kind() > reflect.Invalid { + return fmt.Errorf("Encountered duplicate map key: %v", key.Interface()) + } + + if err := valf(r, value); err != nil { + return err + } + + v.SetMapIndex(key, value) + } + return nil + } +} + +func decodeUnion(t reflect.Type) decodeFunc { + ut, ok := unionRegistry[t] + if !ok { + return func(r *Reader, v reflect.Value) error { + return fmt.Errorf("Union type %s is not registered", t.Name()) + } + } + + decoders := make(map[uint64]decodeFunc) + for tag, t := range ut.types { + t := t + f := getDecoder(t) + + decoders[tag] = func(r *Reader, v reflect.Value) error { + nv := reflect.New(t) + if err := f(r, nv.Elem()); err != nil { + return err + } + + v.Set(nv) + return nil + } + } + + return func(r *Reader, v reflect.Value) error { + tag, err := r.ReadUint() + if err != nil { + return err + } + + if f, ok := decoders[tag]; ok { + return f(r, v) + } + + return fmt.Errorf("Invalid union tag %d for type %s", tag, t.Name()) + } +} + +func decodeUint(r *Reader, v reflect.Value) error { + var err error + switch getIntKind(v.Type()) { + case reflect.Uint: + var u uint64 + u, err = r.ReadUint() + v.SetUint(u) + + case reflect.Uint8: + var u uint8 + u, err = r.ReadU8() + v.SetUint(uint64(u)) + + case reflect.Uint16: + var u uint16 + u, err = r.ReadU16() + v.SetUint(uint64(u)) + case reflect.Uint32: + var u uint32 + u, err = r.ReadU32() + v.SetUint(uint64(u)) + + case reflect.Uint64: + var u uint64 + u, err = r.ReadU64() + v.SetUint(uint64(u)) + + default: + panic("not an uint") + } + + return err +} + +func decodeInt(r *Reader, v reflect.Value) error { + var err error + switch getIntKind(v.Type()) { + case reflect.Int: + var i int64 + i, err = r.ReadInt() + v.SetInt(i) + + case reflect.Int8: + var i int8 + i, err = r.ReadI8() + v.SetInt(int64(i)) + + case reflect.Int16: + var i int16 + i, err = r.ReadI16() + v.SetInt(int64(i)) + case reflect.Int32: + var i int32 + i, err = r.ReadI32() + v.SetInt(int64(i)) + + case reflect.Int64: + var i int64 + i, err = r.ReadI64() + v.SetInt(int64(i)) + + default: + panic("not an int") + } + + return err +} + +func decodeFloat(r *Reader, v reflect.Value) error { + var err error + switch v.Type().Kind() { + case reflect.Float32: + var f float32 + f, err = r.ReadF32() + v.SetFloat(float64(f)) + case reflect.Float64: + var f float64 + f, err = r.ReadF64() + v.SetFloat(f) + default: + panic("not a float") + } + return err +} + +func decodeBool(r *Reader, v reflect.Value) error { + b, err := r.ReadBool() + v.SetBool(b) + return err +} + +func decodeString(r *Reader, v reflect.Value) error { + s, err := r.ReadString() + v.SetString(s) + return err +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/varint.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/varint.go new file mode 100644 index 0000000000000000000000000000000000000000..f5043fb63df96bdaa8b8f7b07dd767118210a86e --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/varint.go @@ -0,0 +1,27 @@ +package bare + +import ( + "reflect" +) + +// Int is a variable-length encoded signed integer. +type Int int64 + +// Uint is a variable-length encoded unsigned integer. +type Uint uint64 + +var ( + intType = reflect.TypeOf(Int(0)) + uintType = reflect.TypeOf(Uint(0)) +) + +func getIntKind(t reflect.Type) reflect.Kind { + switch t { + case intType: + return reflect.Int + case uintType: + return reflect.Uint + default: + return t.Kind() + } +} diff --git a/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/writer.go b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/writer.go new file mode 100644 index 0000000000000000000000000000000000000000..8c54441f25e68579f43160525bfbda20419ee2af --- /dev/null +++ b/encoder/vendor/git.sr.ht/~sircmpwn/go-bare/writer.go @@ -0,0 +1,116 @@ +package bare + +import ( + "encoding/binary" + "fmt" + "io" + "math" +) + +// A Writer for BARE primitive types. +type Writer struct { + base io.Writer + scratch [binary.MaxVarintLen64]byte +} + +// Returns a new BARE primitive writer wrapping the given io.Writer. +func NewWriter(base io.Writer) *Writer { + return &Writer{base: base} +} + +func (w *Writer) WriteUint(i uint64) error { + n := binary.PutUvarint(w.scratch[:], i) + _, err := w.base.Write(w.scratch[:n]) + return err +} + +func (w *Writer) WriteU8(i uint8) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteU16(i uint16) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteU32(i uint32) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteU64(i uint64) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteInt(i int64) error { + var buf [binary.MaxVarintLen64]byte + n := binary.PutVarint(buf[:], i) + _, err := w.base.Write(buf[:n]) + return err +} + +func (w *Writer) WriteI8(i int8) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteI16(i int16) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteI32(i int32) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteI64(i int64) error { + return binary.Write(w.base, binary.LittleEndian, i) +} + +func (w *Writer) WriteF32(f float32) error { + if math.IsNaN(float64(f)) { + return fmt.Errorf("NaN is not permitted in BARE floats") + } + return binary.Write(w.base, binary.LittleEndian, f) +} + +func (w *Writer) WriteF64(f float64) error { + if math.IsNaN(f) { + return fmt.Errorf("NaN is not permitted in BARE floats") + } + return binary.Write(w.base, binary.LittleEndian, f) +} + +func (w *Writer) WriteBool(b bool) error { + return binary.Write(w.base, binary.LittleEndian, b) +} + +func (w *Writer) WriteString(str string) error { + return w.WriteData([]byte(str)) +} + +// Writes a fixed amount of arbitrary data, defined by the length of the slice. +func (w *Writer) WriteDataFixed(data []byte) error { + var amt int = 0 + for amt < len(data) { + n, err := w.base.Write(data[amt:]) + if err != nil { + return err + } + amt += n + } + return nil +} + +// Writes arbitrary data whose length is encoded into the message. +func (w *Writer) WriteData(data []byte) error { + err := w.WriteUint(uint64(len(data))) + if err != nil { + return err + } + var amt int = 0 + for amt < len(data) { + n, err := w.base.Write(data[amt:]) + if err != nil { + return err + } + amt += n + } + return nil +} diff --git a/encoder/vendor/github.com/codahale/sss/.gitignore b/encoder/vendor/github.com/codahale/sss/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c56069fe260287c46fab3178e697b9c41b48ef60 --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/.gitignore @@ -0,0 +1 @@ +*.test \ No newline at end of file diff --git a/encoder/vendor/github.com/codahale/sss/.travis.yml b/encoder/vendor/github.com/codahale/sss/.travis.yml new file mode 100644 index 0000000000000000000000000000000000000000..46cc6e78c8a8bbf39fc4c5289e2063f62d800285 --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.3.3 +notifications: + # See http://about.travis-ci.org/docs/user/build-configuration/ to learn more + # about configuring notification recipients and more. + email: + recipients: + - coda.hale@gmail.com diff --git a/encoder/vendor/github.com/codahale/sss/LICENSE b/encoder/vendor/github.com/codahale/sss/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f9835c241fc479b1a3ca6e71bbb1f6305e7be0bc --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Coda Hale + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/encoder/vendor/github.com/codahale/sss/README.md b/encoder/vendor/github.com/codahale/sss/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f6590122f7e84468365d39b5deddbbbd63290a67 --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/README.md @@ -0,0 +1,11 @@ +# sss (Shamir's Secret Sharing) + +[![Build Status](https://travis-ci.org/codahale/sss.png?branch=master)](https://travis-ci.org/codahale/sss) + +A pure Go implementation of +[Shamir's Secret Sharing algorithm](http://en.wikipedia.org/wiki/Shamir's_Secret_Sharing) +over GF(2^8). + +Inspired by @hbs's [Python implementation](https://github.com/hbs/PySSSS). + +For documentation, check [godoc](http://godoc.org/github.com/codahale/sss). diff --git a/encoder/vendor/github.com/codahale/sss/gf256.go b/encoder/vendor/github.com/codahale/sss/gf256.go new file mode 100644 index 0000000000000000000000000000000000000000..bff81ae3cb4f563bd8e8bf7b118f852b14eca2ac --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/gf256.go @@ -0,0 +1,81 @@ +package sss + +func mul(e, a byte) byte { + if e == 0 || a == 0 { + return 0 + } + return exp[(int(log[e])+int(log[a]))%255] +} + +func div(e, a byte) byte { + if a == 0 { + panic("div by zero") + } + + if e == 0 { + return 0 + } + + p := (int(log[e]) - int(log[a])) % 255 + if p < 0 { + p += 255 + } + + return exp[p] +} + +const ( + fieldSize = 256 // 2^8 +) + +var ( + // 0x11b prime polynomial and 0x03 as generator + exp = [fieldSize]byte{ + 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, + 0xa1, 0xf8, 0x13, 0x35, 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, + 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, 0xe5, 0x34, 0x5c, 0xe4, + 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31, + 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, + 0xd3, 0x6e, 0xb2, 0xcd, 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, + 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, 0x83, 0x9e, 0xb9, 0xd0, + 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a, + 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, + 0xbb, 0xd6, 0x61, 0xa3, 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, + 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, 0xfb, 0x16, 0x3a, 0x4e, + 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41, + 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, + 0x9c, 0xbf, 0xda, 0x75, 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, + 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, 0x9b, 0xb6, 0xc1, 0x58, + 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54, + 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, + 0xb0, 0xcb, 0x46, 0xca, 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, + 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, 0x12, 0x36, 0x5a, 0xee, + 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17, + 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, + 0xc7, 0x52, 0xf6, 0x01, + } + log = [fieldSize]byte{ + 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, + 0x33, 0xee, 0xdf, 0x03, 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, + 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1, 0x7d, 0xc2, 0x1d, 0xb5, + 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78, + 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, + 0x35, 0x93, 0xda, 0x8e, 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, + 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38, 0x66, 0xdd, 0xfd, 0x30, + 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10, + 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, + 0xfa, 0x85, 0x3d, 0xba, 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, + 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57, 0xaf, 0x58, 0xa8, 0x50, + 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8, + 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, + 0x9c, 0xa9, 0x51, 0xa0, 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, + 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7, 0xcc, 0xbb, 0x3e, 0x5a, + 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d, + 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, + 0x37, 0x3f, 0x5b, 0xd1, 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, + 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, 0x44, 0x11, 0x92, 0xd9, + 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5, + 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, + 0xc0, 0xf7, 0x70, 0x07, + } +) diff --git a/encoder/vendor/github.com/codahale/sss/polynomial.go b/encoder/vendor/github.com/codahale/sss/polynomial.go new file mode 100644 index 0000000000000000000000000000000000000000..b8b183a443103daacb57773d82c3efca1a97a206 --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/polynomial.go @@ -0,0 +1,67 @@ +package sss + +import "io" + +// the degree of the polynomial +func degree(p []byte) int { + return len(p) - 1 +} + +// evaluate the polynomial at the given point +func eval(p []byte, x byte) (result byte) { + // Horner's scheme + for i := 1; i <= len(p); i++ { + result = mul(result, x) ^ p[len(p)-i] + } + return +} + +// generates a random n-degree polynomial w/ a given x-intercept +func generate(degree byte, x byte, rand io.Reader) ([]byte, error) { + result := make([]byte, degree+1) + result[0] = x + + buf := make([]byte, degree-1) + if _, err := io.ReadFull(rand, buf); err != nil { + return nil, err + } + + for i := byte(1); i < degree; i++ { + result[i] = buf[i-1] + } + + // the Nth term can't be zero, or else it's a (N-1) degree polynomial + for { + buf = make([]byte, 1) + if _, err := io.ReadFull(rand, buf); err != nil { + return nil, err + } + + if buf[0] != 0 { + result[degree] = buf[0] + return result, nil + } + } +} + +// an input/output pair +type pair struct { + x, y byte +} + +// Lagrange interpolation +func interpolate(points []pair, x byte) (value byte) { + for i, a := range points { + weight := byte(1) + for j, b := range points { + if i != j { + top := x ^ b.x + bottom := a.x ^ b.x + factor := div(top, bottom) + weight = mul(weight, factor) + } + } + value = value ^ mul(weight, a.y) + } + return +} diff --git a/encoder/vendor/github.com/codahale/sss/sss.go b/encoder/vendor/github.com/codahale/sss/sss.go new file mode 100644 index 0000000000000000000000000000000000000000..9221889e5f7d4624eeabf391b8226ae1c673f03e --- /dev/null +++ b/encoder/vendor/github.com/codahale/sss/sss.go @@ -0,0 +1,120 @@ +// Package sss implements Shamir's Secret Sharing algorithm over GF(2^8). +// +// Shamir's Secret Sharing algorithm allows you to securely share a secret with +// N people, allowing the recovery of that secret if K of those people combine +// their shares. +// +// It begins by encoding a secret as a number (e.g., 42), and generating N +// random polynomial equations of degree K-1 which have an X-intercept equal to +// the secret. Given K=3, the following equations might be generated: +// +// f1(x) = 78x^2 + 19x + 42 +// f2(x) = 128x^2 + 171x + 42 +// f3(x) = 121x^2 + 3x + 42 +// f4(x) = 91x^2 + 95x + 42 +// etc. +// +// These polynomials are then evaluated for values of X > 0: +// +// f1(1) = 139 +// f2(2) = 896 +// f3(3) = 1140 +// f4(4) = 1783 +// etc. +// +// These (x, y) pairs are the shares given to the parties. In order to combine +// shares to recover the secret, these (x, y) pairs are used as the input points +// for Lagrange interpolation, which produces a polynomial which matches the +// given points. This polynomial can be evaluated for f(0), producing the secret +// value--the common x-intercept for all the generated polynomials. +// +// If fewer than K shares are combined, the interpolated polynomial will be +// wrong, and the result of f(0) will not be the secret. +// +// This package constructs polynomials over the field GF(2^8) for each byte of +// the secret, allowing for fast splitting and combining of anything which can +// be encoded as bytes. +// +// This package has not been audited by cryptography or security professionals. +package sss + +import ( + "crypto/rand" + "errors" +) + +var ( + // ErrInvalidCount is returned when the count parameter is invalid. + ErrInvalidCount = errors.New("N must be >= K") + // ErrInvalidThreshold is returned when the threshold parameter is invalid. + ErrInvalidThreshold = errors.New("K must be > 1") +) + +func Add(already, k byte, secret []byte) (byte, []byte, error) { + if k <= 1 { + return 0, nil, ErrInvalidThreshold + } + + share := []byte{} + x := already + byte(1) + + for _, b := range secret { + p, err := generate(k-1, b, rand.Reader) + if err != nil { + return 0, nil, err + } + share = append(share, eval(p, x)) + } + return x, share, nil +} + +// Split the given secret into N shares of which K are required to recover the +// secret. Returns a map of share IDs (1-255) to shares. +func Split(n, k byte, secret []byte) (map[byte][]byte, error) { + if k <= 1 { + return nil, ErrInvalidThreshold + } + + if n < k { + return nil, ErrInvalidCount + } + + shares := make(map[byte][]byte, n) + + for _, b := range secret { + p, err := generate(k-1, b, rand.Reader) + if err != nil { + return nil, err + } + + for x := byte(1); x <= n; x++ { + shares[x] = append(shares[x], eval(p, x)) + } + } + + return shares, nil +} + +// Combine the given shares into the original secret. +// +// N.B.: There is no way to know whether the returned value is, in fact, the +// original secret. +func Combine(shares map[byte][]byte) []byte { + var secret []byte + for _, v := range shares { + secret = make([]byte, len(v)) + break + } + + points := make([]pair, len(shares)) + for i := range secret { + p := 0 + for k, v := range shares { + points[p] = pair{x: k, y: v[i]} + p++ + } + secret[i] = interpolate(points, 0) + } + + return secret +} diff --git a/encoder/vendor/modules.txt b/encoder/vendor/modules.txt new file mode 100644 index 0000000000000000000000000000000000000000..68d4d3e8d0722f73ab48df67afaaf3b0e1179946 --- /dev/null +++ b/encoder/vendor/modules.txt @@ -0,0 +1,9 @@ +# apiote.xyz/p/go-dirty v0.0.0-20211218161334-e486e7b5cf43 +## explicit; go 1.16 +apiote.xyz/p/go-dirty +# git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9 +## explicit; go 1.14 +git.sr.ht/~sircmpwn/go-bare +# github.com/codahale/sss v0.0.0-20160501174526-0cb9f6d3f7f1 +## explicit +github.com/codahale/sss diff --git a/index.html b/index.html index 5545bdfe18f02ab0e731d91dfb82b6abaa874aba..c8ac1701bbedb306093b2a037a14ccd5864f55ed 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,8 @@ if (share2.value == '' && share3.value == '') { key = decodePaperKey(share1.value); isPaperKey = true; } else { - key = decodeSSS(share1.value, share2.value, share3.value) + //fetch ('burnt') ==> + key = decodeSSS(share1.value, share2.value, share3.value) //, burnt } if (key.startsWith('ERR: ')) { alert(key); @@ -40,19 +41,35 @@ if (payload.startsWith('ERR: ')) { alert(payload); return; } - let secrets = decryptPayload(key, payload, isPaperKey); - if (secrets.startsWith('ERR: ')) { - alert(secrets); + let will_secrets_res = decryptPayload(key, payload, isPaperKey); + if (will_secrets_res.startsWith('ERR: ')) { + alert(will_secrets); return; } - let element = document.createElement('a'); - let blob = new Blob([secrets], {type: 'text/plain'}); - element.setAttribute('href', URL.createObjectURL(blob)); - element.setAttribute('download', 'secrets'); - element.style.display = 'none'; - document.body.appendChild(element); - element.click(); - document.body.removeChild(element); + let will_secrets = will_secrets_res.split('|'); + let will = will_secrets[0]; + let secrets = will_secrets.slice(1).join('|'); + + let secretsA = document.createElement('a'); + let secretsBlob = new Blob([secrets], {type: 'text/plain'}); + secretsA.setAttribute('href', URL.createObjectURL(secretsBlob)); + secretsA.setAttribute('download', 'secrets.txt'); + secretsA.style.display = 'none'; + document.body.appendChild(secretsA); + secretsA.click(); + document.body.removeChild(secretsA); + + let willA = document.createElement('a'); + let byteArray = Uint8Array.from( + atob(will).split('').map(char => char.charCodeAt(0)) + ); + let willBlob = new Blob([byteArray], { type: 'application/pdf' }); + willA.setAttribute('href', URL.createObjectURL(willBlob)); + willA.setAttribute('download', 'will.pdf'); + willA.style.display = 'none'; + document.body.appendChild(willA); + willA.click(); + document.body.removeChild(willA); }); } </script> diff --git a/joeblack.wasm b/joeblack.wasm index 9be92ac7b63df009ee1817b5ee86209ead113f4d..e3218a0cca5de827379ecd45e5ca5638cda0d080 100755 Binary files a/joeblack.wasm and b/joeblack.wasm differ diff --git a/payload b/payload deleted file mode 100644 index a05e1de891fc9a02b0c256f6fb25b62ba6e49838..0000000000000000000000000000000000000000 --- a/payload +++ /dev/null @@ -1 +0,0 @@ -PArZvSAIs46RG8IJMpgMqDevEVSf8ld+rGklGQ3ACBTq5xffliv5wwR9z7lJ2hrTC500osp0sXWGN3jyajztlUyBV1Z9XgaZi0t4OGRevTIcI3vH8UxeMnjQO4Lax0ulpbcF77uGduOG4GCCrYLfFoaMO4Q92q5fOLuUkGTuM0JWmnNHym3iXMr8AdL0gXimAjxEnZ5sr65+odLjt/qpMz9PvKAz7DU0Rgpjpx8O2gUTfBVv4sPosDX83/XOK5SEYQaf+gfhS7QdRpJsh0z0L3czI4RFYggJ2/HkflBrRNTJsmknEW/c4NBIMIDwyDhjPE1Du/+yhiugz0FQZiUNmLGGX/bXBB4crPaUFsflCTBo6on8Oro93JETWgoBHp17S9LpgM+1L9busQSj+yFkejMGKbYOCc9LS/DsKg16uT2ouIjma8ADw8z6sbg74ctZj6u+KRR/u1tDeCdrndcL2f0HHFy0dIlDV9fJcZdu+LXmtG43mEhuDTK2V1Eftkxu92qb2yeilyb+bl/JY5jVCkRyDEwTOQG9Wm5f2vskOYTfUPqdRvpcvk5obp9guOr4qHUlkoNQWmN+zXxIBEz7XxanZAc0yRsIpzbbPZel4wPc6MtxMjUKz+oCXDfc2ubqAjQm2z0zOcLE2Nx15SGQpp15R8roxUvIy9AtVaSZmZWHlKMqZVNO07y7CE9iQDDZkHceDLQGsICdG7QYHJchi4pVIRKpEibNUK0WHmyRj1U06LvlN33bZ7llZmQW+8vIAeZgyLkoOl4QOpooq2g1u0d4PbS18ylC5kWnNPfe3IXFDcC0wWTCOwxjIXiX3LKzi4nrVuGu6aq7gyE1XlyZVGb7DZSoZK4gEpE9pwDy21a+meB8/h//sv7NRgzb/VuBM8eq5RCb61TOb++gePpjHgFLsYpxIURoDw+X2rq9m9z1Jv09swxJPu69MQKicrV/i+kG8PCHqI4jItZJ8ASJA3Hh+0iCMQFIRUn61WvkxnqVHuod4dHvDJCmtXZVDBDuz8dkUdk54oxP8y1NKZEULnDlCY0HEkmj/FTBlZ+SaClsfu6Ffco3ayZ6Y/JfJrMjgDh2zAsSydurCx/nqlmNCKV22UrIaybzurd1mQG8CITVFAphtWvHl1Mc4KdWAZQzUb+OfhLXSQNESx2ZahT3EuHyhTPhTrJHqNbgkxENdcED9aVGEgbhW7VwDkBRRBrsjyfut7n56C07wG76wRnI6ALjaoDJtoqqLOHG/c3qhy6I9Yd98T7X84xvCiM8xi3xa0VC2C/UzbJYI/RUOqs+WhbJ0MAFgXIJ0CeA0yZd3sR4uuUjnxa/xMAxYTCSptkimy4WL7qJX8cVuFs5PX7pA/uy6hbbw0dkIL1vFHtiujA23wy2Tp92G/fW+8ik9Yt35ZdBUXnbr8/W7bAAOYpdxo9eFwEswoUxT/Owf8z9Kav7/Eg0NTIXMlzsJxjMdxKzVbTuQujhunj4wyUkNrSTntlIR/sbrta+tD6SrvIzTx6MzlchMWHjU/e/EfAnSLrs/1+rNQM29CuvJxpsc0vaFabeBqws+OrwdpuL1OUhSn7LrF2gWfOfHPWuZ7zPOA8PBDi7PgnV9/H5QdJrJZbi0Lk0NJD4bxldh2THBGjFbN7Gewyjsu67t9U/OpGEFeUsxyfpExnYU1i/70wbRguZoptTts2BrbCALCxXZoo9aatXQhlocK4KJoBR+4NCe+2ZcfJAsJYyxSe1hauLBuxwNVgqr+HApUPb60f8RSQvp3y22bHDEP4hWFXOcJR8CImQkz3HESrDhD+O4GA13lh2WnSWC47HTywzbdGioFDCWg189+HWRDVLFV4BDXLd3QHa4VviPnMRDuG/QuotH2xqHPp2KIAXwAiFCbuyaaVjcgBZ/RFkKqn/ezkx1F3MPg5Im77z0Tpj7lpUKEl0qUfDQpK84v90KD6MAcvvmnKM3Iu8JMgtAzzLzJ9dFXEQEFCcfw1euUyyzYLOtIMAGkN+b6QC1QvNEWlT4CRaeb7kbMF/2x/agitTkcy6QCX/gtMqQaHQ/KfSNCEOgYzIjYKFkFQHwgL5ik6c7xsVmurQTsGVh5T/51f+/kESZQXMqNLqbpYcdC9Xi17jch3zeQ9rwoGTvHn/F0p2IPAiYxu1hQPxD16SO3VM2xTk6RUDitIvaH2eusHmvxQKZa5FLhJn4tjvW05L/ShcbOtT+c4UjNT4jaGmK6lqhHhbLOY/n11G5tvsDTLfJr245JS292ZiqqqP5WBChAznq05Jmz1Kk7i/fwhwKP3JH8zaVK0KlC3lu8lzathPyvCg7s4MFytaJOo5ZLlAI3ASFYlfBlGqWPellBxBzR8FOuNgbK8vu5h7/SOCMNlws6juY0ifsXpPykX9rjNvnMCsS3RSE6uJ2OY420oKulD3QOV0r45fLiqQ+BvI3SAWkqOvzTP22oNGWcAhAuErRSBp5WHOrvPV4y6fk5G/u6gfQuANXsDD3R2DsZ8YMIbpZxyYk8ZDerrmcVkbcAqbrbglA48uYNiloHXka7w2nPwcp0T2zoZZN9rPDWJUh24/YgLlda3pqX5uj17aQ759CQyyWyRi6TWeyEDmkimBuHjdXemcRsek92n7ERFBsu8O6aXX53dyKc1WGoWtzeM78sWcctwqdCRkxWd+bGVlaEuokkCcPWTRSdukiHMcGkIFOlPIctATpFisb7mtkYoKHFVe/FMZ3mTUuXPTu+1TuBO+5lTcrgy//IV9zpW/WDWrcoZYhgmCXJ6cvfhu+KZwAhsajgfw+jOhuZtY0RrCWPld5x5lRCoatd0ZzLszdSqeDyqjuccwYuZyf7MSaTSlmF3E8OsFXL3MOYTPQdy4yKtarUqmyBz8pXlpgXf4mjim8RoH/gAa4wqKcVoZMneLQRB4z89D7BEcTR0W3Vsz5HbzVHWs1b/XbWe1Lnv5/LPTJfuqR7rO9iO0x7srIaFDGL1C7bmrUtxsbUZHcMdFLB0h45E1YSeLcQxUTdrautkWUFiKTa+Ju6bUUu+5zFNlLBLa0EChwxG5eKWCILlAjs44OWU6qkhu7q3rB8ja1oNNZlSuYdfSRD0biK8Vi36aONIexLpQxJAn+BNrHDpyx6cEc7+TlKfmI4LhCleutAaKC4SCisZh8vNbvb3CjGkGR4Q4JS1AU24AdfgkK1ZMOhMeBIA1ksvLicXo+I2Ouvr/U7Syfh0hjaDWDN9pQlwmE/HJ53UxVcBn54FnBDoUl00n6i9SS5uQh2R3qmxtCirWon5STPcpalehZvqcH/gJDfb9aeuAALitNaPY4GKg0pM8Edhg4GX7m+JEPDp/k74AU9d1BCefDEyGRk+oO4zXvQrMCXYEto7p9GM6XvuxjcxPbWvRrASHEbqVTaSegFr8P52XPJ9twJt//shHW9OKqgpKp4RJ99OfB1tMFVUI0YIb4gepnkhvscFN/GYCcZldMt+VTCLQSKZhB8lQe/FywDkbJJXXjvbEoZiDnvgUg+qLmAZCmM7Qh2HRi44nmz/f7p2IQd0QDtl/HSk3g24mIW5kud76lFuAcNBuCbarRduDXYY82ML36W09JU+Nk0B+scjfGQrbYBRo6lYaECCepChmG5mbry/FZq8fZP0/z1W8Pal3dhbC3QyAxAodM5WFLO3ozwSaZdGD2NMWL201awDWTCQ22vL8gj2Nzlh8GyJlWqIHTsUrTN5vyrUHG8mPFfF7LUj4U+hPYp1Nye+15HpcEt9HqcXRioUpuF8cOj0+ZvFs+n1rAA5rVTfcgDvQ5WPsV9cmL14Eh5XT/jeqV/1Aca9GM1yyF6c7WlGfLM/MM+uoY+Gk65qBc4My+FyRdFowPI2m6XWLW9NCTC33UAKvbZzQbRzP2XmkNaZcRPPHzakBlF+Aub7gBVXroW3t5QjRGXSzAXjdRg4mo+tLg4LjTxrFnrfz8HOPlCIJMHVBXi2f896zcmsI/CrUxWIOlhWFsxOEshgd/1iQYtCAT8NLG9jU5Nh/Ex2uU/t7T7oeatpQo86dnvxcM/41EeTiByTQYwWvUoMF059vlVxut4VtMH/epTHYKpK9G2Y46FsAPssZs7fcMt+8bQUBZyqe/yA0KqC9foOvDsRTB3eFGBuaWylMXSmSZL4y4wsUTqsXJAjCb7Ey0wU/Cp42QQf3KOO9VuVXd35B1MNWzU32ijckpN1dOvL622TVOdXQK9MePrg5HO1SPEa4CWIj2s9L28BeJRhSaf7+yhjBATSHJ+EtuGY9253Y5270mKWm7JV7m6DD7RIFOBF28k/aA9TkMFe8ysAs1+CYkLfFK3FrmDP4H8r82YX+PtOEtjYYAe+u1fQSUiV5sUJvcEmskLpz4AFfBg8pTTuh0ZpKCmtqIOhy2iN6KIQ59gXKdf/ke+F2mOxOTsDsD1Lj+Z7YJU48SD24j4l2f1UZXLfGWAsVsN1HHIynVlcuQR8oaPBgwePBRH/5B/FmJcBNpr2ym8oJNqTU9eKkVooWDx9J7wjU72aQEaqv2to7K6yiPZwFmHauyuz6hEXpIpej0jUyxdiL8Kh0aLSvb3tchPmAeEywxctQO+v4nuiLV+8dt2CA9xGvb51S+6GhGE7QVHv8MT4Oy3+JQUAJs4BY4hQpPsQ7gZ2zcluXi3e9ETZdy5OAonJeC0h/6cbq1cXTV4vrsYKnDO9/zeKJLF9Z/vxFfwRBXutNHI5MeYRVM9wYVEemalsfKBRV1hcYpGP3nQAdwp3xyGpNgP2SFYv4Q87de+LvQFn231gYBcejl2QnkHEoTBCxlIaHvZygyDOTSv/22dyppvKuSAjhDQH1wRf3uAjavbMkGIEi+trQPBbVu1fwg+ofzx/jTr/+YaoaxFYmMNskyvUxJIfQ7LoYzJMYlGZiW8Aj9ATX6iKPe7+ljfxltRiCvlDhRDqS5o3fY14AFBeyW2TACfia2Z2hOXyqkjN3issWU3nj/J//He15mEVYibNxS199VoQhGnpWTdh3JWiXAVh3JI0bxt2MnFTqv8xBHnHl0s0j/CcHEJHumubOLBYbXvSy2hiGxm8ZKH7cLU9nN8QrlEan5U+vk4fOmcF7r7BknnozJcNBGAW263yUjI4CAYH/DHh2PQMgwQo01kFUVEzGcywKZigf+avAEBBe4oUIo7PLeN9HGmU1LKoZeIAzgh/GRbfqqRikFOPBB9ZqPgdTJyASg71bXX6tqzxJbsseE9jGN8SZGxvQtR1eW2x3x7isco8nJWDJ5gJFA5SkPv5OyXEtDhssUeBU4vEOtZWtAQvSZ0hXrhBRwfzBARPgowNcQJHq9vrtObyTzPk3muOyUw5JYZk8+Rc6jy+CaRGvjdzhTqOIJf27im7su+MN2VBvy3ts27ujJcZpQESteo2AvDdnKjt5VSExH9sKiAFWEKBJx6sCjW8DQlgPJF4a/yxfSOjMDV9yrBNrk4S8aGpGhQbrNghSx/zHYWtsypW4SHHLfI9Ez5XVw5ArBwoMmOVfkASR7oy/ZDssxG2h26IlIJ+eLnLP4IPwh6rza6ScLhffkG/0sc0BRS500lKQIoAvskjR/g8wCAcou/WZqllJJEbs79tIH9EJOlfvJQpTJ+nPmahL4csr1fQabKOdKWHWo2v+1Z31xJtgtMaMpfwRrDTfOf0oEZevaQ0CJxzMSswhaoV90O7P0JkZtSYdmU4+3g0YTh1Y3dxbWJjy+wf5ZKryl0cW4qxm3CMzQdSDuk3xCZbJ8REJG7aTe+IheRMwNg0bhNniUc4XgiRTS2qEz1kSAC7QaeYlvz9071WFT7DM+jEIU8cxqZrlo1gYHBJ+/e5OI1VXExd6wE3YFW/KSH0lhE3BzRgrId5V1ZDRvlX2erGrrxvFJsC1v0AznhvZiVfJGTW+oXKdLMAixP8wVl3eFxcIVqslvag66KZITX+Zyw9P43JpC0dgtZQji6Vb4x/DrGXUdrF1ftrX+i46ufrgipd742bAXhAI/CpeOeCzRImMTApTcuzo+PLgyIymowJ6GUtOSLzIrNy3zZN7mv/a3yhO4s3Fhn7G0Rx5m5KjW5PSagTFKUfJHxwmAJd4x7L2YDcCb0MnRfjAWC6n76DmDFKn78sNYmsv+IC7zD2theRnXnKYurVPG+bOe5VAhqgRHsBC08mM5ZIJm3/b6pj5ru08tBeaORn5dkuwnVUDbIVoyYCSj4U5E6nSP3yb4Uu/b03nmQqgS4RkJl0/D9Jos/MFWYLv9UjQgVNIy2Gvs/qnOXv3mYAkAh/CdNwmI//yFOAO9QSoGCK1uwV3wyBIcizX1sPOUJa9tfc9AkaZk+cUi+ucIxxuBI478bL7/bLweBhZ6cdr6UfDT8zUOIAS+VJ5icC6SUVxKTflsexdL6yEQX41Q/5fC5tVHyLczwP9YrO6Z4IMkyDitjzfb3/MBBNh/BTFuSc/zQRIi96beka33pYYiCW2yhZ7RIzAW4lpc1QLLRnaYWfwWFjblduUttJZP7cxLkY5edBdSsaIs29QFrrhVqqL83LH2tquodr7kFXYAnz1/0m7Ym28r8iZS8ZiVh4H8Fr9oW6btQ7ALbRvIfLuw0+Mc6eG+erbG/7vinLaci1VK1D8c8bwRCYzWWzSDWzoWxdPmuIA8FHAwSFX481FbDgyv9stB7B3EvNB/DKmO7M27CHhMVJRm7T3HxFYtSNpF2w+PKUs7wCtixyyYj3QumlvLhrOQOEPR1ixN155nDqitK25oNvscHpOJt91wlzWeKJ4WWsOg442eXGGi+ndM8ov97mvQbi+7Ev4uTaG51Im5kN3I1M/xRR51bYBzZI+6yxx4yP2U/yWasLqDJla7trheE1HqAPXUNRXkTabeOoWUjpYmCJ2aXiUX3tMSGyyEnGUTIZ5v/AZwbgBOQDLh8RJoC3xbgoUnwycd78rSggGInlg5NaXmJVmH4X5PMNtWKiEbEozE9VgeVreuN3PgIlkDd0kxQFe+MTuh9v+km4264DNPFZ7mDIUva5OWmD7V/9N9Cy6KXfcONzRFvF0IHkUYYXGn4aompj5Uhpmqany3ABKUK+NIS2Rgwf4DSddGiDUVyLX7/jzcrQvWx+FQLb0QuFXlyueCB5CNI1yaJ+IE/LapvMAf3HXFEch2Phdi4U1yY6NblO4bwdiSHeE5MPldgqtaSF/aaM5c/yWY0DSMdOhR3ag12PQgLi4pB5TqrvDYt8KHFqXXDPdx1K5kySkE4T+le3vNfnPQxeT4771oMg4k+FU+wG+4Aom453zIIADB5kFMhbqAPYbUfvn/VE6izGrlYHCIvB9WYvhg/TOnKduFvdfY8BHK4ESxthsZ2ug+qwEY4f41pfvIEnz1raFDhcolqVZwYrRvaSuvaB/aofW/ISMZ3XGvQgfP+iIi5jJcaoPvg7TRgQBNZA7pjQYGiypLhofk3riTe6iXBPs0xK6VnL+3W4sqKGnAONqRnTYzr0pHusWaV0+VvBV4aeXE69HWBWkOqOP6tOwE2Gx8BsQQQHWyRCzQhjwxQrhaIwXterwTAyMLuI349t05PRwU2UE93RpBNh6gry9Kl6/JfamKD++DR4WXsmpYRaLhHNDo9Uv7rrjeuPZ9RjXRh/qGFJMU2v7cETsJmorI3VvaBAsGf5K1FJwSstxwv4lG+shw+3Y0sWpFX5bn+2qZKIjWmmJlRuQTTeRY2uoLV17zeDYPIAMdvtctYwdgjnOUpyPDdtAArdPUqmjvIejw9L6ybWKxRgE6XwTtNNwkpbZfTjRCHt17sDeDy4dyJ1Xtf6SYbpCS8gXQnTOqAoE2ULV3P6ATp4P7mWy5VdgFs+c5x/jAwqaBm9Qok3KX+z4Puhz+kN1I3uXQaiitfi/osMukfKpuNmJra4jIa3NixI+J2VJEcZ+FwgX5NiWlx1JECerd474roZoaDOyFjuFVLggexyn4GMnTCdMQGZo7pYI6iA6PNmFYHmgFPUfJbr/V2nHZoqXVa9/KGdkCqeAsmmSZw7ns7HlIdxOZVaexEX2wFsZ/QEhtoZCUZgtSa46TMc53l/xIno1tf96dV0r0ajqdCkq+gorGRqLO+q9X347QyuZJqBMipQYuQY6H7XkMJuxAXqmHgs75F/i+BmeCfk+6+qNFqsKTO7orydHm+9AuqDsSXR6lHZgK1p5C0YEa8KwCyvocRfs7j8YO0rdywa5n2b9OAdmUrd7oz3k74qDRIFtq3QNdIlZ+zCz1motKZ0d1gwWaQ2bPVmhYVXe90Hw4vV8FE6rQiqQI7jPbb55wOztaXwbSJ2cPq1a78zAaVijo1mk/jZhtSEH9daFi25SaLW5CdZ75gjQOaJju5qjEzSpyTRSb6ZqI1NqeIAqekBbM+tiQ74dP7gFkgkOpVrxueUZxHMTZgkrp7LsyimfVK40B5fkA7ME7hwCQ8TufdTA2kB8R/RvaOQmJHT2pzl1nHb8dOIx7bhWmNB6PK+dgWlzfRRaTMUTDvBYKykGTWcapuJkQ1+Kn2b1Fa3rjS9yCKx1oTzHgPPHbLuv2tK9HasPb51DTa/kBk2vqPSDhJzH3O/6XrkPtmhX4Y0Dxds2COtBVu/Wh0AYQQXBdEL90rg2xktmZ/nfa74KZ94tVpOIqYZ9UmJ7wJboJql16UC7cOZ8ViE4tTZWo1LKnsVH538TtoFdm2wBPgf5ayKhjjkhDpOcBhQlqnuhTuaCFTQcWltZa/0oWcAgy0+ha5BYRgPoBUadpMEhH2Qdu4+XFB1tFWWFCExZhSJLolznvHiFmEuLACdSQ7MWvxZEYkx7ePSZq4AsfE2chCyQdKxo0ksG0J11uhggmxdn3s0+4wSx79wdnLBL9bIuzmqE2CpOLIoqF0pyhsUOSEgpOOlhqPVRASb++4n2A6jQiy8+hzSY68WL6R2ZUaeG36wFWNq4+w/IalT7sVx+5bJNZOfytMKQtTC9Gwr3KxSzE4ozUQ/L5qte4O+hSsi1g1PzwiOWeXc5FQGiRxyk6/U6UjdHfcJpXJx5BkT7ClRB2/gKe9g/+Q1YZl50hsPqdsW2Z08YLxi/j9x69TU3Uh5rPncwyT1YDhRaT8wu09TUMJp7UV0P0Pzlu41+fmx0Mz2HJdOVcE+jYeVEI7lw7Rti9b5WwlluU0AyK3LuuCCqS+2as3hTDLSRR6ROFC/5wSm6m8dDXRuUFQwabIf4IhDWKvos9wOkfERw0i2h55EzqtJjYoFo+jAIDIpnBM0HOZYbsYXLs4V9oYvE7UCNNA2FejWVhhDEQ9VfOmoO3tVG0pgGPUxr8IVIuCa0oOtdxLkT7jXirkmMk5guLilF5wb5YVWEU424fsbsG3TxNJSpcc3Ri1J3hKTrfZvbwMUb4TqWg4S3Q+N7MoMrJFbYh58lnufowH5gZCmRlaWWC6gN5Hi9QV1fm67D9XY4LWg7a5ZP0N0L5GPb7wAd+LNpq28jIsfqjeE5THyFShw7j/0WZ8EEQ9hTQ2xMZGKV+ieNf3ZHs2daz7vhfH3QSKIkntvwGanbLskSh3L/YpYii8gavNkqS/vPfytdZPKnPW8QuDHSXrKT0ybYtaK6FZgisxKhM7V/uQbO20H4VwL2wlajCp+W/hWNIKxmMPKzj/X+mlvDyrpN/xysBw/75JSwKtdYGQWTqV4r4WL6RnoMgWS8sP8YlXiEGlxXOnhDEEiZBm9anrMfLrICYDqIusUyzPgRXibPo9xVroBLnjt34N0LIMayC7NU97vX1htTr+BzmG7+DiNO+9ZeP62740sN/Uk4X+0ieasoWRQXxUr31tpcpmcqjoTOYaAhrIkN4YjEyg6KsdhGC/O1sUPEDOrqwGK777JQ+ZY/w3C49Q8Sjno7tYJRsCVZenTHulcRn6dTpMi7vPQTykhVH2OzYKRJ4u9noozi7caiEfq/P6Sqgowf+xsbY8RJnalTamVdysNSqNY9PULZRWvFOIDvT2nSpJWqQCT5yBpu38LmfDA6ngWZEttFSN3HBHoePraKXKO58Q5ehLuMMyTKxQ9Du0RWOoAs/5iF1/nR+vIIns6SDLznHmYbg3R13EPs2LWQh+IDtJhfZJzsWAxoikqKgy+kFMXg6pd8qvhCe70SSFLP+EvSnE1YzSOORgJQlhxTWnuxPXr7+3ExF5lAqsT1wYdP2HWP7pMcGUgadd3BXacjEJqIDelaAoTygCboUtZahVguYasO2H+LCKq6QRS5bDrKms6UjQ44oXEHSTpuLWpqi/LfRe3MScYGo70eRCFFUIhLHEYEwF+fcF4y1392pLZ3rGZMWxLDOfCrwgyirRYJBjU1ySf0PbhM+hbi+xan1irDCT6hMdVGILU+S0wGlR68pUNqyp/2Kg+B2lY4TK0W/WKP3HVx5KUhGRDI85zpq5Tu2e9wGBXJ5NDB0O3fU9wfGsnfGyq3Lovh4wYZpBecKTQThVyX5ZURbz9iu6w8qYd9LMU4pHT8/jT7AQ+rcIzpSDSyYj+Ijme8z09/sinSv7gaV9GDKZzZdS/pHqwOx/YzeOdXLzrU8XxsfVzKGkDMCrMrRHgPe0gDw/PDxo+Tkz4J6cra3CjwCd9QUshNBZH6nrWxzFY/kiuEqyriYE9+CA+gQzPfRgUJy4aXPYjjlp4ge34o2uUsjLsJ60usjq0dyxkiFJzcUmJqpaSS9N7feVJAK/C+Wsf2ES/w1Cnx3DQnORe7j0KcLIrlKOEaeiNi3JRrldOMZs2jAum09qRGL75purqRpIg2rzRXerJE+vKxLvVh9iTHoPF6aVicICgcT1HTpzI2/5yWzD/J9cWtoBNkZLfq6C28/HFUNbkpzhd8LR/AhGXIBEgZudAUG+SS9iYuA7HWydsJg4NuHg5XOIAWIXRe1VIc6GyF5zBTSSilBBNuq5h5pxMtXlOfxfUlLFHFfVszYfnuOKvKDP5TqjGVV8milBwI9WPwDEZbm9zco6f1fPy15SC863n4q5D6Mf+UcsfgA0u3IBhRyUOW9iKPK1XPyBoCaZkYMkrrljE8Z+RpS5vJ+2pUAHB72Mz9EbSbjd3mIuwWjYQTer0uGRGP4rajTlXZCmH5qUjKRpBGJOIHtmK0/9AK4foWUmYIVox/jPpDNUXhe0mZmOEFOywgGLAr52gJZMLqhONMJ4O7EIZ2gmlCEiRNR5OqLt/kBJvNMYMMtVTUaBNS4DRcTgLYcgpvDm3Ib99bnGSQAKIv60kpYyqtW4Hkb0jLibJJ5wZxGaAB+aWNECoxL1ce2/POkFVyNypYkxgIEgwyHWTjrqH+haW6T+xFJgXl5KKpJ/j9UzRpSQy1O56AnH0v6Nu+smUrGDgmH4x5V9MFNrLQD+K2HeavDnBvzoRoCHOjPmGmWPvXLK2jpYPl5D7SvuCXcznJ6+NEUCINJIk38Bq73jeHBQ7+QxfAg0AiSWii6ZgCq4N9W7j2481IR+stj4GIFUjdUc7XFnDhdfBY+SBi9HyBzu5v8M6Rk3is99tSYxCMpxak1VWCwE05fXozQxDDunSjAeFBDE0Z3DRoTUIKv9SXl+tJNEUOY1pL6Labd/kKQyMBnyyyyrjf0Y7X66Hn0bZmqvPTKV42oayN83kW7aMOd9JcJUduFF80+4x5QTPMJ5KreirAdunnNPRVho7EJ3TUYXaTN8WmnWp1gqECLCDGYvCA7aX4pzoS04GCGE5ukZp5YEsQ5ER7VThzYQ3ddHjgFHc52EhLF3Dk5b3C+GSzI+wNv8a0HFJwwKMuJIG41pTfrTDGyBUdS3/RORhgc2pnT+iLXmlFB2uxUu6Sl1+8UlshJp5RStthkxCIFJSqkmJc9RoPqyQjcJ+nEG6/IXpGaItyh9GH14xJpjZR2286Brd3hefpL4dq5zlhEdJRe91G2jVtlQacICXlrx14UDa90jhpXrZrWOdNxA5imHHiEKwdJsrqO3EpzZTChFtqpEvbcS71fU+Ti3gmyjn9OCxYQmywfRLHpenhQV5oO4k9Z6hmcxBGtZtnnyGWHlNQOh1SrYHJVY1Z50DMoW/MYKrEWrkB/Vkfdo3UM3bbB4fH0ilMlszLCwqAhQMQQ/XbwF6cnGWHtpc9wRvRXvospn+8ponDFmbwlsxF2XyVcVWzEMtj/aWF3Q+h/amR8V/KZCgeMsoqTcF7S8raQazaUwTdF/fI/y7CJHebxvH5FSGNI0Jah5RKi4u0u0xbU4jMiC0E0kTVEPl8Zio4kVMCMylOdLy7L7Hw1nOAN+2394ovm0QTmAxdIZJSOti07NXo3aaTMbX/VAlJC4E73bn97M8CMrUVSt09YKh7O56/axX/99rEmlWasqmlDf56QXJNGwmkdrCc7HS7VibfTki5mmx0wljd0mGoQFq9Kdl4uHW9DpcU7tCekhp2UOlPsq/lPv6Yp9FgsE5W8T3xH+HC/1t9kjVfe/Rc20YEXqpt1h95eO6RK3ERnH7G1WVQkQ3Vy0xQEqCGkljuiXmKZ9s2mGkmxL9D3Tgt/dFu87GthVTk86AdEr9gbthMJ6Umfu1pD/4WLsrBCD6Nt6Q7Ix4bNevpmdOPn4iSwbsHOLo0BnhPXFZ150H87CZ5Ul3Zd3cHIIDXOEmcZI8lPpvJtADNsO/svCqufwiVf3aQxTxGpwSUmigd9kpIGLigJcai7SicqPJ27MzcXfr/bCF0p8DwTwDHlIktwiHhTaBwy3q1QUXpE0ldMv8hEr90VewEU0FNhz3fzQiBUS80kPOG4mCs0kAbuJwej8lHKVhA4Grfo6angcMqqFAEJXPYvMGyS21iiT5gtzzXovQp8g0aWI+qGbtsXiabxMunBRxEnS8xu2cclyOcMihXF18/D/RYlu7ryjjrg2iiNBGaR15UrYuDqQFsYJyKmfsRRvPKr1W+NK/Q0Cbvfu7GpzfgBJnI5KJRhBqRSrJ/7qcFw66e8N/YQmhL83newhmLykBD6Ew43umYz3JidSMcY/DP4mLj/PCMBcuMyBSuDUpCpPXE08bgGkxC5WLdxPyTn5Izuk9x9ffGGjKt9+8ri6A8vVUWE2eyZAMT3Wwbfi/YEqD6WLC3lL1cVj2UKc1AGiRRhpQ1+PDxo3m7I2T5QeOCMUYI6Sw1tYb75pajqKjpd+KtIj26OpDBD3zFi3ocSk1kQhlNJrJh7W4a2GgpVfd3Ip0cmCDKZTGW6nTUzUPfWSDkSXRBfaISyN/fRIUTowADpAvLruMd3M9wTip0lkV5rCQn5W3HkTICKR4oVs0j5pR/0aHTPz0Q812uyORk2lZVmlBuGwj+iURZ3mVn5rk/Ebq877Lh1gEDriJALrfAeEm8UKfqxEo7Tcf5snax9MAwAOAllkWhGTdgcGy/lM2hK0mUl1RoQTbhe8xjRqjvwP/qKXQTTmy/fhPuseVxCCZwP3lV16+mvztD5C/U6lcDpkoF3xTxY6QkbvBtdWpP+VHmEe8bk9D+OcolIjEd8T/nb5RF0voEO/GLEHuVbUH8ITQQIf+WuIqvVs++eXaYLphUImYw9IewLJ1ogYSVrKtAVaUhC+3SCmDSCoRHZ7Inp+GLqSC2HOF7MWXmtSS9f5RwHjIsPU3Oqak3J5wuGKnFNEsWN6j9zXF/15inZRLLcm5zQDYy/UO0KBafutyeIFtyvHzNy8lwi2e8hxLnVXM9NIJkQyNZMLWpzgQU9bkLq04D4jsHjpvR/E3Op7n8GQ9nLnkWSDrwP9Wv+Wv0b9QR1c36bW96Y/LXWuk5nhrY/MpSn+xjB95a72W30x9ES3GOyCCn+8IKGNqdsOYq04jMtuO2WxNsUQP83tWziqBO8U8QGsoPFUfjEzuX+ziKxUZlniXnkslh162QXlqzUulPzzJ23hCTRClkJGGtgRzxQPRItMMjcJpcNov7iOVzKMEhcGKXuxPp2PwOhvxS3v8PF4LaonjOTpWeImnKaItbUM0YMY8V1/FF/PLqOdsF8m7G85qIDf/ni2FCgjN4p7QnTKMGZeQ8dc3v0UokWrLBscOe3DWlThsvJY3+gnJzdOMd6lq7P0zVMVL1tiXG8dy9ABW9nzAdsntvyIKWn1jir01NYyy/0Ds+hDex/GeFa3ZZAnMyiuO9xdVUXD+BkjlkZpImUeHlVolDfcU0SfzwXYWZ9HfnOkQD8mRXWhI5Czs66LmA+SfWDri+EmBcNHSUVvKn9NGgNbIlZA0j6QxgiKGwmd5j+Cptpx6RCyu679SibbbsUlxdIHB39dfZuoErnmagluBBevsq9ZalteGVUIsofll4gekc67MmP7ZYHnY+BaTHcBW1p2pHQUDsWLsMRl00FCTpz9x2y4GE3dvcfVKeANEm4bpSyxazRd/PB9P1BN1pAi54p9KPCVw9r6KjgYcwI0gBKtQn0GStps34wBK5L7tojzTCdUHi4caMzcmUZkZMuhf468jhwAvhWLaX/h+ajWF0uTD/D9UWg4NBvcsVYYvXP5UWA28qLKmqCtsUTzhmMo9oA9WuQrZ+I54D2K0evBJgH5tmCd+uExgKGm1NiMmRInZC6zwic83c8XN2gYrZW5RTr1cOoigerCbCzshdXg84wgbKpuAsB8fo1ZAJKcEvfEp/tFH4KG63y5aFhZrP/y64McHgeKB7j/XaPScaOIZ+8cQ3SaHicjULkoSWPwAYj6JZDgV7Wq/laAb1n/N6DPd8ANdtcZ0b6U00SFQCvUBu6MR7VSj3buOnUQ2NN9w1dmpvV7dzrHHV+9ulb8GZ4m1OM68Gw3uK8uR1pw3DZmPUFsEz7c+imAuw7KFYWt+NNZSrve7IHLzqnZwmWqUQRQJkZtzk2gOt+wzc+eTeWVqBe6KvysDkwBJbF7yFjs9DGckw8J5jJwCqCT6LI6SaUv3uMe0WegnxeSaJK1rfplYC+xDxkOoSx4H7o7QDcuoL3KaJIu7F0d2xcVtybFIiP4+sMl+FEbvscectYGwLPT3wQKpZwedZ7BbRZVC0BjsBa4Pe6LYRmSiiajFO7+BV8tFpZBN5LIfGtIMtloyMr1oUKKSumbcLEz6d44qKipTbqFpos5H28NoRqqgUuit6CPbwUSYMlTeuqBzYr+UdB4QGad6x3kDXKD7DxAxBSOVioyl2GH8D4MayR9/K3j0NvuLlmz7KxR2Cs/g0V0wbUoU47k1bTnr3KxCsyWCFBCR1cjRApzK3cFsDo4BOvJ+xbwzW8LMLrHEEPe8tquGCOpjIFjKOHDY8mkKjXmsCBY8R3nbE2A0EsZa9//8Vt1P7IbQZ3rKBnl/nk2QdgucgUdiNpLMmF5KkmdLxOc9Utk5M7MA5bTBfG6Ojeskwzmfeloc8CvHO8pn1MeKDoV6QyPEwry4/NMj6VBYb8b1BtDOsdtQEcH54CXCTkPNZc8FNV7NRlF1Mg0fmhqVPFIBPbrP0DzfaVTdLPENNNDiDp/jTBD2Od+phBm8XPBP8jIQIvL4Omw+8IdV1KEaYyWpMgTx9PLYn5pPr8xrHmMh7MmXdxKKp1Eldx7+X/WNis3w3e6ia6JAJ49fDPkecWr6jMvM7FXSD+orTvPl2Rhv3e5OUxvCSqqNcTYtiy1vMRDwueql2Tt4HAb/mkyBZ1gk4R/OFzftEwmgX6jsHe3Mpot+ltp/8w8K22eccLtcmW6fTpRJ2E8Wl3cR8W4zhkI5Ld3iG3yPSSIpGzb5BcdEPcyj7hleDSDxODXg5zT2mBJ7d2v56qdAMdfJ87q7x/zupub2AW9vUd7c/UTMeQU8swiI9JCgd+opbxOJHpJ+d3AAykBsPnSZdX+K1ClmFLpovkG7+1U9RUa7DAo6Obr1lqOZgEoKpiCUCZA/xr7hIzrwLXvcn/s/uXNzlRbKqgqZ2TzIh9yX5VAcFQOVIWtl4/NJ4++9gHJViHCIeo/VZS1Mz2oAUaVweyFiZg5gzPFWTn577Zi1r6NrTMkFMIMEXCwxde2WYMR0J3UBdwQnpLkytg4ISb3BX0CdwVhzHfzwzB955MW8jjSW/E/3c0qretgy62eOQXU6Bkl7MbVdu963il3pPpu3+KAu/635HeUYqrAEmrABuC1v1+qYTq1ndF7W1yh+cycFNkjx1khfrRSPBBhe4wlOvE7jIb2/Cgv7ctd7mdH+ku4MuTXBvwWplH7nQj85C5uURDfFuTvbo7p05CJ4do+Zptk82bvHBf26WIt1GBeW9Q8FXBou+2nud17IxpiwrtDDaiRLVax3MJ0F7JCkL13oFiyYW5HTUzj5n3nlrO04qMtGFQvrzaQ+sl+4/NxHE+kuKVWip/1AJtPDO6CEOL4GybgEWMyew1EKQcEb19b2t0MXFEF7/8FWv8OjRL/YSjbvKLjDPs7ODnPP6DHJFRxxs8XR5ugH2n5iEhtvSVOd4v9bdTSYelSPkGA1IWa8qNJmOQsquAQ9yWAXWuEDHPx3GloH2VCoDCsUks3/VY4ebr8oknIFSeKpTGER8OtWKVvCyQj9ACGz2P+APG+XguHp50ORGkjniWkvW7R3eVc5TIZEyEpC9R1mhA1k98pyQl9Zgv4VUIcfXXoLDSaXA9XPdwJZk7Qd7XWsIk25ABOwXU2CQ6Y+bb4MWv1w6oBBu0wfK1ROTAiO/6KcrF0OtjO2IJCKGoSbqRfGSFuxJh+e9g3ixuU3OdV8nFS5tmFstWTQGZVheZIqxzdbxfyCusZZGHqZOrhJeGlYKdH855wQ4AQJxMkHo7pOgkJRJuYNl1qV3If+5B4Q7W9PH+ph1jD1ZOLZFxyzFwp7Pajj2PN3ZdJ0cjzzsCbMU57aN9kFeHuE2/VUJAbztA19pxQdVheTC3ksU9id/90/XJvlTJB4J65r1TGGRTjJhnjACs9qgl3IkBv3adySZoYLlY6UwIJ7F2sBbgWcGO3wpD7IuDZIruj5E3QF4ZuQdV5ZEZ6uOlZLdQ6sCLx633uB9Sk5q6WIevpje0UydyTd6Eqi9Zt+Kisq5nc9+wHGazE4KbXMyi3F7Oi0M33oYbXx34+03BKs4Kg21a3zhU4REoh0I1Q3pLhKfhE2RDooyEa/jqyqUS5rRCY8ZePew4gVppKu/j0ZCjQWleBiXFYOQL95yAtYIkd6DU5xZrHlOUrRrmHpqZIF3z1ZEtej7ootTHiB4bXSr30omogLmi5uykUVoYS4NLrXf2wiU1x3fhy3/w5YHVQkHidee3owxQPD8EfyRTX3yAdlwopkDG6LE/545pnXRSgdtv3NqaTMzjb2Po/oeZjy1xTNfdSJQ2SJMZqqH3o0ZdpO5KQXnMfvgN+CqjvkGR1pMs9ozBg2VlCOln0684Z7GSu8Xr8e3IetihRbg4GAQMZvaIOH3PK1qb3WQM1c1lgW6+k0wfIaHqNYb4FzY6zNm1p16BCkfn9XgPdfQXo1hjHpbKSyYS1ayYGgCxwWygBALLbuL5gTnoNGT7tT7VlqDbNv/tRbjbSUhkLdBzO766EcTrjc9b10j/DKAcJLdMNLtm6OwXjfUo5c1PocaCrvKeKT5rQMoiFy8ONCKlOvfQY5yF0Vm4zQ9CCNb62qRxCfZli1RB9ZvEH89x/nVpvdU1CNMM3Mes6RHYnBvc8TfbqGGgKS830g5i9VWMJ3ljLZ0ec7QJblLeaBwSDAcKkzYMYRLWZmBsw8iQO3KORu1jCyp3lBowDhPevLSpkqAqcbfz4sVVhwd8O4gtZumM7sVZLBjqwx1r+J7BN+F9RzpfsEICNnkEVFy9LxMmY/Fx2XlJ/xXO/DKQ7SaGznd4flR69pPBu2rpqGrBhocWCtZ+rcbyW/cxPJAWz9QplpqnYoXEOjDnTlWO8xZOk5qToPve1ML5T9A35kEnuJ+Gydzw4nBt0hHJdLTMB+jv3v9WM+lv8RPoLvNrcAfEut6Z464DYJq1ipI8uPzCbtyiM1koUsSldERyzy7VoEvYAuEUfMFNTWhi0fpR+rgvjl344kc7/lCawu1+4XTAXPMS5bMrMPF6qqf4fkL48S2Nupn3sPPiSYdhBIMrTlz65Fvru/66VzyGEoQCx7PYUyhLGvAsSGU3BF+/v39YKEzRHaxK+2GiIGKFTUTuZXSZeT8Exs55GpcyduZdUbe7ksoq6F9jz9hwx4Z9P05qh/f3iUdmeuE5kgz/0OmorcaiYPOxGHktW845y+9jZDP1D9u/Mb8dyR9Rd/y+ayqxJQbZPY9ENscEbzRFmzeST/VbcYvbDfO++W6mDNf3ZiLQefRgmiuzvb5zLOpkJ0M0VIhRn/k6N9hlGgND0fnXCzfcXNO1pwOFStzRvf8p6Zd4EZoma0UJg8qXYJ+2Kvk+2IEWiVg3yjpvYUahW/mfLK1FlPzPzs0plenm9bkYs2i/7HOCJVR0tF2Oig6AJAyjc8hM4LhP5q/doRm3pdt2XdhX4AOC9VO4XuBUYi8ag1SH/uX9qNX6zYs/KG6elKrsXyvNHWsimMJ3tx7XFM+0TeRwN33qIKBUr7aC5MFwC+KEXR/GG9+FJp2kNqpOagtmcH8msNOpOyOTrWgEJvCvbmVpx9mqz/owoxfXeCMwfL2OAD9gCO+Wk/ZQivx0UnFbVdrg3hqf9vQhDKHIJjmdMkOAx2/V1rJKoSByQjzU9vF/DdmD6LnAU8RvRzLca9U7tqqZ24/YjTDTaFc6oE7C/qNSVeC3DQdi5/oTneeaKiFIuBV1ViozIo9HxdmAJTmdXaGpMwrQwE0p6N4N1QUE7c0JWOWcn28HbWPnLHRm5RtgUL+jEPVWpDw8mON7/TbT1ma+R5R8ycnXIsZhCuj11EJKpL+hirbY05QVn67oZoyT7ZH2X3Gd4wMIdr5pS0hJ+q0wYYHsSRUMNT0+gbcyfKUZ0YeQi4446itMo7HnCJu8HThgfhqzA2qWbiq0dp0HseeJU0PJYPmujPydcyNzn/kYjp2uH1WUBHyL9ysgq6zqnUiBd5utWrlsM8KqqGqVv/aRpXpDHsNjKRhj+9+47SQqwO6OiEc7xNroa3fcxTl3o8lJ4jI+le1Yy8e1sFbZrR6WJ8/FxZnlC1bYam2e2EbzPzqtO7+hZMKS+Ns8AWVVlm16k/5pXXHnNJYlQ8fJF6PcsH+0SihD82ZpHL9z2ISxtpFGZX/3iujVYR3Wv5YcW+EFxF0BWkisVVMTd0CWWg+ThhYtWQpnCJREOGTMh8n5om8BaUeonz1JRBusCT08K0qW9acIcxrzMpyHT8RaRDwwy6VXeAJOYWSxegWeuOHtA5JFtqvEAB3L+X2ofFT6FaPGa9Y6ZiOLza9FGI3EQsy/ez3dBkPiDn9hHjF8144ZfE3VA800+Otwfn5d0Sqdt2NQyTDuTO2+0a67E5SypKIEAUfnCcpiacR6x/e1eVus7M6VUp2eLnSHZ4J1jVM85CIV00lRJ06kSNPfUrY2puSqcAygcvDZyuPn20W1sdC5WH7RKKPzkqeeroITJeCXe1c4QEAlXhCMrOT15Rrmwbgijh31rUqQXqfy3XtW7KbjqQFa/pPUrfgg9h+KFd+HCv6yPepmKENukp8iq0DSZPWWH6hNPwxwUsw9/8VP3F1jg/j5/4/K82/vlmuKKmW4V/og7stiZ8Se43qYASdK8l1bDiKYikmZbzpyUM7y36v1V7GIvCz1PZnWjq3Sqh2/KeXL5r8CqC4ck+Or1qHhY22A4iRmrwm2gHULmfSA7TKBzrNR8P92sLvJKiv9qUnIIiIYu0IDw0fUfhvUwvzg8BqIFfnJ4UNkLowQTtxbGaMvKCarGnCtHnWd98unotE7q5q6GV+q3Fkflw4tinT0iqYnvCBc+cdPPZ3ntOPKunGaVfk8lHkW8eLgf2xvjLZ3Y/0RCfeCjboy6piaXrfnytuvG0HrYM9BuBsqkNvRYxih+BZ7HZHfJ9J+SMa+DpK2Gb4xCbUbyOGmupm0ASSjulGy3CNeYWuhNd4MyVuX6NY9cLSI/tGikMjQ9o3XUiZR0upUBQ5ryKo4TAqLbLJ41C0cNerU+6hHXcntv0+/sQROcyqwSTjeoFBYpAsAuOG7vWySVlqbkrfoexQagwXCbjzXE2+9EmZpt0gCbjRbBzOGYfaUd8Xpu3thjzm9Vl20xpQLf2NO6tKm7osiJ7kSOTg58kCzxP9J7DBHoaiIGeTMZgmQn277QN1kitDnR3Ion5LYeqaDmP7eSP1DtG6xsH4P6a79Azl+ySQ0n+b9VR9AoVbRac8tfz/fN3rLGS7IXDhL39m8Q/kEuKrMVWQ0EfV7Chihk0kcCurRX6FNpoZh45zdhiXenPRyUkptzksLbgSXzVo0J7AYfEQJuNV3Ytd9WOD1NCw4er2AWn2eW5JpZcXpQNkz112InEQmZU23IUL24AZ2h3YMgYNVxOdIo+cClbukeOvwg7XWxwRvUd7uhMPfYoPLNe8eFfdbqdB39bGBU6AGQbihcYtl9n87JobedEZH/q3Bf3RB44Y/6yvYdbLwtdUE+fCEB2pmzg9WqDRMrhycOmB1oGTWjdb8y0eIYMRCOWhFOBh0IpToDoudza/e1jOoV9JoV3iI0nit+/Tt7TwYGdJYVdOC1GeUG0fgSDoZTzfSWmo/N/cyWmC3an2bwEJXj6uyq+W9DftTyShnjLHEt0ZlW/7o+H99nJrtcc8PJYffvGnDZvsgXik82dIEJypVl6K0v0wxIRELZu19PMGnagMW0zhK55nvaCWtB+U1D4j6Zg7r6C5RpOPGeRAW5D5PE1eWCoVYFPMcRQd7YGgA+e1fMgeY94WaJa1GpW72Dec7A10cWj2NYE2M382WWPMpHBdsmuPa7Mlf0YkgXIh5aIbeRy+eRGkVfDbvUX8bk13Js97Ei2bvAwubXZF82MEwpyHS4N1BvnpxwyJjSE/9xvppfFSPBcC9LvDjOZN7Lb9J6dQ2ql7Zqd7exzzSYfeGbWFMBoa6QU4Yha777hMOkEjkMHUXzEqUNf899WOb+fTtXIQU5B0aYqiXxTAJ+qjuutS99Mmpc2w9xSdg4lJ2QKTM9b+IODrx8ECgRb07JXBXvFEnfjvrIkYmkVvMyBt4ko8CGY6mU5zq/CoTFhC6+m1RVFfeAfNZBK+RPboSiuqQR2SVECSPkm2xhOdn5TtnkG0Ay6AdDaIUQ+cmT10pQb8+Eg0ktDkhtuA+8FKGF32cQh6CpwbY3NallNPnN3EUtoCW+9BVpO8wRLJ3oDrrrvIvKlhpmNEAIzQJQe4BYohSKAsKvYg8n/uTqG6jKZE0VYnJAv0Jcqxweri4/KkH8AutChWIwBg2cVdTBMTBiT7kIUZD7uSYLnEjQmJcOKKQovnK2LD1U0Cpf2/XjpQVaQhsvY+7N4Cx3sy7zk24Nn1fWXrtMz5RnhfwUvkzOdSToAyyGAYO6Xp3J8xc0Euby1duBF4oJNgLiq9E9lp9nQAO6ugI1duBZXRMkvUsHTFMIU4T9Td8Ue2QRr9rJnBcqz7rxjdVDPlJO4wM/ajC5tXq4m0vjVhUjwqcBfJ3wpcT+ji9wjCrPR1aM4aKQFTdRonbdCEztiiBx6R4W+hfOLttnZBPy6wXBfsLvJMOjVUCgqkppLUc+kfBslVZmx8DTjtvSe0qBYDM2n2O9cFvVlStsMBZimysSo1m8HQY99ZeG0hwLgCb1Zf6MMHPHYg3bEtC+e1vWbAuYcuCwU/54M0aJkkMKPjYcAbsj+RVK5qWrsgFr/4FE91i3rgRDOp/fh12VMw1x0P0gGsGtPNmfSJUqa4l1Rnil82vsbDA7BITGFtJUgd/fT0qnd0B42Fc9rTJebUMwZcxpb6u+jWbO09GU7q0/snditYeYCPPdvW6n4FGMX7YoeZARqyVNIy5zWU0rhdCfKuWyvMLAHcHzTFB1juf+Kucz9NCdx5Wo8v8LFluOfsXF7UW5zalx/maApU4C1i7trvlCp10HiIIj8gcURviMBlLEYXBNpqDoDFVAZiFIwzu1srO4+uSw5vytwfonViweIf4lW5tMXKQe57eIdqOz8bi7j7tUpkmy1aLo/y56ZejcJ7j/idUxk8jS3YeKRrm+WIabdIHg7JRyFlFAxXR0Rj8VvKvSw2pStkjq6kVRvBqULVJ3MuGlKViWhKBtQ2nRY1KcaB92ehv27E6ssdsM/wEZyVHtk19fl6WyJeQZ0Ze2UWyNaXE+U1bhcfS02r27/zUWDMnmwpJ11J0QsV0Vw4BEnErJafiqlNHcozrAGIuWtsw5BjSVvw8oaG1rjt/wmsRp5biRG0z1MfIALb8FxXSQdvoi4dQiu7jTRuPaj8YrlUaxAzmTT+XZf+VSHs3EciWWbdIi3oLIsj9tBwp75ASJIr1VseCb69FmcUenWfmpGb8JdgtItmlv6GMcnpSiC+d8qmGIkHSEFgYsWMvBGMxz0bxnI0irYnc0ZxK6y4VtpG5zVY9nut8QxZsezqua2RbQaX1MvsCd14lRqZJDPZRD5TCpXK6v9tsajqBiopkD93sAKG6/AS+uUDHzdUpLKQly+CEr2PM9JloZcmPiHTrbt/sPxoJWV2XGboC1Dzo4eWKM3nE9qIxb25565G8bfNbUeAoEQAPbqpHBY6IRTJ6IbZ3bnjOgCT79rHkyjb7ogPa0rBVSIYIH4x/rMSzkkCl8bsAHbHiCd7SoyMKjIWrKl01Snkcji39+YXDdaF7JX84dRA08JZDo6vfdRwSfa6Qm+WxTOSvppp7Lz6hrNrXh15LWh+iOynZwcsQw031mePhi7y0PAe93Si5mk5D6C8a5divFZpgBzKU2+sDfbjhsM6HI/viy6hTN13tIsVfjIaeyESttOTgRyl2OvhAb5wAnLEtK0k+HUgpJP/LpbB4ILsFZkixNfEY3mElOTeg8ETdfmGxH9vc2FFwmhFRznv7FG795t514BtkmOcbbFDH7+sxEtpdqCR2HvyzzLNWpbVeVcqR+YvU+RExhuYsHk4jvwtv2U5qnBQ74vRVEtHhkUkcx7BZkVuTGzZgawyk1vhdkH01f4gnay3S2Sjmmj5xBSvl2iFtszE6LEsv72sV4573OLwxv1uEqop1RWy2BRWoeOL4bGfl4EQo7Zw/cTKM4aiUVh2QVJvf3de0L8l7aWzCnIXQvDB3WZ0tuHDLCFdWUc32eCZhTz+6NqRI2Zpd4oAUr7Heq9AhaAPxAQaRL+/8BETcM6XFJkhSwSxwb/JFIHCe441pxNwctJ7WpKR+av6yXUOzBy42jy4SfQcSIyFnvQP883WRsFs9onX/QtO/00VuuR5CL/1vHhUuAMEeKT9j/WTt/DIaK4VHxw/BbxVew02wrg789AO1onvCAI3aMKRGvPdho4P0nK/rfhkfnLqkbwFzEHpQaJDrn/EZUFbyVyDK38EHVZKUulJfqR38rqWGhr4o3fmgGNAOhPLWE46ogh0vLmCnfZ3dWk+e6Q/TWq0Q+wO8z/rqPsPr4OgnZJO/OwvRpmc+jRjz0HzZ17VuMSi6ysKTvmp/HuZby4uYJ+owYzHeyUXeeVfFAStCUv8e4p6lwFblj1I/jb3qtrYVecAgit0qMxbKVpvRgcoPRsT0ywQFzrMCUXF+aRDvQExNJk5yNcBzwN+JwzDglu40zVi6ehn7wQx7RMkYL0i3YX7qgl6DmTAUxZRQroWlr1DaZ/zULBGpiK2S/W3vPadteldjwuuYS6IfQ+VD68lkoDOQVB/jb8Fd6i6ZJV4nbmWugNhwcJ7WD4IHz6WZvonGeIDfp39PIqshcSE1zishlx3tUX1Nwcur4HV80Ut607IInwy6q9snYZf5lEicCjG3XYgYAzhOEVj7RqUDVnlc8ws1dOOw/WMtbQqa/8V0uFxQGtkMQXeTik1+2F4/gU2j+CbyvzbfwB1fE0pA47i1Q4kmMVRJcoef6JYO9r030eaOsHLI7TcKtBDeCphatTlwHI+ZQsaY48nwtb/+2eUuR85loCbBy77ddcB/tQuUwQBRuk42yhMlHKT4GeFRNXGjbgK0NO542ys0aUAbt5o5KFAG88eBU9j8L4HqfPAWZz8zMwmmx7aUbRLm41NP5YaNPkSipIXCohWp680AjAhCzPqINBsGXWVmefu28IaIDQeN+g/ZacnpH1TM9hdddqf3NmqDy6PPfhjoiQu+CG/5fuIT/KXZCekKeu67B7hQBsrdnByMtQsvn5Xxy8bL391I3qwDZolNtDr9adBT9PXWcKfrClFx4DfEYAB0sFe1UbfGFfQ5eZzsQlHpFebdm236C9gB7kdswnodUL/enKKh15cYeyv7cBQPp8QSGvbHDp3HVgvFIcA9L+l190BdajjaQVff1mdndDn75Z7IzmEcHN6qa21zLGbZRZhH8BfDBc44sog0wT9hokA2x60ONNfFZLxR8soyxIyr5I2NlJwrtdslpyRSN1xBMqsVIf1yrOa4b8ByhVL3fg6Be998jE+QAHmSm0E9O1kXKIDvnXX06031wd+DYfthOfzDSIRlMX7cx79HMwmHnZy8s9IkHBYFRfZ4gOGrUD2PLLRiK6JdboDKelj0pL5CXNM3kKmTO/U6UHtZL6loXjw8pUDh02faB6o9E/ZWIg42AkyNbYK3nkhRpi5OjDfvgrgRGBiilA8oAFY65cUCwiEJHVifDhN/6HWeEP0FxHB9GEvmq/MqAVPv3wkTABzHSAJhRsnAPUIFbTFo5VU73jz0DucbG2KKQpaIQljjQur9OFyizVMbvA+/gLTTHzLJ5VHUsZemv/ESm69AAX9BLRUwX5coAFzbE4rdcAgflWoxdLVXWO2hWnUW+tNdEJueer4Mz2r4+Pby9Ywrq7/6hWvd2cwu21mgMeD1Wo5jLqUf707YplPhmd1SYaKnHqwm8ZWoGUFr4d7VPYU/koj0w6eLPXxe4jWrHCOkPCp7/ZtsR6zE9F0Js96x5Gm+zvWcRIdfBe1vZIvJNpedZ4kabfMcQ8OL4mWPvNo8L0TVnxcAN1oj2L1ekc4mIi54Tkr8uMl2Rgq7zluGx0+dICeGgk/sX6Be9U2IVNkoqiAdkWP4CoM+Yhgiqke3Hmep986tkebZllQBHBKc8yLXyfVAf7lI/NdJru+N1zgI7AdpaZaZjmvdZwitBYC25sS2f68kulYWXp2b2XTKVLf1ZA3keS3PSEOMOTsTf+ux7ZieewZspEyA2/3v4u7JaSVIiFMPwnsCPebEuvc6Za80u3QrUxrOrjx0XNBr2shFRTwiTBcOGrylSf9NpKArIfw+1vsZsN8h/S/rqJX0ZTrDCKerc7CaThBzBQISoIC3vsqMaW3Od9cnRWCetEtaVFvVmSdivAVcuLyhSUfKITY68RrDQ9VqzpHV+hbKOARv6SgBVRtS8eNNmhTk5q8wysaTCc9ucHG3Lesk9TdPQrG2v58+xivmO0LiT+cQt2OZuPF7zkhNaq7mLxKwwJ1shKqmHKPVW2GN0kVlgSFVybXasga7R4SK6z9s9RM+AfLq3jYi/oDPDVn2W5EwD47GWfmqZbI5m6o3KdlXsHWyqiH0f9mJ/j4u+nKxAJPO3X92gVGX01h244XQOL+t8k8yNuBWJtQWVtF3+W5ZmjsScbQLl4O5UZqatIlWR+u03OVVNK+tR0hu6n3pRqfnFcrIpOvG2Arv11S/FsJvN7s3Z7flSBc7OnacG/QBEPP1Ymjb8hI8FwnBIeZ6pDrfjivECLlTZMbsndHLuvRwSJA+rJmbjcsyT2Kx0uESnkoXW17Tm3IJ3ibkItrMNE2ISF5fuzfWMTGWQFFsAPyYnAiMyLmZ5rFTAs1V8c+SQ0iWhmdplTwDjeAnSa9TCVFpGbOdsc9Y3Xsr0nxqADtbgyZMdUAWGPxqa2lgEpdVb81PlybecByU+26swkcy6zuInwDZfTke21RcohBZyv7Z3VAA/CzmEXTm+XbvKSCcNz7tjjqNwHz8Y4fRTL+R5XE6Lsfv39xsTwOUIyN+EMoqjDrgA4x8jjaGbSJoqqfevvaYp03uvuLqdUjlBk1yDgs65JdMivk20ZeDVp335Cq7jNv87x2rFcEEnSheWDgSVBQD88KlQkLEFTofwgAfD4EcKAU5xCbLpOSxVZGyScMRySRQjCd8odzrTokOByaCuleO5upVy2I/rxp8tLF2JTYV9xXIN4BrKPhsg2XSG4pl8FjWZquU0mNWBY7PbfgqgCYzIYFPGAECDcjW2wU1HpqfLNe9y6S9KpJS/Gzg94KmD0iM3OXmeaNMJ9FhBdUITfYipsQZ1iWei3ayu23UYEAyfzySlnyJpLz4v1EUq9dB5QHsDikXgb2L96uvYDsJskdXnSUzTbYed5q2PsaGHZfTosQdv9ouh2zsUNET0tOwereHjpbSnS/9rIpFX+j9luCOOY4NyIBf1aUZgB7ko8kezJ8FYPh48lQl2HQ2PkUysO9JcHqBLGDiu7v7pIPovxvjekXo57dy/JBFuGwYjcCD/dzr08UeXeAzWhuFy+EzuyVG16FkETrGVb+Py9lrEs4OknwKSEhi1oEpwRBR4hbieCJEc9OBfeEFNLxTJDGqZMJGH7aVR1tIsHZaoRp3ux9K1zIQqHdZLSkcRZ5JeGvuOGYjzH7aFYGMlnCa5dXFE/RwIXFXpHjLB20AqAT3cjsG/SUXRHeOwCr2XDsMznaECfxm73VUZOfaGvgRKjF0BqpdSvpLS2CGysW7j7FE11SHjtJ5nv1y1RqnhJQh9IjDm5ujzuZtejWla5Ndxvt/NXBza5f+igOyDBX1+f5ZABNO1dvoHz1BSf4HpuR+P2WbXfA9/fOgEGc+hZ341LXI9e6l+r/bNLQkj8QX5AiEYiDP1phEaNSDAk2noYJjagdvOCwpQbNtof56LgUNDW76Ok5t7SLtcwyUY8IiAvY9Hy1saQ4J1L2tOLvASFzMQwVaS2foHScVGuug9GKc+9g97o/CHype9A3g4xSvB1K/yHWGmA2s+2QQx8r+P4yO3R9n7nYsxvIilILvJ5SHeLI0Ab7uInOJeAwn7nl1N3Fe1pmVNryJUVarPNJyifKbv2E4zjSl1Sh5NubVARll9hegzdXYabybRUVEuWx9uatu5ikppGtsR7l98O8hUSqydHoHVxQZVyuu/Q0huBjf9bB3sKQEc1xZ9roYAz6UMh8a9/+XTJlXlkqsp6rkFL/DHtqrJcAMkCqen6Y3pQFIHsVY9QrcxQX7wyYBjoaVaQ8DGiql6dptRmoVWnX24z+h1ZWypigogZkJG1S2fVPxClM8H5VtLJK4HC6pPBone/w3FhyC5Sx3ASVJkuoJ/WgYwVSHNJBVx4wvL6lIJ4LYBQNhAW3OOmJY74i/K3S6VQhKrEjLCErKM+trJ2RbSKMlDFJDbXeW8hDQf62qUnNmUw5oha4sE42b4xcHJ8go+kvzs2D12npETCW2WxFHpZ3Cd+DJOBsqaq4FXiKe+R2nCIxjobtqo6pJAAouiENyxhMhEikGvVGsNLLFs8xnLvhnW39leTr87+99vc3URe6IpnBbBXpFTvOJ1VBdG7Zvm2KQtJeGllDsqszBMzk8AEPoCSAS5cH55bp8D0ffupmhqNgeEG0T06rr6PAf0TJT8pkIH/OyI2PETkEooBM6OFXR5UXbRoJvuFkMo5XpeVCe4yvTKiauVseOv4uA2ef2oFoSo76g9PAkUlmHFI6cq/G9pEdMteJRzHWNFreXeYG0OiWODvD0lHXGalLx6hRP2SnTlv02COGJU7WJaQtKJjvL7rOWlTOmDgGO2jJBD2PuH2C9cMQ7fwgL+TNfGOWhreTtZ/ExJjjhmBnj57+vunFfZ17B3y/kCsYHmGbExuwCsKBcfTSV8rnFY3UNrYSwcJrw31Hph6FYKoL6EM7if+oIYNZgF2bS78eWeOD1qHzqNgusSeBffCWwJ3OAc7c545QHIiBTevtbwsT56Q7pEM7cTNtbeOWeV5BJiBTccEKkk9DZv7kbQ449G4Sfz/zcxn8euTdeGBJ9cBcJsXszDd4gJrt7B0lr+NjrFovrxKBgVWmOtXWHKi6paOCJJIjHPASh3etfX4XTeGsLZpJS72oEQgnnRYo88GsbOnO57CfxIbFL80z0SQgHOWJlHRvILneKsgFtFaE3X53+e6OKup/WdV8sfoYotdBEsRHxojZq+2LPK8iIcUYVDDWY9n7aCM6kU9gwbk9MuBGdXmdLT0X7WsRSDekpSRHoB/mTVv+NXL8vKP/6blkSzR4XWFDnTTZw1uI4wxncjBYX9dkeGM1sQ2ZMmVrIhZAdaIlZ57eN0pl+M9P0Dy2pidIHDeKFMSDj1YSZFs7gFdyKgk0XCtpZS+a0PL2G0HAjLz855qmrZKPcKciXEp0/RJpgHdZjYG170ix10kLAmaLPKJwXPjqbzDttOTj4uZPaxlB1djr4HWOlIE5I0bXIjalc21BAp5Y6cfpm2luTMu49RnBVj7+X6mXII5bp81RDZvOXhlf0isOiev+BJ6p/QpmyQtRJG2unCs+qyDnBWYn/X9Z10XnOpD3gaAygPrh81zC3HD5Cl/ey2k/4l675W8dCxl2IjSedToGUeoDSWoKZn62Zk9Bg7ja+dGby2gDZ0Q6i4x4lKP3a1BbKQBdt2spWtB3xaqm5xx+04vfGlzJkPolBSxioF4m8LnPPxWFPrb1CP9bZWOEvz4rIgEkXmubmmzUWCzU8cBJUAZVYoWftLCQSqY3C6iXqQWMkK6N66/K+GMLNrv+bvpCzEXFWNateowVv10UudtX8AmE8QIo2/a4/cSD0Zq+MehqMWHGdga3VkWt0Z6kR2ljxfDrPO70Speul9Wz/N1wQEFBnxAuepmsigsVh+Nda+aFfripytv1htZ7hQkS86U47BjBTmY0+fFu30k/QhS7U/tEvx2RNkOdpxxWH4nFOS9s11AF+2WiqGtuE60gtHZozDccjxRQ3UYxe08AGi9ukg1zXd1GXa1Vj1lwOs/3BiATp4npdAH44O6jpYYSgJagsqk2dxcGNdmZseI6D+7Iq/CEMqzeKMnrWK4Dzxg21F8HbOaLS6akkxJR7qSBRQRXYgCI2/0fsDlDmt/ccoooJQ050RqqyTkbCeATYdnS6Mjs3gIV2pvl7Ho349GvPYiwY5iL9lJVqCx1aN1DA8ycRtHuihEb3IkM60CesQnoSDc3pujXPgHc6ytfGA2M2bK3UMLMF2y9p7ZIC25woG6340kjAmZ45hdmJY+5GnbhGlL6luJzv93b8JCGis4vULVWiGJQe6WBrONz4/ATMYj9SxAPRTEyMIkz7caL3CvATJHPpr6A6uPAJjqxK1vxoTux4w69Q8RugdYXaPPM8GMl6aVW5xgB/lg5B4fu41nxYpM8KWKB3pljHnGjebZkzaNw/SOkRUHBljB1oRAAbgERG2oMn2JdjFTu8WXH17FW13T1iOeQL/Qj42qmm82ZPdxFuHGkJkAawWhqDJHap7MfebzFBq61aWrViN/XBcwp/4/tFczLnO/8k+5+t751sll6b3ileIxH9ZYffTOF8INn9giwn1W3MU9FGMp5n4Ffaj1kTBUcEGpTxTY712Q43SZxbP7rUAsdRtwbavqTrn/Yj6qyU7EBeHXSbHbeFuhaejhg0u/QDn55aXSX5xdnEfY587vdIrOsjxX5+Fa6lSPVE5ozHbANP3Hw5u0aB2nCiPkLcmhkVJ9jWGFwXmOFAn0bF7p+m851f773fj7uG0WKxRo/5nhgtuyhOVCnnPfqSSPTgjf8cLwgNZyp5jb7+9StYvuN6oufAx8O8YiETXt28cc8ueFuwpgl1mjr+gd1kSQbzFl++l28lq5xaBMJL+IifrzE6fXkN9Qc73byhK6BoR+NlF5rPwzUXGmlUgUFL5VhwcXj/Y4+a2eZK0hsvsSVQmAQjGwAx56lg1KEAWZVBHtqhZevZ8T3eAAXV+eZbraqD0HLTZiRQ8cH400o0iJGekfy7/owccyHV7sWVwWGfE79MiU5rht5HhwhSFVvGETRGICwEv3DCbtr6ZRBTdBHkHpGConIZojbkl2722FsCNrHnDKYrDWYVdpx9n+uz3QQdRMRk9275XuENhDI180dGg2Tvro5FBVH/OLwqpG2cZGyle8ktQ+Lm0Ybwbb4n1skYhmI+O/n2ok+l+d2pe6OuPL1in1fJoJk2B37ZQos8gubsYU8KGo6zhhL2Cj+MS+meXmwvzmWFeISSv/TpDkXINSns9+V10mkAYmI9mUges6cQvXqfoZTTG3RwjTIXzDDu0mTOtsRIsH41kFot59bSp14kXxmNFBDlohdf7rmT53TtDiAcfFbFPfXvE7jCYOa5eQAryB83AtJ+8GmGYesMrzieXnwNAByJmeChbbgmxb9KZGToZyQpFnDgMyOnRTC9fKOv5k6iimCpDD7+++8Q8RYJ8DUBwRP7/xRPDqt2hO/tE2KIKmPu02i5A39Tvew/P2cx8Nrek/4Vr8VveIwYQ+sPgV/s/RPUmrOXy5hWS/OO8hJEfCt8+5+qtODQR4c+M25PnRT7TR6WqmPu6d8+xiDUaw3dMy7peEAR6uXaUbWOXC2ksFLQs5y0jaME8ApDAhOsJhIw+zWdMYniTbXW+L/7inbiLDemWrvXhHuMZf6ch/vzjDvRTkIQv5HDwhJQxdMDZW4FWh+hl1Zvw05mY53rCbvyaluO+ll9jRc8AJ03FnXt3mGjlbs46EdHX3iB35SNTPEEGfMfzzwS8QDV+Ao9KJ91ioFGUgeNJm8QZitrqRmAR3I4Ln18FcbMfHQbxjwJudFDGKAuAE4X76HLbIK+StyE2j1Jw== \ No newline at end of file diff --git a/shared/shared.go b/shared/shared.go index 430b7ff9565223eda45a5d77ae67811dd965657c..18b2ea03ca2c0b71caebb9e8819be998876c0a20 100644 --- a/shared/shared.go +++ b/shared/shared.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" @@ -9,6 +10,8 @@ "fmt" "io" "math/big" "strings" + + "git.sr.ht/~sircmpwn/go-bare" ) type SecretEntry struct { @@ -20,6 +23,55 @@ type Payload struct { Keys [][]byte Secrets []byte + Will []byte +} + +func unmarshal(b []byte) (Payload, error) { + bare.MaxArrayLength(30720) + payload := Payload{ + Keys: [][]byte{}, + } + buffer := bytes.NewBuffer(b) + r := bare.NewReader(buffer) + k, err := r.ReadUint() + if err != nil { + return payload, fmt.Errorf("while reading Keys length: %w", err) + } + var i uint64 = 0 + for ; i < k; i++ { + l, err := r.ReadUint() + if err != nil { + return payload, fmt.Errorf("while reading Keys[%d] length: %w", i, err) + } + data := make([]byte, l) + err = r.ReadDataFixed(data) + if err != nil { + return payload, fmt.Errorf("while reading Keys[%d]: %w", i, err) + } + payload.Keys = append(payload.Keys, data) + } + l, err := r.ReadUint() + if err != nil { + return payload, fmt.Errorf("while reading Secrets length: %w", err) + } + data := make([]byte, l) + err = r.ReadDataFixed(data) + if err != nil { + return payload, fmt.Errorf("while reading Secrets: %w", err) + } + payload.Secrets = data + l, err = r.ReadUint() + if err != nil { + return payload, fmt.Errorf("while reading Will length: %w", err) + } + data = make([]byte, l) + err = r.ReadDataFixed(data) + if err != nil { + return payload, fmt.Errorf("while reading Will: %w", err) + } + payload.Will = data + + return payload, nil } func encrypt(plaintext, key []byte) ([]byte, error) {