feat: still working
This commit is contained in:
17
README.md
17
README.md
@@ -7,7 +7,7 @@ In stage 1 we only encrypt file content, the file name is not encrypted.
|
|||||||
In the future we are going to encrypt the file name also.
|
In the future we are going to encrypt the file name also.
|
||||||
|
|
||||||
|
|
||||||
<br>
|
## AES-CTR Introduction
|
||||||
|
|
||||||
AES-CTR algorithm is show as: https://git.hatter.ink/hatter/simple-rust-tests/src/branch/master/__crypto/aes_ctr_test/src/main.rs
|
AES-CTR algorithm is show as: https://git.hatter.ink/hatter/simple-rust-tests/src/branch/master/__crypto/aes_ctr_test/src/main.rs
|
||||||
|
|
||||||
@@ -31,7 +31,20 @@ for counter in 0..plaintext_block_count {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<br>
|
## EncFile Spec
|
||||||
|
|
||||||
|
File ext `*.__encfile`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"iv": "<16 bytes IV in base64>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> if `*.__encfile` not found, then file is unencrypted.
|
||||||
|
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
Related projects:
|
Related projects:
|
||||||
* https://github.com/spf13/afero
|
* https://github.com/spf13/afero
|
||||||
|
|||||||
159
encfs/file.go
159
encfs/file.go
@@ -1,111 +1,103 @@
|
|||||||
package encfs
|
package encfs
|
||||||
|
|
||||||
type EncFile struct {}
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
func (f *File) Close() error {
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EncFile struct {
|
||||||
|
isDir bool
|
||||||
|
closed bool
|
||||||
|
file *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEncFile(file *os.File) (*EncFile, error) {
|
||||||
|
fileInfo, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
isDir := fileInfo.IsDir()
|
||||||
|
return &EncFile{
|
||||||
|
isDir: isDir,
|
||||||
|
closed: false,
|
||||||
|
file: file,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *EncFile) Close() error {
|
||||||
if f.closed {
|
if f.closed {
|
||||||
return afero.ErrFileClosed
|
return afero.ErrFileClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
f.closed = true
|
f.closed = true
|
||||||
f.h = nil
|
return f.file.Close()
|
||||||
f.data = nil
|
|
||||||
f.fs = nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Read(p []byte) (n int, err error) {
|
func (f *EncFile) Read(p []byte) (n int, err error) {
|
||||||
if f.closed {
|
checkIsFileErr := f.checkIsFile()
|
||||||
return 0, afero.ErrFileClosed
|
if checkIsFileErr != nil {
|
||||||
|
return 0, checkIsFileErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.h.Typeflag == tar.TypeDir {
|
// TODO decrypt
|
||||||
return 0, syscall.EISDIR
|
return f.file.Read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.data.Read(p)
|
func (f *EncFile) ReadAt(p []byte, off int64) (n int, err error) {
|
||||||
|
checkIsFileErr := f.checkIsFile()
|
||||||
|
if checkIsFileErr != nil {
|
||||||
|
return 0, checkIsFileErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) ReadAt(p []byte, off int64) (n int, err error) {
|
// TODO decrypt
|
||||||
if f.closed {
|
return f.file.ReadAt(p, off)
|
||||||
return 0, afero.ErrFileClosed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.h.Typeflag == tar.TypeDir {
|
func (f *EncFile) Seek(offset int64, whence int) (int64, error) {
|
||||||
return 0, syscall.EISDIR
|
checkIsFileErr := f.checkIsFile()
|
||||||
|
if checkIsFileErr != nil {
|
||||||
|
return 0, checkIsFileErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.data.ReadAt(p, off)
|
// TODO decrypt
|
||||||
|
return f.file.Seek(offset, whence)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
func (f *EncFile) Write(p []byte) (n int, err error) {
|
||||||
if f.closed {
|
checkIsFileErr := f.checkIsFile()
|
||||||
return 0, afero.ErrFileClosed
|
if checkIsFileErr != nil {
|
||||||
|
return 0, checkIsFileErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.h.Typeflag == tar.TypeDir {
|
// TODO encrypt
|
||||||
return 0, syscall.EISDIR
|
return f.file.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.data.Seek(offset, whence)
|
func (f *EncFile) WriteAt(p []byte, off int64) (n int, err error) {
|
||||||
|
checkIsFileErr := f.checkIsFile()
|
||||||
|
if checkIsFileErr != nil {
|
||||||
|
return 0, checkIsFileErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Write(p []byte) (n int, err error) { return 0, syscall.EROFS }
|
// TODO encrypt
|
||||||
|
return f.file.WriteAt(p, off)
|
||||||
func (f *File) WriteAt(p []byte, off int64) (n int, err error) { return 0, syscall.EROFS }
|
|
||||||
|
|
||||||
func (f *File) Name() string {
|
|
||||||
return filepath.Join(splitpath(f.h.Name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) getDirectoryNames() ([]string, error) {
|
func (f *EncFile) Name() string {
|
||||||
d, ok := f.fs.files[f.Name()]
|
return f.file.Name()
|
||||||
if !ok {
|
|
||||||
return nil, &os.PathError{Op: "readdir", Path: f.Name(), Err: syscall.ENOENT}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var names []string
|
func (f *EncFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||||
for n := range d {
|
|
||||||
names = append(names, n)
|
|
||||||
}
|
|
||||||
sort.Strings(names)
|
|
||||||
|
|
||||||
return names, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
|
||||||
if f.closed {
|
if f.closed {
|
||||||
return nil, afero.ErrFileClosed
|
return nil, afero.ErrFileClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.h.FileInfo().IsDir() {
|
return f.file.Readdir(count)
|
||||||
return nil, syscall.ENOTDIR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
names, err := f.getDirectoryNames()
|
func (f *EncFile) Readdirnames(n int) ([]string, error) {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d := f.fs.files[f.Name()]
|
|
||||||
var fi []os.FileInfo
|
|
||||||
for _, n := range names {
|
|
||||||
if n == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
f := d[n]
|
|
||||||
fi = append(fi, f.h.FileInfo())
|
|
||||||
if count > 0 && len(fi) >= count {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fi, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *File) Readdirnames(n int) ([]string, error) {
|
|
||||||
fi, err := f.Readdir(n)
|
fi, err := f.Readdir(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -119,10 +111,29 @@ func (f *File) Readdirnames(n int) ([]string, error) {
|
|||||||
return names, nil
|
return names, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Stat() (os.FileInfo, error) { return f.h.FileInfo(), nil }
|
func (f *EncFile) Stat() (os.FileInfo, error) {
|
||||||
|
return f.file.Stat()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *File) Sync() error { return nil }
|
func (f *EncFile) Sync() error {
|
||||||
|
return f.file.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *File) Truncate(size int64) error { return syscall.EROFS }
|
func (f *EncFile) Truncate(size int64) error {
|
||||||
|
return f.file.Truncate(size)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *File) WriteString(s string) (ret int, err error) { return 0, syscall.EROFS }
|
func (f *EncFile) WriteString(s string) (ret int, err error) {
|
||||||
|
// TODO encrypt
|
||||||
|
return f.file.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *EncFile) checkIsFile() error {
|
||||||
|
if f.closed {
|
||||||
|
return afero.ErrFileClosed
|
||||||
|
}
|
||||||
|
if f.isDir {
|
||||||
|
return syscall.EISDIR
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
29
encfs/fs.go
29
encfs/fs.go
@@ -3,26 +3,28 @@ package encfs
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copied from afero/os.go
|
// copied from afero/os.go
|
||||||
|
|
||||||
type EncFs struct{}
|
type EncFs struct{}
|
||||||
|
|
||||||
func NewEncFs() Fs {
|
func NewEncFs() afero.Fs {
|
||||||
return &EncFs{}
|
return &EncFs{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) Name() string { return "EncFs" }
|
func (EncFs) Name() string { return "EncFs" }
|
||||||
|
|
||||||
func (EncFs) Create(name string) (File, error) {
|
func (EncFs) Create(name string) (afero.File, error) {
|
||||||
f, e := os.Create(name)
|
f, e := os.Create(name)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
// while this looks strange, we need to return a bare nil (of type nil) not
|
// while this looks strange, we need to return a bare nil (of type nil) not
|
||||||
// a nil value of type *os.File or nil won't be nil
|
// a nil value of type *os.File or nil won't be nil
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
return f, e
|
return convertOsFileToEncFile(f, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) Mkdir(name string, perm os.FileMode) error {
|
func (EncFs) Mkdir(name string, perm os.FileMode) error {
|
||||||
@@ -33,17 +35,17 @@ func (EncFs) MkdirAll(path string, perm os.FileMode) error {
|
|||||||
return os.MkdirAll(path, perm)
|
return os.MkdirAll(path, perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) Open(name string) (File, error) {
|
func (EncFs) Open(name string) (afero.File, error) {
|
||||||
f, e := os.Open(name)
|
f, e := os.Open(name)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
// while this looks strange, we need to return a bare nil (of type nil) not
|
// while this looks strange, we need to return a bare nil (of type nil) not
|
||||||
// a nil value of type *os.File or nil won't be nil
|
// a nil value of type *os.File or nil won't be nil
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
return f, e
|
return convertOsFileToEncFile(f, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
|
||||||
f, e := os.OpenFile(name, flag, perm)
|
f, e := os.OpenFile(name, flag, perm)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
// while this looks strange, we need to return a bare nil (of type nil) not
|
// while this looks strange, we need to return a bare nil (of type nil) not
|
||||||
@@ -54,14 +56,17 @@ func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) Remove(name string) error {
|
func (EncFs) Remove(name string) error {
|
||||||
|
// TODO remove enc file meta
|
||||||
return os.Remove(name)
|
return os.Remove(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) RemoveAll(path string) error {
|
func (EncFs) RemoveAll(path string) error {
|
||||||
|
// TODO remove enc file meta
|
||||||
return os.RemoveAll(path)
|
return os.RemoveAll(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EncFs) Rename(oldname, newname string) error {
|
func (EncFs) Rename(oldname, newname string) error {
|
||||||
|
// TODO rename enc file meta
|
||||||
return os.Rename(oldname, newname)
|
return os.Rename(oldname, newname)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,3 +98,15 @@ func (EncFs) SymlinkIfPossible(oldname, newname string) error {
|
|||||||
func (EncFs) ReadlinkIfPossible(name string) (string, error) {
|
func (EncFs) ReadlinkIfPossible(name string) (string, error) {
|
||||||
return os.Readlink(name)
|
return os.Readlink(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertOsFileToEncFile(file *os.File, e error) (afero.File, error) {
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
// TODO add password, and IV etc ...
|
||||||
|
encFile, err := NewEncFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return encFile, nil
|
||||||
|
}
|
||||||
|
|||||||
10
justfile
Normal file
10
justfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
_:
|
||||||
|
@just --list
|
||||||
|
|
||||||
|
run:
|
||||||
|
go run main.go
|
||||||
|
|
||||||
|
build:
|
||||||
|
go build main.go
|
||||||
|
|
||||||
|
|
||||||
24
main.go
24
main.go
@@ -1,11 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"crypto/aes"
|
||||||
"math"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"crypto/aes"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"git.hatter.ink/hatter/go-afero-encfs/encfs"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +37,6 @@ func main() {
|
|||||||
fmt.Println(hex.EncodeToString(src))
|
fmt.Println(hex.EncodeToString(src))
|
||||||
fmt.Println(hex.EncodeToString(dest))
|
fmt.Println(hex.EncodeToString(dest))
|
||||||
|
|
||||||
|
|
||||||
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
||||||
nonce, err := hex.DecodeString("0011223344556677ffffffffffffffff")
|
nonce, err := hex.DecodeString("0011223344556677ffffffffffffffff")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -58,7 +59,6 @@ func main() {
|
|||||||
newNonce = nonceAdd(newNonce, 1)
|
newNonce = nonceAdd(newNonce, 1)
|
||||||
fmt.Println(hex.EncodeToString(newNonce))
|
fmt.Println(hex.EncodeToString(newNonce))
|
||||||
|
|
||||||
|
|
||||||
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
||||||
test_key := []byte{
|
test_key := []byte{
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
@@ -80,6 +80,20 @@ func main() {
|
|||||||
}
|
}
|
||||||
// SHOULD BE: 84ad8d80732490c061177a58bd26d032d6fcff2e66f9afe3cf95717485d3a4485d4a2a7bd835df3d0756b8192e3bf5a287ad8dd81942c43bc812c82d666ebbb34df4e2a5069467d9
|
// SHOULD BE: 84ad8d80732490c061177a58bd26d032d6fcff2e66f9afe3cf95717485d3a4485d4a2a7bd835df3d0756b8192e3bf5a287ad8dd81942c43bc812c82d666ebbb34df4e2a5069467d9
|
||||||
fmt.Println(hex.EncodeToString(plaintextBytes))
|
fmt.Println(hex.EncodeToString(plaintextBytes))
|
||||||
|
|
||||||
|
encFs := encfs.NewEncFs()
|
||||||
|
|
||||||
|
encFile, err := encFs.Create("test")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
len, err := encFile.Write([]byte("hello world"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("write len: ", len)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateCtrEncryptBytes(key, iv []byte, offset, len int64) ([]byte, error) {
|
func generateCtrEncryptBytes(key, iv []byte, offset, len int64) ([]byte, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user