Split into FS and File
This commit is contained in:
parent
4e93fdf820
commit
f8fddff769
42
backend.go
42
backend.go
@ -1,42 +0,0 @@
|
||||
package gocryptfs
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/aes"
|
||||
)
|
||||
|
||||
const (
|
||||
NONCE_LEN = 12
|
||||
AUTH_TAG_LEN = 16
|
||||
DEFAULT_PLAINBS = 4096
|
||||
|
||||
ENCRYPT = true
|
||||
DECRYPT = false
|
||||
)
|
||||
|
||||
type Backend struct {
|
||||
blockCipher cipher.Block
|
||||
gcm cipher.AEAD
|
||||
plainBS int64
|
||||
cipherBS int64
|
||||
}
|
||||
|
||||
func New(key [16]byte) *Backend {
|
||||
|
||||
b, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
g, err := cipher.NewGCM(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Backend{
|
||||
blockCipher: b,
|
||||
gcm: g,
|
||||
plainBS: DEFAULT_PLAINBS,
|
||||
cipherBS: DEFAULT_PLAINBS + NONCE_LEN + AUTH_TAG_LEN,
|
||||
}
|
||||
}
|
@ -1,19 +1,27 @@
|
||||
package gocryptfs
|
||||
package cryptfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"io"
|
||||
"errors"
|
||||
"crypto/cipher"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
file *os.File
|
||||
gcm cipher.AEAD
|
||||
plainBS int64
|
||||
cipherBS int64
|
||||
}
|
||||
|
||||
// readCipherBlock - Read ciphertext block number "blockNo", decrypt,
|
||||
// return plaintext
|
||||
func (be *Backend) readCipherBlock(blockNo int64, f *os.File) ([]byte, error) {
|
||||
func (be *File) readCipherBlock(blockNo int64) ([]byte, error) {
|
||||
off := blockNo * int64(be.cipherBS)
|
||||
buf := make([]byte, be.cipherBS)
|
||||
|
||||
readN, err := f.ReadAt(buf, off)
|
||||
readN, err := be.file.ReadAt(buf, off)
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
@ -56,7 +64,7 @@ type intraBlock struct {
|
||||
}
|
||||
|
||||
// Split a plaintext byte range into (possible partial) blocks
|
||||
func (be *Backend) splitRange(offset int64, length int64, f *os.File) []intraBlock {
|
||||
func (be *File) splitRange(offset int64, length int64) []intraBlock {
|
||||
var b intraBlock
|
||||
var parts []intraBlock
|
||||
|
||||
@ -71,7 +79,7 @@ func (be *Backend) splitRange(offset int64, length int64, f *os.File) []intraBlo
|
||||
return parts
|
||||
}
|
||||
|
||||
func (be *Backend) min64(x int64, y int64) int64 {
|
||||
func (be *File) min64(x int64, y int64) int64 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
@ -79,7 +87,7 @@ func (be *Backend) min64(x int64, y int64) int64 {
|
||||
}
|
||||
|
||||
// writeCipherBlock - Encrypt plaintext and write it to file block "blockNo"
|
||||
func (be *Backend) writeCipherBlock(blockNo int64, plain []byte, f *os.File) error {
|
||||
func (be *File) writeCipherBlock(blockNo int64, plain []byte) error {
|
||||
|
||||
if int64(len(plain)) > be.plainBS {
|
||||
panic("writeCipherBlock: Cannot write block that is larger than plainBS")
|
||||
@ -91,7 +99,7 @@ func (be *Backend) writeCipherBlock(blockNo int64, plain []byte, f *os.File) err
|
||||
cipherBuf := be.gcm.Seal(nonce, nonce, plain, nil)
|
||||
|
||||
// WriteAt retries short writes autmatically
|
||||
written, err := f.WriteAt(cipherBuf, blockNo * be.cipherBS)
|
||||
written, err := be.file.WriteAt(cipherBuf, blockNo * be.cipherBS)
|
||||
|
||||
debug.Printf("writeCipherBlock: wrote %d ciphertext bytes to block %d\n",
|
||||
written, blockNo)
|
||||
@ -101,12 +109,12 @@ func (be *Backend) writeCipherBlock(blockNo int64, plain []byte, f *os.File) err
|
||||
|
||||
// Perform RMW cycle on block
|
||||
// Write "data" into file location specified in "b"
|
||||
func (be *Backend) rmwWrite(b intraBlock, data []byte, f *os.File) error {
|
||||
func (be *File) rmwWrite(b intraBlock, data []byte, f *os.File) error {
|
||||
if b.length != int64(len(data)) {
|
||||
panic("Length mismatch")
|
||||
}
|
||||
|
||||
oldBlock, err := be.readCipherBlock(b.blockNo, f)
|
||||
oldBlock, err := be.readCipherBlock(b.blockNo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -128,7 +136,7 @@ func (be *Backend) rmwWrite(b intraBlock, data []byte, f *os.File) error {
|
||||
copy(newBlock[b.offset:b.offset + b.length], data)
|
||||
|
||||
// Actual write
|
||||
err = be.writeCipherBlock(b.blockNo, newBlock, f)
|
||||
err = be.writeCipherBlock(b.blockNo, newBlock)
|
||||
|
||||
if err != nil {
|
||||
// An incomplete write to a ciphertext block means that the whole block
|
@ -1,16 +1,62 @@
|
||||
package gocryptfs
|
||||
package cryptfs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"crypto/cipher"
|
||||
"crypto/aes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"encoding/base64"
|
||||
"crypto/cipher"
|
||||
"crypto/aes"
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
NONCE_LEN = 12
|
||||
AUTH_TAG_LEN = 16
|
||||
DEFAULT_PLAINBS = 4096
|
||||
|
||||
ENCRYPT = true
|
||||
DECRYPT = false
|
||||
)
|
||||
|
||||
type FS struct {
|
||||
blockCipher cipher.Block
|
||||
gcm cipher.AEAD
|
||||
plainBS int64
|
||||
cipherBS int64
|
||||
}
|
||||
|
||||
func New(key [16]byte) *FS {
|
||||
|
||||
b, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
g, err := cipher.NewGCM(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &FS{
|
||||
blockCipher: b,
|
||||
gcm: g,
|
||||
plainBS: DEFAULT_PLAINBS,
|
||||
cipherBS: DEFAULT_PLAINBS + NONCE_LEN + AUTH_TAG_LEN,
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FS) NewFile(f *os.File) *File {
|
||||
return &File {
|
||||
file: f,
|
||||
gcm: fs.gcm,
|
||||
plainBS: fs.plainBS,
|
||||
cipherBS: fs.cipherBS,
|
||||
}
|
||||
}
|
||||
|
||||
// DecryptName - decrypt filename
|
||||
func (be *Backend) decryptName(cipherName string) (string, error) {
|
||||
func (be *FS) decryptName(cipherName string) (string, error) {
|
||||
|
||||
bin, err := base64.URLEncoding.DecodeString(cipherName)
|
||||
if err != nil {
|
||||
@ -35,7 +81,7 @@ func (be *Backend) decryptName(cipherName string) (string, error) {
|
||||
}
|
||||
|
||||
// EncryptName - encrypt filename
|
||||
func (be *Backend) encryptName(plainName string) string {
|
||||
func (be *FS) encryptName(plainName string) string {
|
||||
|
||||
bin := []byte(plainName)
|
||||
bin = be.pad16(bin)
|
||||
@ -51,7 +97,7 @@ func (be *Backend) encryptName(plainName string) string {
|
||||
|
||||
// TranslatePath - encrypt or decrypt path. Just splits the string on "/"
|
||||
// and hands the parts to EncryptName() / DecryptName()
|
||||
func (be *Backend) translatePath(path string, op bool) (string, error) {
|
||||
func (be *FS) translatePath(path string, op bool) (string, error) {
|
||||
var err error
|
||||
|
||||
// Empty string means root directory
|
||||
@ -79,18 +125,18 @@ func (be *Backend) translatePath(path string, op bool) (string, error) {
|
||||
}
|
||||
|
||||
// EncryptPath - encrypt filename or path. Just hands it to TranslatePath().
|
||||
func (be *Backend) EncryptPath(path string) string {
|
||||
func (be *FS) EncryptPath(path string) string {
|
||||
newPath, _ := be.translatePath(path, ENCRYPT)
|
||||
return newPath
|
||||
}
|
||||
|
||||
// DecryptPath - decrypt filename or path. Just hands it to TranslatePath().
|
||||
func (be *Backend) DecryptPath(path string) (string, error) {
|
||||
func (be *FS) DecryptPath(path string) (string, error) {
|
||||
return be.translatePath(path, DECRYPT)
|
||||
}
|
||||
|
||||
// plainSize - calculate plaintext size from ciphertext size
|
||||
func (be *Backend) PlainSize(s int64) int64 {
|
||||
func (be *FS) PlainSize(s int64) int64 {
|
||||
// Zero sized files stay zero-sized
|
||||
if s > 0 {
|
||||
// Number of blocks
|
||||
@ -103,7 +149,7 @@ func (be *Backend) PlainSize(s int64) int64 {
|
||||
|
||||
// pad16 - pad filename to 16 byte blocks using standard PKCS#7 padding
|
||||
// https://tools.ietf.org/html/rfc5652#section-6.3
|
||||
func (be *Backend) pad16(orig []byte) (padded []byte) {
|
||||
func (be *FS) pad16(orig []byte) (padded []byte) {
|
||||
oldLen := len(orig)
|
||||
if oldLen == 0 {
|
||||
panic("Padding zero-length string makes no sense")
|
||||
@ -123,7 +169,7 @@ func (be *Backend) pad16(orig []byte) (padded []byte) {
|
||||
}
|
||||
|
||||
// unPad16 - remove padding
|
||||
func (be *Backend) unPad16(orig []byte) ([]byte, error) {
|
||||
func (be *FS) unPad16(orig []byte) ([]byte, error) {
|
||||
oldLen := len(orig)
|
||||
if oldLen % aes.BlockSize != 0 {
|
||||
return nil, errors.New("Unaligned size")
|
@ -1,4 +1,4 @@
|
||||
package gocryptfs
|
||||
package cryptfs
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package gocryptfs
|
||||
package cryptfs
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
Loading…
Reference in New Issue
Block a user