commit 9a4b0a076c0c0f0b35b4a0a4a1562c2c55741990
parent bd900945f0f8c11f24a2e0046ae66a3d20744241
Author: Sean Enck <sean@ttypty.com>
Date: Sat, 17 Sep 2022 12:26:33 -0400
more algorithm support
Diffstat:
6 files changed, 63 insertions(+), 73 deletions(-)
diff --git a/internal/encrypt/algorithms.go b/internal/encrypt/algorithms.go
@@ -1,67 +0,0 @@
-package encrypt
-
-import (
- "crypto/sha512"
- "errors"
- random "math/rand"
- "time"
-
- "github.com/enckse/lockbox/internal/inputs"
- "golang.org/x/crypto/pbkdf2"
-)
-
-const (
- secretBoxAlgorithmVersion uint8 = 1
- isSecretBox = "secretbox"
- aesGCMAlgorithmVersion uint8 = 2
-)
-
-type (
- algorithm interface {
- encrypt(k, d []byte) ([]byte, error)
- decrypt(k, d []byte) ([]byte, error)
- version() []byte
- }
-)
-
-func init() {
- random.Seed(time.Now().UnixNano())
-}
-
-func newAlgorithmFromVersion(vers uint8) algorithm {
- switch vers {
- case secretBoxAlgorithmVersion:
- return secretBoxAlgorithm{}
- case aesGCMAlgorithmVersion:
- return aesGCMAlgorithm{}
- }
- return nil
-}
-
-func newAlgorithm(mode string) algorithm {
- useMode := mode
- if mode == "" {
- useMode = inputs.EnvOrDefault(inputs.EncryptModeEnv, isSecretBox)
- }
- switch useMode {
- case isSecretBox:
- return secretBoxAlgorithm{}
- case "aes":
- return aesGCMAlgorithm{}
- }
- return nil
-}
-
-func algoVersion(v uint8) []byte {
- return []byte{0, v}
-}
-
-func pad(salt, key []byte) ([keyLength]byte, error) {
- d := pbkdf2.Key(key, salt, 4096, keyLength, sha512.New)
- if len(d) != keyLength {
- return [keyLength]byte{}, errors.New("invalid key result from pad")
- }
- var obj [keyLength]byte
- copy(obj[:], d[:keyLength])
- return obj, nil
-}
diff --git a/internal/encrypt/core.go b/internal/encrypt/core.go
@@ -2,14 +2,21 @@
package encrypt
import (
+ "crypto/sha512"
"errors"
+ random "math/rand"
"os"
+ "time"
"github.com/enckse/lockbox/internal/inputs"
+ "golang.org/x/crypto/pbkdf2"
)
const (
- keyLength = 32
+ keyLength = 32
+ secretBoxAlgorithmVersion uint8 = 1
+ isSecretBox = "secretbox"
+ aesGCMAlgorithmVersion uint8 = 2
)
type (
@@ -27,8 +34,55 @@ type (
File string
Algorithm string
}
+ algorithm interface {
+ encrypt(k, d []byte) ([]byte, error)
+ decrypt(k, d []byte) ([]byte, error)
+ version() []byte
+ }
)
+func init() {
+ random.Seed(time.Now().UnixNano())
+}
+
+func newAlgorithmFromVersion(vers uint8) algorithm {
+ switch vers {
+ case secretBoxAlgorithmVersion:
+ return secretBoxAlgorithm{}
+ case aesGCMAlgorithmVersion:
+ return aesGCMAlgorithm{}
+ }
+ return nil
+}
+
+func newAlgorithm(mode string) algorithm {
+ useMode := mode
+ if mode == "" {
+ useMode = inputs.EnvOrDefault(inputs.EncryptModeEnv, isSecretBox)
+ }
+ switch useMode {
+ case isSecretBox:
+ return secretBoxAlgorithm{}
+ case "aesgcm":
+ return aesGCMAlgorithm{}
+ }
+ return nil
+}
+
+func algoVersion(v uint8) []byte {
+ return []byte{0, v}
+}
+
+func pad(salt, key []byte) ([keyLength]byte, error) {
+ d := pbkdf2.Key(key, salt, 4096, keyLength, sha512.New)
+ if len(d) != keyLength {
+ return [keyLength]byte{}, errors.New("invalid key result from pad")
+ }
+ var obj [keyLength]byte
+ copy(obj[:], d[:keyLength])
+ return obj, nil
+}
+
// FromFile decrypts a file-system based encrypted file.
func FromFile(file string) ([]byte, error) {
l, err := NewLockbox(LockboxOptions{File: file})
diff --git a/internal/encrypt/core_test.go b/internal/encrypt/core_test.go
@@ -111,7 +111,7 @@ func TestEncryptDecryptSecretBox(t *testing.T) {
}
func TestEncryptDecryptAESBox(t *testing.T) {
- e, err := encrypt.NewLockbox(encrypt.LockboxOptions{Key: "plain", KeyMode: inputs.PlainKeyMode, File: setupData(t), Algorithm: "aes"})
+ e, err := encrypt.NewLockbox(encrypt.LockboxOptions{Key: "plain", KeyMode: inputs.PlainKeyMode, File: setupData(t), Algorithm: "aesgcm"})
if err != nil {
t.Errorf("failed to create lockbox: %v", err)
}
diff --git a/internal/inputs/env.go b/internal/inputs/env.go
@@ -35,7 +35,7 @@ const (
// ColorBetweenEnv is a comma-delimited list of times to color totp outputs (e.g. 0:5,30:35 which is the default).
ColorBetweenEnv = prefixKey + "TOTPBETWEEN"
// EncryptModeEnv indicates the underlying algorith to use for encryption.
- EncryptModeEnv = prefixKey + "ALGORITHM"
+ EncryptModeEnv = prefixKey + "ALGORITHM"
// PlainKeyMode is plaintext based key resolution.
PlainKeyMode = "plaintext"
// CommandKeyMode will run an external command to get the key (from stdout).
diff --git a/internal/subcommands/readwrite.go b/internal/subcommands/readwrite.go
@@ -16,11 +16,12 @@ func ReadWrite(args []string) error {
key := flags.String("key", "", "security key")
file := flags.String("file", "", "file to process")
keyMode := flags.String("keymode", "", "key lookup mode")
+ algo := flags.String("algorithm", "", "algorithm to use")
if err := flags.Parse(args); err != nil {
return err
}
- l, err := encrypt.NewLockbox(encrypt.LockboxOptions{Key: *key, KeyMode: *keyMode, File: *file})
+ l, err := encrypt.NewLockbox(encrypt.LockboxOptions{Key: *key, KeyMode: *keyMode, File: *file, Algorithm: *algo})
if err != nil {
return err
}
diff --git a/internal/subcommands/rekey.go b/internal/subcommands/rekey.go
@@ -17,6 +17,8 @@ func Rekey(args []string) error {
outKey := flags.String("outkey", "", "output encryption key to update values with")
inMode := flags.String("inmode", "", "input encryption key mode")
outMode := flags.String("outmode", "", "output encryption key mode")
+ inAlgo := flags.String("inalgorithm", "", "input encryption algorithm")
+ outAlgo := flags.String("outalgorithm", "", "output encryption algorithm")
if err := flags.Parse(args); err != nil {
return err
}
@@ -24,8 +26,8 @@ func Rekey(args []string) error {
if err != nil {
return err
}
- inOpts := encrypt.LockboxOptions{Key: *inKey, KeyMode: *inMode}
- outOpts := encrypt.LockboxOptions{Key: *outKey, KeyMode: *outMode}
+ inOpts := encrypt.LockboxOptions{Key: *inKey, KeyMode: *inMode, Algorithm: *inAlgo}
+ outOpts := encrypt.LockboxOptions{Key: *outKey, KeyMode: *outMode, Algorithm: *outAlgo}
for _, file := range found {
fmt.Printf("rekeying: %s\n", file)
inOpts.File = file