feat: working in process

This commit is contained in:
2024-09-01 17:44:33 +08:00
parent 84c0e2e872
commit df2a6d45b7
4 changed files with 185 additions and 159 deletions

View File

@@ -1,11 +1,18 @@
package encfs
import (
"crypto/aes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"math"
"os"
"strings"
"syscall"
"github.com/spf13/afero"
@@ -52,7 +59,7 @@ func newEncFileMeta(name string) (*EncFileMeta, error) {
}
func openEncFileMeta(name string) (*EncFileMeta, error) {
encFileMetaName := name + "." + EncFileExt
encFileMetaName := name + EncFileExt
encFileMetaFile, err := os.Open(encFileMetaName)
if err != nil {
if os.IsNotExist(err) {
@@ -91,10 +98,12 @@ type EncFile struct {
isDir bool
closed bool
encFileMeta *EncFileMeta
encFs *EncFs
filePos int64
file *os.File
}
func NewEncFile(name string, file *os.File, isCreate bool) (*EncFile, error) {
func NewEncFile(name string, file *os.File, encFs *EncFs, isCreate bool) (*EncFile, error) {
fileInfo, err := file.Stat()
if err != nil {
return nil, err
@@ -115,6 +124,8 @@ func NewEncFile(name string, file *os.File, isCreate bool) (*EncFile, error) {
isDir: isDir,
closed: false,
encFileMeta: encFileMeta,
encFs: encFs,
filePos: 0,
file: file,
}, nil
}
@@ -134,8 +145,21 @@ func (f *EncFile) Read(p []byte) (n int, err error) {
return 0, checkIsFileErr
}
// TODO decrypt
return f.file.Read(p)
beforeReadFilePos := f.filePos
readLen, err := f.file.Read(p)
if err == nil {
f.filePos += int64(readLen)
if f.encFs != nil && f.encFs.key != nil && f.encFileMeta != nil {
encryptedBytes, err := generateCtrEncryptBytes(f.encFs.key, f.encFileMeta.Iv, beforeReadFilePos, int64(readLen))
if err != nil {
return 0, err
}
for i := 0; i < readLen; i++ {
p[i] = p[i] ^ encryptedBytes[i]
}
}
}
return readLen, err
}
func (f *EncFile) ReadAt(p []byte, off int64) (n int, err error) {
@@ -153,8 +177,6 @@ func (f *EncFile) Seek(offset int64, whence int) (int64, error) {
if checkIsFileErr != nil {
return 0, checkIsFileErr
}
// TODO decrypt
return f.file.Seek(offset, whence)
}
@@ -164,8 +186,24 @@ func (f *EncFile) Write(p []byte) (n int, err error) {
return 0, checkIsFileErr
}
// TODO encrypt
return f.file.Write(p)
writeBuff := p
if f.encFs != nil && f.encFs.key != nil && f.encFileMeta != nil {
buff := make([]byte, len(p))
encryptedBytes, err := generateCtrEncryptBytes(f.encFs.key, f.encFileMeta.Iv, f.filePos, int64(len(p)))
if err != nil {
return 0, err
}
for i := 0; i < len(p); i++ {
buff[i] = p[i] ^ encryptedBytes[i]
}
writeBuff = buff
}
writeLen, err := f.file.Write(writeBuff)
if err == nil {
f.filePos += int64(writeLen)
}
return writeLen, err
}
func (f *EncFile) WriteAt(p []byte, off int64) (n int, err error) {
@@ -174,8 +212,24 @@ func (f *EncFile) WriteAt(p []byte, off int64) (n int, err error) {
return 0, checkIsFileErr
}
// TODO encrypt
return f.file.WriteAt(p, off)
writeBuff := p
if f.encFs != nil && f.encFs.key != nil && f.encFileMeta != nil {
buff := make([]byte, len(p))
encryptedBytes, err := generateCtrEncryptBytes(f.encFs.key, f.encFileMeta.Iv, off, int64(len(p)))
if err != nil {
return 0, err
}
for i := 0; i < len(p); i++ {
buff[i] = p[i] ^ encryptedBytes[i]
}
writeBuff = buff
}
writeLen, err := f.file.WriteAt(writeBuff, off)
// if err == nil {
// f.filePos += int64(writeLen)
// }
return writeLen, err
}
func (f *EncFile) Name() string {
@@ -187,7 +241,27 @@ func (f *EncFile) Readdir(count int) ([]os.FileInfo, error) {
return nil, afero.ErrFileClosed
}
return f.file.Readdir(count)
// FIXME is count * 2 just ok?
fileInfos, err := f.file.Readdir(count * 2)
if err != nil {
return nil, err
}
if count == 0 {
return make([]fs.FileInfo, 0), nil
}
filterFileInfos := make([]os.FileInfo, 0)
for _, fileInfo := range fileInfos {
isEncFileMetaFile := strings.HasSuffix(fileInfo.Name(), EncFileExt)
if !isEncFileMetaFile {
filterFileInfos = append(filterFileInfos, fileInfo)
}
if count >= 0 && len(filterFileInfos) >= count {
break
}
}
return filterFileInfos, nil
}
func (f *EncFile) Readdirnames(n int) ([]string, error) {
@@ -230,3 +304,46 @@ func (f *EncFile) checkIsFile() error {
}
return nil
}
func generateCtrEncryptBytes(key, iv []byte, offset, len int64) ([]byte, error) {
endOffset := offset + len
encryptStartOffset := (offset / 16) * 16
encryptEndOffset := (endOffset / 16) * 16
if endOffset%16 > 0 {
encryptEndOffset += 16
}
blocksCount := int((encryptEndOffset - encryptStartOffset) / 16)
cipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
encryptBytes := make([]byte, blocksCount*16)
for i := 0; i < blocksCount; i++ {
encNonce := nonceAdd(iv, uint64(i))
cipher.Encrypt(encryptBytes[i*16:(i+1)*16], encNonce)
}
// fmt.Println("XX ", hex.EncodeToString(encryptBytes))
encryptedBytes := encryptBytes[offset-encryptStartOffset : offset-encryptStartOffset+len]
fmt.Println("XX", hex.EncodeToString(key), hex.EncodeToString(iv), offset, len, hex.EncodeToString(encryptedBytes))
return encryptedBytes, nil
}
func nonceAdd(nonce []byte, incrementValue uint64) []byte {
n1 := binary.BigEndian.Uint64(nonce[:8])
n2 := binary.BigEndian.Uint64(nonce[8:])
leftToMax := math.MaxUint64 - n2
if leftToMax <= incrementValue {
incrementValue -= leftToMax + 1
n2 = incrementValue
n1 += 1
} else {
n2 += incrementValue
}
newNonce := make([]byte, 16)
binary.BigEndian.PutUint64(newNonce, n1)
binary.BigEndian.PutUint64(newNonce[8:], n2)
return newNonce
}