253 lines
5.2 KiB
Go
253 lines
5.2 KiB
Go
package encoder
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"local/encryptor"
|
|
"os"
|
|
"path"
|
|
)
|
|
|
|
type Encoder struct {
|
|
bops []BOP
|
|
}
|
|
|
|
func New(config *Config, bops ...BOP) (*Encoder, error) {
|
|
if len(bops) != 0 {
|
|
return &Encoder{bops: bops}, nil
|
|
}
|
|
|
|
bops = []BOP{
|
|
&Zipper{},
|
|
&Salter{},
|
|
}
|
|
|
|
if config != nil {
|
|
if config.SymKey != "" {
|
|
bops = append(bops, &AES{Key: []byte(config.SymKey)})
|
|
}
|
|
|
|
if !config.SymKeyOnly {
|
|
var encr encryptor.Encryptor
|
|
if path.Base(config.KeyPath) == "env" {
|
|
pub := os.Getenv("PUB")
|
|
pri := os.Getenv("PRI")
|
|
if pub == "" || pri == "" {
|
|
return nil, errors.New("PUB and PRI cannot be empty")
|
|
}
|
|
encr = encryptor.NewEncryptor(pri, pub, false)
|
|
} else if config.KeyPath != "" {
|
|
encr = encryptor.NewEncryptor("", "", false)
|
|
priKeyPath := path.Join(config.KeyPath, "key.pri")
|
|
pubKeyPath := path.Join(config.KeyPath, "key.pub")
|
|
defer encr.ToFiles(priKeyPath, pubKeyPath)
|
|
if err := encr.FromFiles(priKeyPath, pubKeyPath); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
encr = encryptor.NewEncryptor("", "", false)
|
|
}
|
|
bops = append(bops, &asymCryptor{Encryptor: encr})
|
|
}
|
|
}
|
|
|
|
bops = append(bops, &Zipper{})
|
|
return &Encoder{
|
|
bops: bops,
|
|
}, nil
|
|
}
|
|
|
|
func (e *Encoder) Encode2(r io.Reader) (io.Reader, error) {
|
|
pipeR, pipeW := io.Pipe()
|
|
go func() {
|
|
defer pipeW.Close()
|
|
for i := 0; i < len(e.bops); i++ {
|
|
r = e.bops[i].(BOP2).Wrap2(r)
|
|
}
|
|
if _, err := io.Copy(pipeW, r); err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
return pipeR, nil
|
|
}
|
|
|
|
func (e *Encoder) Decode2(r io.Reader) (io.Reader, error) {
|
|
pipeR, pipeW := io.Pipe()
|
|
go func() {
|
|
defer pipeW.Close()
|
|
r = screenReader(r)
|
|
for i := len(e.bops) - 1; i >= 0; i-- {
|
|
r = e.bops[i].(BOP2).Unwrap2(r)
|
|
r = screenReader(r)
|
|
}
|
|
if _, err := io.Copy(pipeW, r); err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
return pipeR, nil
|
|
}
|
|
|
|
func (e *Encoder) Encode3(r io.Reader) (io.Reader, error) {
|
|
pipeR, pipeW := io.Pipe()
|
|
|
|
bopCh := make([]chan []byte, len(e.bops)+1)
|
|
inputChIndex := len(bopCh) - 1
|
|
bopCh[inputChIndex] = make(chan []byte)
|
|
//[0]=bops[0]([n+1])
|
|
//[1]=bops[1]([0])
|
|
//...
|
|
//[n]=bops[n]([n-1])
|
|
//[n+1]=firstin
|
|
for i := range e.bops {
|
|
bopCh[i] = e.bops[i].(BOP3).Wrap3(bopCh[(i-1+len(bopCh))%len(bopCh)])
|
|
}
|
|
go func() {
|
|
defer pipeW.Close()
|
|
for input := range bopCh[inputChIndex-1] {
|
|
if _, err := pipeW.Write(input); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}()
|
|
go func() {
|
|
defer close(bopCh[inputChIndex])
|
|
buff := make([]byte, 64000)
|
|
for {
|
|
n, err := r.Read(buff)
|
|
if err != nil && err != io.EOF {
|
|
panic(err)
|
|
}
|
|
if n > 0 {
|
|
bopCh[inputChIndex] <- copyBSlice(buff[:n])
|
|
}
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
return pipeR, nil
|
|
}
|
|
|
|
func (e *Encoder) Decode3(r io.Reader) (io.Reader, error) {
|
|
pipeR, pipeW := io.Pipe()
|
|
|
|
bopCh := make([]chan []byte, len(e.bops)+1)
|
|
inputChIndex := len(bopCh) - 1
|
|
bopCh[inputChIndex] = make(chan []byte)
|
|
//[0]=bops[0]([1])
|
|
//[1]=bops[1]([2])
|
|
//...
|
|
//[n]=bops[n]([n+1])
|
|
//[n+1]=firstin
|
|
for i := len(e.bops) - 1; i >= 0; i-- {
|
|
bopCh[i] = e.bops[i].(BOP3).Unwrap3(bopCh[i+1])
|
|
}
|
|
go func() {
|
|
defer pipeW.Close()
|
|
for input := range bopCh[0] {
|
|
if _, err := pipeW.Write(input); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}()
|
|
go func() {
|
|
defer close(bopCh[inputChIndex])
|
|
buff := make([]byte, 64000)
|
|
for {
|
|
n, err := r.Read(buff)
|
|
if err != nil && err != io.EOF {
|
|
panic(err)
|
|
}
|
|
if n > 0 {
|
|
bopCh[inputChIndex] <- copyBSlice(buff[:n])
|
|
}
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
return pipeR, nil
|
|
}
|
|
|
|
func (e *Encoder) Encode(payload []byte, metadata ...[]byte) ([]byte, error) {
|
|
if len(payload) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
for i := range e.bops {
|
|
payload = e.bops[i].Wrap(payload)
|
|
if len(payload) == 0 {
|
|
return nil, errors.New("cannot encode payload")
|
|
}
|
|
}
|
|
|
|
return e.WriteMetadata(payload, metadata)
|
|
}
|
|
|
|
func (e *Encoder) Decode(payload []byte) ([]byte, error) {
|
|
metalen, err := e.metadataLength(payload)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
payload = payload[metalen:]
|
|
|
|
if len(payload) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
for i := len(e.bops); i > 0; i-- {
|
|
payload = e.bops[i-1].Unwrap(payload)
|
|
if len(payload) == 0 {
|
|
return nil, errors.New("cannot decode payload")
|
|
}
|
|
}
|
|
|
|
return payload, nil
|
|
}
|
|
|
|
func (e *Encoder) WriteMetadata(payload []byte, metadata [][]byte) ([]byte, error) {
|
|
meta := []byte{byte(len(metadata))}
|
|
for i := range metadata {
|
|
meta = append(meta, byte(len(metadata[i])))
|
|
meta = append(meta, metadata[i]...)
|
|
}
|
|
payload = append(meta, payload...)
|
|
return payload, nil
|
|
}
|
|
|
|
func (e *Encoder) ReadMetadata(payload []byte) ([][]byte, error) {
|
|
metadata := [][]byte{}
|
|
if len(payload) < 2 {
|
|
return nil, nil
|
|
}
|
|
metalen := int(payload[0])
|
|
payload = payload[1:]
|
|
for i := 0; i < metalen; i++ {
|
|
if len(payload) < 1 {
|
|
return nil, nil
|
|
}
|
|
j := payload[0]
|
|
if len(payload) < 1+int(j) {
|
|
return nil, nil
|
|
}
|
|
metadata = append(metadata, payload[1:1+int(j)])
|
|
payload = payload[1+int(j):]
|
|
}
|
|
return metadata, nil
|
|
}
|
|
|
|
func (e *Encoder) metadataLength(payload []byte) (int, error) {
|
|
metadata, err := e.ReadMetadata(payload)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
n := 1
|
|
for i := range metadata {
|
|
n += 1 + len(metadata[i])
|
|
}
|
|
if len(payload) < n {
|
|
return 0, nil
|
|
}
|
|
return n, nil
|
|
}
|