build test funcs
This commit is contained in:
parent
f388fcf9ee
commit
51003e492b
14 changed files with 291 additions and 1 deletions
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
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.
|
43
README.md
43
README.md
|
@ -1,3 +1,46 @@
|
||||||
# bloat
|
# bloat
|
||||||
|
|
||||||
> XML serialization version. for ActivityPub see dogberry
|
> XML serialization version. for ActivityPub see dogberry
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Read
|
||||||
|
- [ ] serialize
|
||||||
|
- [ ] decrypt
|
||||||
|
- [ ] verify
|
||||||
|
- [ ] Write
|
||||||
|
- [ ] sign
|
||||||
|
- [ ] encrypt
|
||||||
|
- [ ] deserialize
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- notes on deletions:
|
||||||
|
|
||||||
|
- /host.xml
|
||||||
|
- /group/
|
||||||
|
- /index.xml <-
|
||||||
|
- /indexes/
|
||||||
|
- /{peer name}/
|
||||||
|
- /passwords.xml <- encrypted to a peer
|
||||||
|
- /posts.a.xml <-
|
||||||
|
- /posts.b.xml <-
|
||||||
|
|
||||||
|
|
||||||
|
- options:
|
||||||
|
- encrypt each post to every group member
|
||||||
|
- pros:
|
||||||
|
- safe if they haven't downloaded something
|
||||||
|
- cons:
|
||||||
|
- removing a member means rewriting each post
|
||||||
|
- adding a member means rewriting each post
|
||||||
|
- encrypt a password file next to each post
|
||||||
|
- pros:
|
||||||
|
- don't need to upload the content twice
|
||||||
|
- cons:
|
||||||
|
- need a password file for each member (n x m storage)
|
||||||
|
- encrypt an index file
|
||||||
|
- pros:
|
||||||
|
- need o(n) storage
|
||||||
|
- cons:
|
||||||
|
- if they've downloaded the index they have the passwords to the files
|
17
decrypt.go
17
decrypt.go
|
@ -1 +1,18 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"filippo.io/age"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Decrypt(src []byte) ([]byte, error) {
|
||||||
|
input := bytes.NewReader(src)
|
||||||
|
out, err := age.Decrypt(input, &b.encDec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res, err := io.ReadAll(out)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
18
encrypt.go
18
encrypt.go
|
@ -1 +1,19 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"filippo.io/age"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Encrypt(plain []byte) ([]byte, error) {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
w, err := age.Encrypt(buf, &b.EncPub) // my wrapper doesn't support multiple recipients yet
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
var r string
|
||||||
|
_, err = io.WriteString(w, r)
|
||||||
|
return []byte(r), err
|
||||||
|
}
|
||||||
|
|
10
go.mod
10
go.mod
|
@ -1,3 +1,13 @@
|
||||||
module git.bivouac.wiki/go/bloat
|
module git.bivouac.wiki/go/bloat
|
||||||
|
|
||||||
go 1.22.5
|
go 1.22.5
|
||||||
|
|
||||||
|
require (
|
||||||
|
aead.dev/minisign v0.3.0
|
||||||
|
filippo.io/age v1.2.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/crypto v0.24.0 // indirect
|
||||||
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
|
)
|
||||||
|
|
8
go.sum
Normal file
8
go.sum
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
aead.dev/minisign v0.3.0 h1:8Xafzy5PEVZqYDNP60yJHARlW1eOQtsKNp/Ph2c0vRA=
|
||||||
|
aead.dev/minisign v0.3.0/go.mod h1:NLvG3Uoq3skkRMDuc3YHpWUTMTrSExqm+Ij73W13F6Y=
|
||||||
|
filippo.io/age v1.2.1 h1:X0TZjehAZylOIj4DubWYU1vWQxv9bJpo+Uu2/LGhi1o=
|
||||||
|
filippo.io/age v1.2.1/go.mod h1:JL9ew2lTN+Pyft4RiNGguFfOpewKwSHm5ayKD/A4004=
|
||||||
|
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||||
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
@ -1 +1,8 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Marshal(body T) ([]byte, error) {
|
||||||
|
final, err := xml.Marshal(body)
|
||||||
|
return final, err
|
||||||
|
}
|
||||||
|
|
47
module_test.go
Normal file
47
module_test.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestItem(t *testing.T) {
|
||||||
|
type typ struct {
|
||||||
|
A int
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
data := typ{
|
||||||
|
A: 1,
|
||||||
|
B: "hello",
|
||||||
|
}
|
||||||
|
trySender, err := NewBloat[typ]()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("error on newbloat")
|
||||||
|
}
|
||||||
|
trySender.Obj = typ{}
|
||||||
|
tryReceiver, err := NewBloat[typ]()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("error on newbloat")
|
||||||
|
}
|
||||||
|
cyphertext, err := trySender.Write(data, tryReceiver)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("error on write")
|
||||||
|
}
|
||||||
|
plainobj, err := tryReceiver.Read(cyphertext, trySender)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("error on read")
|
||||||
|
}
|
||||||
|
if plainobj.A != 1 {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("int not equal")
|
||||||
|
}
|
||||||
|
if plainobj.B != "hello" {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Errorf("string not hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
obj.go
Normal file
37
obj.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
|
||||||
|
"aead.dev/minisign"
|
||||||
|
"filippo.io/age"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bloat[T any] struct {
|
||||||
|
SignPub minisign.PublicKey
|
||||||
|
signPriv minisign.PrivateKey
|
||||||
|
EncPub age.X25519Recipient
|
||||||
|
encDec age.X25519Identity // Scrypt is the password one?
|
||||||
|
Obj T
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBloat[T any]() (Bloat[T], error) {
|
||||||
|
|
||||||
|
pub, sign, err := minisign.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return Bloat[T]{}, err
|
||||||
|
}
|
||||||
|
enc, err := age.GenerateX25519Identity()
|
||||||
|
if err != nil {
|
||||||
|
return Bloat[T]{}, err
|
||||||
|
}
|
||||||
|
recip := enc.Recipient()
|
||||||
|
|
||||||
|
res := Bloat[T]{
|
||||||
|
SignPub: pub,
|
||||||
|
signPriv: sign,
|
||||||
|
EncPub: *recip,
|
||||||
|
encDec: *enc,
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
19
read.go
19
read.go
|
@ -1 +1,20 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Read(packed []byte, author Bloat[T]) (T, error) {
|
||||||
|
var final T
|
||||||
|
decrypted, err := b.Decrypt(packed) // our own key
|
||||||
|
if err != nil {
|
||||||
|
return final, err
|
||||||
|
}
|
||||||
|
body, verified, err := author.Verify(decrypted) // author's key
|
||||||
|
if err != nil {
|
||||||
|
return final, err
|
||||||
|
}
|
||||||
|
if !verified {
|
||||||
|
return final, errors.New("not verified")
|
||||||
|
}
|
||||||
|
final, err = b.Unmarshal(body)
|
||||||
|
return final, err
|
||||||
|
}
|
||||||
|
|
15
sign.go
15
sign.go
|
@ -1 +1,16 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"aead.dev/minisign"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sign the payload and append 4 lines
|
||||||
|
func (b *Bloat[T]) Sign(plaintext []byte) ([]byte, error) {
|
||||||
|
|
||||||
|
signature := minisign.Sign(b.signPriv, plaintext)
|
||||||
|
parts := [][]byte{plaintext, signature}
|
||||||
|
final := bytes.Join(parts, []byte("\n"))
|
||||||
|
return final, nil
|
||||||
|
}
|
||||||
|
|
17
unmarshal.go
17
unmarshal.go
|
@ -1 +1,18 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
/*
|
||||||
|
types to decode:
|
||||||
|
.phish (identity)
|
||||||
|
.bivouac (decisions)
|
||||||
|
.cicada (indexes/feeds)
|
||||||
|
.crew (groups)
|
||||||
|
.mores (rules)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Unmarshal(plain []byte) (T, error) {
|
||||||
|
err := xml.Unmarshal(plain, b.Obj)
|
||||||
|
return b.Obj, err
|
||||||
|
}
|
||||||
|
|
18
verify.go
18
verify.go
|
@ -1 +1,19 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"aead.dev/minisign"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify checks the minisign signature and returns the body if valid.
|
||||||
|
func (b *Bloat[T]) Verify(message []byte) ([]byte, bool, error) {
|
||||||
|
// signature is last 4 lines:
|
||||||
|
separated := bytes.Split(message, []byte("\n"))
|
||||||
|
signature := bytes.Join(separated[len(separated)-4:len(separated)], []byte("\n"))
|
||||||
|
body := bytes.Join(separated[:len(separated)-4], []byte("\n"))
|
||||||
|
if !minisign.Verify(b.SignPub, body, signature) {
|
||||||
|
return []byte(""), false, nil
|
||||||
|
}
|
||||||
|
return body, true, nil
|
||||||
|
}
|
||||||
|
|
13
write.go
13
write.go
|
@ -1 +1,14 @@
|
||||||
package bloat
|
package bloat
|
||||||
|
|
||||||
|
func (b *Bloat[T]) Write(body T, recip Bloat[T]) ([]byte, error) {
|
||||||
|
start, err := b.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signed, err := b.Sign(start) // our key
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
final, err := recip.Encrypt(signed) // their key
|
||||||
|
return final, err
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue