This commit is contained in:
olebeck 2023-03-21 11:22:07 +01:00
parent 68890eddd2
commit 21566df29f
1 changed files with 45 additions and 26 deletions

View File

@ -30,7 +30,7 @@ type Content struct {
var StaticKey = []byte("s5s5ejuDru4uchuF2drUFuthaspAbepE") var StaticKey = []byte("s5s5ejuDru4uchuF2drUFuthaspAbepE")
func generateKey() (out []byte) { func GenerateKey() (out []byte) {
out = make([]byte, 32) out = make([]byte, 32)
var vocab = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") var vocab = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
@ -60,12 +60,14 @@ func canEncrypt(path string) bool {
} }
func enc(fsys fs.FS, fsyso fstest.MapFS, contentsJson *Content, dir string) error { func enc(fsys fs.FS, fsyso fstest.MapFS, contentsJson *Content, dir string) error {
// get all files in this folder
matches, err := fs.Glob(fsys, dir+"**") matches, err := fs.Glob(fsys, dir+"**")
if err != nil { if err != nil {
return err return err
} }
for _, path := range matches { for _, path := range matches {
// create output file
ifo, err := fs.Stat(fsys, path) ifo, err := fs.Stat(fsys, path)
if err != nil { if err != nil {
return err return err
@ -76,18 +78,21 @@ func enc(fsys fs.FS, fsyso fstest.MapFS, contentsJson *Content, dir string) erro
} }
fsyso[path] = fo fsyso[path] = fo
// recurse
if ifo.IsDir() { if ifo.IsDir() {
return enc(fsys, fsyso, contentsJson, path+"/") return enc(fsys, fsyso, contentsJson, path+"/")
} }
// read data
var data []byte var data []byte
data, err = fs.ReadFile(fsys, path) data, err = fs.ReadFile(fsys, path)
if err != nil { if err != nil {
return err return err
} }
if canEncrypt(path) && !ifo.IsDir() { // encrypt if needed
key := generateKey() if canEncrypt(path) {
key := GenerateKey()
it := contentItem{ it := contentItem{
Path: path, Path: path,
Key: hex.EncodeToString(key), Key: hex.EncodeToString(key),
@ -95,53 +100,66 @@ func enc(fsys fs.FS, fsyso fstest.MapFS, contentsJson *Content, dir string) erro
contentsJson.Content = append(contentsJson.Content, it) contentsJson.Content = append(contentsJson.Content, it)
encryptCfb(data, key) encryptCfb(data, key)
} }
// write to output
fo.Data = data fo.Data = data
} }
return nil return nil
} }
func Enc(fsys fs.FS, id *uuid.UUID, ContentKey []byte) (fs.FS, error) { func Enc(fsys fs.FS, id *uuid.UUID, ContentKey []byte) (fs.FS, error) {
if id == nil { var manifest map[string]any
f, err := fsys.Open("manifest.json")
if err != nil {
return nil, err
}
var manifest map[string]any // read the manifest
f, err := fsys.Open("manifest.json")
if err == nil {
dec := json.NewDecoder(f) dec := json.NewDecoder(f)
err = dec.Decode(&manifest) err = dec.Decode(&manifest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
header, ok := manifest["header"].(map[string]any) header, ok := manifest["header"].(map[string]any)
if !ok { if !ok {
return nil, errors.New("no header") return nil, errors.New("no header")
} }
idstr, ok := header["uuid"].(string)
if !ok {
return nil, errors.New("no id")
}
_id, err := uuid.Parse(idstr) // get id from manifest if not specified, else change it in the manifet
if err != nil { if id == nil {
idstr, ok := header["uuid"].(string)
if !ok {
return nil, errors.New("no id")
}
_id, err := uuid.Parse(idstr)
if err != nil {
return nil, err
}
id = &_id
} else {
header["uuid"] = id.String()
}
} else {
if id != nil {
// create a manifest
} else {
return nil, err return nil, err
} }
id = &_id
} }
if ContentKey == nil {
ContentKey = StaticKey
}
var contentsJson Content
fsyso := fstest.MapFS{} fsyso := fstest.MapFS{}
err := enc(fsys, fsyso, &contentsJson, "") // encrypt
var contentsJson Content
err = enc(fsys, fsyso, &contentsJson, "")
if err != nil { if err != nil {
return nil, err return nil, err
} }
// write new manifest
manifestData, _ := json.MarshalIndent(manifest, "", "\t")
fsyso["manifest.json"] = &fstest.MapFile{
Data: manifestData,
}
// write the contents.json encrypted
contentsBuf := bytes.NewBuffer(nil) contentsBuf := bytes.NewBuffer(nil)
binary.Write(contentsBuf, binary.LittleEndian, uint32(0)) binary.Write(contentsBuf, binary.LittleEndian, uint32(0))
binary.Write(contentsBuf, binary.LittleEndian, uint32(0x9bcfb9fc)) binary.Write(contentsBuf, binary.LittleEndian, uint32(0x9bcfb9fc))
@ -149,11 +167,9 @@ func Enc(fsys fs.FS, id *uuid.UUID, ContentKey []byte) (fs.FS, error) {
contentsBuf.WriteByte(byte(len(id.String()))) contentsBuf.WriteByte(byte(len(id.String())))
contentsBuf.Write([]byte(id.String())) contentsBuf.Write([]byte(id.String()))
contentsBuf.Write(make([]byte, 0xff-contentsBuf.Len())) contentsBuf.Write(make([]byte, 0xff-contentsBuf.Len()))
contentsData, _ := json.Marshal(&contentsJson) contentsData, _ := json.Marshal(&contentsJson)
encryptCfb(contentsData, ContentKey) encryptCfb(contentsData, ContentKey)
contentsBuf.Write(contentsData) contentsBuf.Write(contentsData)
fsyso["contents.json"] = &fstest.MapFile{ fsyso["contents.json"] = &fstest.MapFile{
Data: contentsBuf.Bytes(), Data: contentsBuf.Bytes(),
Mode: 0775, Mode: 0775,
@ -164,15 +180,18 @@ func Enc(fsys fs.FS, id *uuid.UUID, ContentKey []byte) (fs.FS, error) {
} }
func fstozip(fsys fs.FS, zw *zip.Writer, dir string) error { func fstozip(fsys fs.FS, zw *zip.Writer, dir string) error {
// get files in this folder
matches, err := fs.Glob(fsys, dir+"**") matches, err := fs.Glob(fsys, dir+"**")
if err != nil { if err != nil {
return err return err
} }
for _, path := range matches { for _, path := range matches {
// if this path is a folder, recurse
ifo, _ := fs.Stat(fsys, path) ifo, _ := fs.Stat(fsys, path)
if ifo.IsDir() { if ifo.IsDir() {
return fstozip(fsys, zw, path+"/") return fstozip(fsys, zw, path+"/")
} }
// copy the file to the zip
w, err := zw.CreateHeader(&zip.FileHeader{ w, err := zw.CreateHeader(&zip.FileHeader{
Name: ifo.Name(), Name: ifo.Name(),
Modified: ifo.ModTime(), Modified: ifo.ModTime(),