diff options
Diffstat (limited to 'internal/nametransform/names.go')
-rw-r--r-- | internal/nametransform/names.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/internal/nametransform/names.go b/internal/nametransform/names.go new file mode 100644 index 0000000..8a7e260 --- /dev/null +++ b/internal/nametransform/names.go @@ -0,0 +1,84 @@ +package nametransform + +// Filename encryption / decryption functions + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "fmt" + + "github.com/rfjakob/eme" + + "github.com/rfjakob/gocryptfs/internal/cryptocore" +) + +type NameTransform struct { + cryptoCore *cryptocore.CryptoCore + useEME bool + longNames bool + DirIVCache dirIVCache +} + +func New(c *cryptocore.CryptoCore, useEME bool, longNames bool) *NameTransform { + return &NameTransform{ + cryptoCore: c, + longNames: longNames, + useEME: useEME, + } +} + +// DecryptName - decrypt base64-encoded encrypted filename "cipherName" +// Used by DecryptPathDirIV(). +// The encryption is either CBC or EME, depending on "useEME". +// +// This function is exported because it allows for a very efficient readdir +// implementation (read IV once, decrypt all names using this function). +func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error) { + + bin, err := base64.URLEncoding.DecodeString(cipherName) + if err != nil { + return "", err + } + + if len(bin)%aes.BlockSize != 0 { + return "", fmt.Errorf("Decoded length %d is not a multiple of the AES block size", len(bin)) + } + + if n.useEME { + bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionDecrypt) + } else { + cbc := cipher.NewCBCDecrypter(n.cryptoCore.BlockCipher, iv) + cbc.CryptBlocks(bin, bin) + } + + bin, err = unPad16(bin) + if err != nil { + return "", err + } + + plain := string(bin) + return plain, err +} + +// encryptName - encrypt "plainName", return base64-encoded "cipherName64". +// Used internally by EncryptPathDirIV(). +// The encryption is either CBC or EME, depending on "useEME". +// +// This function is exported because fusefrontend needs access to the full (not hashed) +// name if longname is used. Otherwise you should use EncryptPathDirIV() +func (n *NameTransform) EncryptName(plainName string, iv []byte) (cipherName64 string) { + + bin := []byte(plainName) + bin = pad16(bin) + + if n.useEME { + bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionEncrypt) + } else { + cbc := cipher.NewCBCEncrypter(n.cryptoCore.BlockCipher, iv) + cbc.CryptBlocks(bin, bin) + } + + cipherName64 = base64.URLEncoding.EncodeToString(bin) + return cipherName64 +} |