diff --git a/utils/encryptor/enc.go b/utils/encryptor/enc.go index 1d15de8..ff95d2c 100644 --- a/utils/encryptor/enc.go +++ b/utils/encryptor/enc.go @@ -30,7 +30,7 @@ type Content struct { var StaticKey = []byte("s5s5ejuDru4uchuF2drUFuthaspAbepE") -func generateKey() (out []byte) { +func GenerateKey() (out []byte) { out = make([]byte, 32) var vocab = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") 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 { + // get all files in this folder matches, err := fs.Glob(fsys, dir+"**") if err != nil { return err } for _, path := range matches { + // create output file ifo, err := fs.Stat(fsys, path) if err != nil { return err @@ -76,18 +78,21 @@ func enc(fsys fs.FS, fsyso fstest.MapFS, contentsJson *Content, dir string) erro } fsyso[path] = fo + // recurse if ifo.IsDir() { return enc(fsys, fsyso, contentsJson, path+"/") } + // read data var data []byte data, err = fs.ReadFile(fsys, path) if err != nil { return err } - if canEncrypt(path) && !ifo.IsDir() { - key := generateKey() + // encrypt if needed + if canEncrypt(path) { + key := GenerateKey() it := contentItem{ Path: path, 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) encryptCfb(data, key) } + + // write to output fo.Data = data } return nil } func Enc(fsys fs.FS, id *uuid.UUID, ContentKey []byte) (fs.FS, error) { - if id == nil { - f, err := fsys.Open("manifest.json") - if err != nil { - return nil, err - } + var manifest map[string]any - var manifest map[string]any + // read the manifest + f, err := fsys.Open("manifest.json") + if err == nil { dec := json.NewDecoder(f) err = dec.Decode(&manifest) if err != nil { return nil, err } - header, ok := manifest["header"].(map[string]any) if !ok { return nil, errors.New("no header") } - idstr, ok := header["uuid"].(string) - if !ok { - return nil, errors.New("no id") - } - _id, err := uuid.Parse(idstr) - if err != nil { + // get id from manifest if not specified, else change it in the manifet + 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 } - id = &_id } - if ContentKey == nil { - ContentKey = StaticKey - } - - var contentsJson Content - fsyso := fstest.MapFS{} - err := enc(fsys, fsyso, &contentsJson, "") + // encrypt + var contentsJson Content + err = enc(fsys, fsyso, &contentsJson, "") if err != nil { 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) binary.Write(contentsBuf, binary.LittleEndian, uint32(0)) 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.Write([]byte(id.String())) contentsBuf.Write(make([]byte, 0xff-contentsBuf.Len())) - contentsData, _ := json.Marshal(&contentsJson) encryptCfb(contentsData, ContentKey) contentsBuf.Write(contentsData) - fsyso["contents.json"] = &fstest.MapFile{ Data: contentsBuf.Bytes(), 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 { + // get files in this folder matches, err := fs.Glob(fsys, dir+"**") if err != nil { return err } for _, path := range matches { + // if this path is a folder, recurse ifo, _ := fs.Stat(fsys, path) if ifo.IsDir() { return fstozip(fsys, zw, path+"/") } + // copy the file to the zip w, err := zw.CreateHeader(&zip.FileHeader{ Name: ifo.Name(), Modified: ifo.ModTime(),