bedrocktool/marketplace.go

95 lines
1.8 KiB
Go

package main
import (
"archive/zip"
"bytes"
"crypto/aes"
"encoding/json"
"io"
"os"
)
// decrypt using cfb with segmentsize = 1
func cfb_decrypt(data []byte, key []byte) ([]byte, error) {
b, err := aes.NewCipher([]byte(key))
if err != nil {
return nil, err
}
shift_register := append(key[:16], data...) // prefill with iv + cipherdata
_tmp := make([]byte, 16)
off := 0
for off < len(data) {
b.Encrypt(_tmp, shift_register)
data[off] ^= _tmp[0]
shift_register = shift_register[1:]
off++
}
return data, nil
}
type ContentEntry struct {
Path string `json:"path"`
Key string `json:"key"`
}
type ContentJson struct {
Content []ContentEntry `json:"content"`
}
func decrypt_pack(pack_zip []byte, filename, key string) error {
// open reader and writers
r := bytes.NewReader(pack_zip)
z, err := zip.NewReader(r, r.Size())
if err != nil {
return err
}
f, err := os.Create(filename)
if err != nil {
return err
}
zw := zip.NewWriter(f)
defer f.Close()
defer zw.Close()
written := make(map[string]interface{})
// read content json file
var content ContentJson
{
ff, err := z.Open("contents.json")
if err != nil {
return err
}
buf, _ := io.ReadAll(ff)
dec, _ := cfb_decrypt(buf[0x100:], []byte(key))
fw, _ := zw.Create("contents.json")
fw.Write(dec)
if err := json.Unmarshal(dec, &content); err != nil {
return err
}
written["contents.json"] = true
}
// copy and decrypt all content
for _, entry := range content.Content {
ff, _ := z.Open(entry.Path)
buf, _ := io.ReadAll(ff)
if entry.Key != "" {
buf, _ = cfb_decrypt(buf, []byte(entry.Key))
}
fw, _ := zw.Create(entry.Path)
fw.Write(buf)
written[entry.Path] = true
}
// copy everything not in the contents file
for _, src_file := range z.File {
if written[src_file.Name] == nil {
zw.Copy(src_file)
}
}
return nil
}