aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-10-24 15:10:12 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-10-24 15:10:12 -0700
commitedd01c62855ff5d1b0ef50a1d9350718cb033c84 (patch)
tree24651fbc3774da158d36a19f8a532ed50828cf45
parent9a08b03b83ff28a26b0c20ccebc178df29cf7312 (diff)
downloadsym-edd01c62855ff5d1b0ef50a1d9350718cb033c84.tar.zst
Remove all metadata
-rw-r--r--dec.go25
-rw-r--r--dec_test.go107
-rw-r--r--enc.go20
-rw-r--r--enc_test.go6
-rw-r--r--encryptionalg_string.go25
-rw-r--r--metadata.go21
-rw-r--r--oae.go96
-rw-r--r--oae_test.go15
-rw-r--r--pwhash.go32
-rw-r--r--pwhash_string.go25
-rw-r--r--sym_test.go8
11 files changed, 71 insertions, 309 deletions
diff --git a/dec.go b/dec.go
index fdea3fe..aa551ad 100644
--- a/dec.go
+++ b/dec.go
@@ -1,7 +1,6 @@
package main
import (
- "encoding/binary"
"errors"
"flag"
"fmt"
@@ -10,22 +9,8 @@ import (
"strings"
)
-func decrypt(w io.Writer, r io.Reader, password string) error {
- fileFormat := make([]byte, 4)
- if _, err := io.ReadFull(r, fileFormat); err != nil {
- return err
- }
- if string(fileFormat) != magic {
- return fmt.Errorf("bad file format")
- }
- header := new(fileMetadata)
- if err := binary.Read(r, binary.BigEndian, header); err != nil {
- return err
- }
- if err := header.validate(); err != nil {
- return err
- }
- _, err := io.Copy(w, header.EncryptionMetadata.newDecryptingReader(r, password, &header.HashMetadata))
+func (o *decryptOptions) decrypt(w io.Writer, r io.Reader, password string) error {
+ _, err := io.Copy(w, newDecryptingReader(r, password, o.iterations))
return err
}
@@ -42,12 +27,14 @@ func (f *decryptFlags) registerFlags(fs *flag.FlagSet) {
type decryptOptions struct {
decryptFlags
+ iterations int
passwordIn func() (string, error)
stdin io.Reader
stdout io.Writer
}
var defaultDecryptOptions = decryptOptions{
+ iterations: defaultPBKDF2Iters,
passwordIn: termReadPassword,
stdin: os.Stdin,
stdout: os.Stdout,
@@ -86,7 +73,7 @@ func (o *decryptOptions) decryptFile(fileName string, password string) (err erro
os.Remove(fOut.Name())
}
}()
- if err := decrypt(fOut, fIn, password); err != nil {
+ if err := o.decrypt(fOut, fIn, password); err != nil {
return fmt.Errorf("decrypt %q: %s", fileName, err)
}
return fOut.Close()
@@ -114,7 +101,7 @@ func (o *decryptOptions) run(args ...string) error {
}
}
if len(args) == 0 {
- return decrypt(o.stdout, o.stdin, password)
+ return o.decrypt(o.stdout, o.stdin, password)
}
for _, fileName := range args {
if err := o.decryptFile(fileName, password); err != nil {
diff --git a/dec_test.go b/dec_test.go
index 46bb588..27fdd96 100644
--- a/dec_test.go
+++ b/dec_test.go
@@ -2,7 +2,6 @@ package main
import (
"bytes"
- "encoding/binary"
"errors"
"flag"
"path/filepath"
@@ -36,7 +35,7 @@ func TestDecryptFile_Force(t *testing.T) {
if err := testEncryptOptions.encryptFile(fileName, password); err != nil {
t.Fatalf("Failed to encrypt file: %s", err)
}
- decOpts := defaultDecryptOptions
+ decOpts := testDecryptOptions
decOpts.force = tc.force
err := decOpts.decryptFile(fileName+".enc", password)
if gotErr := err != nil; gotErr != tc.wantErr {
@@ -46,31 +45,6 @@ func TestDecryptFile_Force(t *testing.T) {
}
}
-func encodeHeader(t *testing.T, f *fileMetadata) []byte {
- t.Helper()
-
- if f.HashMetadata.PasswordHashType == pwHashInvalid {
- f.HashMetadata.PasswordHashType = pwHashPBKDF2_HMAC_SHA256
- }
- if f.HashMetadata.Iterations == 0 {
- f.HashMetadata.Iterations = 10
- }
- if f.HashMetadata.SaltSize == 0 {
- f.HashMetadata.SaltSize = defaultSaltSize
- }
- if f.EncryptionMetadata.EncryptionType == encryptionAlgInvalid {
- f.EncryptionMetadata.EncryptionType = encryptionAlgAES256_GCM
- }
- if f.EncryptionMetadata.SegmentSize == 0 {
- f.EncryptionMetadata.SegmentSize = defaultSegmentSize
- }
- b, err := binary.Append([]byte(magic), binary.BigEndian, f)
- if err != nil {
- t.Fatalf("Bad file metadata: %s", err)
- }
- return b
-}
-
func TestDecrypt_BadFileFormat(t *testing.T) {
t.Parallel()
@@ -84,67 +58,12 @@ func TestDecrypt_BadFileFormat(t *testing.T) {
desc: "Short",
fileContent: []byte{0x80},
}, {
- desc: "BadFormat",
- fileContent: []byte("bad file format"),
- }, {
- desc: "BadMagic",
- fileContent: []byte("\x80asdf"),
- }, {
- desc: "BadHeader",
- fileContent: []byte("\x80symasdf"),
- }, {
- desc: "BadVersion",
- fileContent: encodeHeader(t, &fileMetadata{
- Version: -1,
- }),
- }, {
- desc: "BadEncryptionAlg",
- fileContent: encodeHeader(t, &fileMetadata{
- EncryptionMetadata: encryptionMetadata{
- EncryptionType: -1,
- },
- }),
- }, {
- desc: "BadSegmentSize",
- fileContent: encodeHeader(t, &fileMetadata{
- EncryptionMetadata: encryptionMetadata{
- SegmentSize: -1,
- },
- }),
- }, {
- desc: "BadSaltSize",
- fileContent: encodeHeader(t, &fileMetadata{
- HashMetadata: hashMetadata{
- SaltSize: -1,
- },
- }),
- }, {
- desc: "BadPasswordHashType",
- fileContent: encodeHeader(t, &fileMetadata{
- HashMetadata: hashMetadata{
- PasswordHashType: -1,
- },
- }),
- }, {
- desc: "BadIterations",
- fileContent: encodeHeader(t, &fileMetadata{
- HashMetadata: hashMetadata{
- Iterations: -1,
- },
- }),
- }, {
- desc: "NoSalt",
- fileContent: encodeHeader(t, &fileMetadata{}),
- }, {
- desc: "ShortSalt",
- fileContent: slices.Concat(
- encodeHeader(t, &fileMetadata{}),
- []byte("asdf")),
+ desc: "NoContent",
+ fileContent: bytes.Repeat([]byte{0}, saltSize),
}, {
desc: "BadContent",
fileContent: slices.Concat(
- encodeHeader(t, &fileMetadata{}),
- bytes.Repeat([]byte{0}, defaultSaltSize),
+ bytes.Repeat([]byte{0}, saltSize),
[]byte("bad content")),
}} {
t.Run(tc.desc, func(t *testing.T) {
@@ -152,7 +71,7 @@ func TestDecrypt_BadFileFormat(t *testing.T) {
fileName := filepath.Join(t.TempDir(), "file")
mustWriteFile(t, fileName, tc.fileContent)
- err := defaultDecryptOptions.decryptFile(fileName, "asdf")
+ err := testDecryptOptions.decryptFile(fileName, "asdf")
if err == nil {
t.Errorf("DecryptFile succeeded for incorrect file format, want error")
}
@@ -171,7 +90,7 @@ func TestDecryptFile_WeirdName(t *testing.T) {
t.Fatalf("EncryptFile failed: %s", err)
}
mustRename(t, fileName+".enc", fileName+".encrypted")
- if err := defaultDecryptOptions.decryptFile(fileName+".encrypted", password); err != nil {
+ if err := testDecryptOptions.decryptFile(fileName+".encrypted", password); err != nil {
t.Fatalf("DecryptFile failed: %s", err)
}
gotContents := mustReadFile(t, fileName+".encrypted.dec")
@@ -183,7 +102,7 @@ func TestDecryptFile_WeirdName(t *testing.T) {
func TestDecryptFile_NotFound(t *testing.T) {
t.Parallel()
- err := defaultDecryptOptions.decryptFile("my-nonexistent-file.txt", "asdf")
+ err := testDecryptOptions.decryptFile("my-nonexistent-file.txt", "asdf")
if err == nil {
t.Fatal("decryptFile succeeded for nonexistent file, want error")
}
@@ -196,7 +115,7 @@ func TestDecryptFile_NoPermission(t *testing.T) {
mustWriteFile(t, fileName, []byte("test file content"))
mustWriteFile(t, strings.TrimSuffix(fileName, ".enc"), nil)
mustChmod(t, strings.TrimSuffix(fileName, ".enc"), 0400)
- opts := defaultDecryptOptions
+ opts := testDecryptOptions
opts.force = true
err := opts.decryptFile(fileName, "asdf")
if err == nil {
@@ -232,7 +151,7 @@ func TestDecryptOptions_Run(t *testing.T) {
t.Errorf("EncryptFile failed: %s", err)
}
mustRemove(t, fileName)
- opts := defaultDecryptOptions
+ opts := testDecryptOptions
opts.password = password
err := opts.run(fileName + ".enc")
if err != nil {
@@ -247,7 +166,7 @@ func TestDecryptOptions_Run(t *testing.T) {
func TestDecryptOptions_Run_UsageError(t *testing.T) {
t.Parallel()
- err := defaultDecryptOptions.run()
+ err := testDecryptOptions.run()
if err == nil {
t.Errorf("Run without -p when reading from stdin, want error")
}
@@ -256,7 +175,7 @@ func TestDecryptOptions_Run_UsageError(t *testing.T) {
func TestDecryptOptions_Run_NotFound(t *testing.T) {
t.Parallel()
- opts := defaultDecryptOptions
+ opts := testDecryptOptions
opts.password = "asdf"
err := opts.run("my-nonexistent-file-name.txt")
if err == nil {
@@ -274,7 +193,7 @@ func TestDecryptOptions_Run_Stdin(t *testing.T) {
t.Fatalf("Failed to encrypt: %s", err)
}
gotContentBuf := new(bytes.Buffer)
- opts := defaultDecryptOptions
+ opts := testDecryptOptions
opts.password = password
opts.stdin = bytes.NewReader(encrypted.Bytes())
opts.stdout = gotContentBuf
@@ -313,7 +232,7 @@ func TestDecryptOptions_Run_ReadPassword(t *testing.T) {
}
mustRemove(t, fileName)
- opts := defaultDecryptOptions
+ opts := testDecryptOptions
opts.passwordIn = func() (string, error) {
return password, tc.err
}
diff --git a/enc.go b/enc.go
index 6327f25..5990121 100644
--- a/enc.go
+++ b/enc.go
@@ -44,25 +44,7 @@ var defaultEncryptOptions = encryptOptions{
}
func (o *encryptOptions) encrypt(w io.Writer, r io.Reader, password string) error {
- if _, err := io.WriteString(w, magic); err != nil {
- return err
- }
- header := &fileMetadata{
- Version: 0,
- HashMetadata: hashMetadata{
- PasswordHashType: pwHashPBKDF2_HMAC_SHA256,
- Iterations: int32(o.iterations),
- SaltSize: defaultSaltSize,
- },
- EncryptionMetadata: encryptionMetadata{
- EncryptionType: encryptionAlgAES256_GCM,
- SegmentSize: defaultSegmentSize,
- },
- }
- if err := binary.Write(w, binary.BigEndian, header); err != nil {
- return err
- }
- writer := header.EncryptionMetadata.newEncryptingWriter(w, password, &header.HashMetadata)
+ writer := newEncryptingWriter(w, password, o.iterations)
if _, err := io.Copy(writer, r); err != nil {
return err
}
diff --git a/enc_test.go b/enc_test.go
index d2c6690..35d9f9e 100644
--- a/enc_test.go
+++ b/enc_test.go
@@ -96,7 +96,7 @@ func TestEncryptOptions_Run(t *testing.T) {
t.Fatalf("enc failed: %s", err)
}
mustRemove(t, fileName)
- if err := defaultDecryptOptions.decryptFile(fileName+".enc", password); err != nil {
+ if err := testDecryptOptions.decryptFile(fileName+".enc", password); err != nil {
t.Fatalf("Failed to decrypt encrypted file: %s", err)
}
gotFileContents := mustReadFile(t, fileName)
@@ -155,7 +155,7 @@ func TestEncryptOptions_Run_GeneratePassword(t *testing.T) {
}
pw := password.String()
mustRemove(t, fileName)
- if err := defaultDecryptOptions.decryptFile(fileName+".enc", pw); err != nil {
+ if err := testDecryptOptions.decryptFile(fileName+".enc", pw); err != nil {
t.Fatalf("Failed to decrypt encrypted file with generated password %q: %s", pw, err)
}
gotFileContents := mustReadFile(t, fileName)
@@ -180,7 +180,7 @@ func TestEncryptOptions_Run_Stdin(t *testing.T) {
t.Errorf("enc(+%v) failed: %s", opts, err)
}
got := new(strings.Builder)
- if err := decrypt(got, strings.NewReader(stdout.String()), password); err != nil {
+ if err := testDecryptOptions.decrypt(got, strings.NewReader(stdout.String()), password); err != nil {
t.Errorf("Failed to decrypt stdout content %q: %s", stdout, err)
}
if got, want := got.String(), input; got != want {
diff --git a/encryptionalg_string.go b/encryptionalg_string.go
deleted file mode 100644
index 9860f20..0000000
--- a/encryptionalg_string.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Code generated by "stringer -type=encryptionAlg -linecomment"; DO NOT EDIT.
-
-package main
-
-import "strconv"
-
-func _() {
- // An "invalid array index" compiler error signifies that the constant values have changed.
- // Re-run the stringer command to generate them again.
- var x [1]struct{}
- _ = x[encryptionAlgInvalid-0]
- _ = x[encryptionAlgAES256_GCM-1]
-}
-
-const _encryptionAlg_name = "encryptionAlgInvalidAES-256-GCM"
-
-var _encryptionAlg_index = [...]uint8{0, 20, 31}
-
-func (i encryptionAlg) String() string {
- idx := int(i) - 0
- if i < 0 || idx >= len(_encryptionAlg_index)-1 {
- return "encryptionAlg(" + strconv.FormatInt(int64(i), 10) + ")"
- }
- return _encryptionAlg_name[_encryptionAlg_index[idx]:_encryptionAlg_index[idx+1]]
-}
diff --git a/metadata.go b/metadata.go
deleted file mode 100644
index 8c789c0..0000000
--- a/metadata.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package main
-
-import "fmt"
-
-const magic = "\x80sym"
-
-type fileMetadata struct {
- Version int8
- HashMetadata hashMetadata
- EncryptionMetadata encryptionMetadata
-}
-
-func (f *fileMetadata) validate() error {
- if f.Version != 0 {
- return fmt.Errorf("bad version")
- }
- if err := f.HashMetadata.validate(); err != nil {
- return err
- }
- return f.EncryptionMetadata.validate()
-}
diff --git a/oae.go b/oae.go
index a462b05..5b6140c 100644
--- a/oae.go
+++ b/oae.go
@@ -7,7 +7,6 @@ import (
"crypto/cipher"
"crypto/rand"
"errors"
- "fmt"
"io"
)
@@ -15,49 +14,22 @@ const (
nonceSize = 12
aeadOverhead = 16
- defaultSegmentSize = 1024 * 1024
+ segmentSize = 1024 * 1024
+ plaintextSegmentSize = segmentSize - aeadOverhead
- defaultSaltSize = 32
+ saltSize = 32
)
-//go:generate go tool stringer -type=encryptionAlg -linecomment
-type encryptionAlg int8
-
-const (
- encryptionAlgInvalid encryptionAlg = iota
- encryptionAlgAES256_GCM // AES-256-GCM
-)
-
-type encryptionMetadata struct {
- EncryptionType encryptionAlg
- SegmentSize int32
-}
-
-func (e *encryptionMetadata) validate() error {
- if e.EncryptionType != encryptionAlgAES256_GCM {
- return fmt.Errorf("invalid encryption alg %q", e.EncryptionType)
- }
- if e.SegmentSize <= 0 || e.SegmentSize > defaultSegmentSize {
- return fmt.Errorf("segment size too long")
- }
- return nil
-}
-
-func (e *encryptionMetadata) plaintextSegmentSize() int {
- return int(e.SegmentSize) - aeadOverhead
-}
-
type segmentEncrypter struct {
- hashMetadata hashMetadata
- encryptionMetadata encryptionMetadata
- password string
+ password string
+ iterations int
aead cipher.AEAD
nonce [nonceSize]byte
}
func (se *segmentEncrypter) initialize(salt []byte) error {
- key, err := se.hashMetadata.hashPassword(se.password, salt)
+ key, err := hashPassword(se.password, salt, se.iterations)
if err != nil {
return err
}
@@ -111,13 +83,12 @@ type encryptingWriter struct {
initialized bool
}
-func (e *encryptionMetadata) newEncryptingWriter(w io.Writer, password string, passwordMetadata *hashMetadata) *encryptingWriter {
+func newEncryptingWriter(w io.Writer, password string, iterations int) *encryptingWriter {
return &encryptingWriter{
w: w,
encrypter: segmentEncrypter{
- hashMetadata: *passwordMetadata,
- encryptionMetadata: *e,
- password: password,
+ password: password,
+ iterations: iterations,
},
}
}
@@ -126,7 +97,7 @@ func (w *encryptingWriter) initialize() error {
if w.initialized {
return nil
}
- header := make([]byte, w.encrypter.hashMetadata.SaltSize)
+ header := make([]byte, saltSize)
rand.Read(header)
if err := w.encrypter.initialize(header); err != nil {
return err
@@ -134,7 +105,7 @@ func (w *encryptingWriter) initialize() error {
if _, err := w.w.Write(header); err != nil {
return err
}
- w.buf = make([]byte, 0, w.encrypter.encryptionMetadata.SegmentSize)
+ w.buf = make([]byte, 0, segmentSize)
w.initialized = true
return nil
}
@@ -157,12 +128,12 @@ func (w *encryptingWriter) Write(buf []byte) (int, error) {
}
nn := 0
for len(buf) > 0 {
- if len(w.buf) == w.encrypter.encryptionMetadata.plaintextSegmentSize() {
+ if len(w.buf) == plaintextSegmentSize {
if err := w.writeBuf(false); err != nil {
return nn, err
}
}
- n := copy(w.buf[len(w.buf):w.encrypter.encryptionMetadata.plaintextSegmentSize()], buf)
+ n := copy(w.buf[len(w.buf):plaintextSegmentSize], buf)
nn += n
w.buf = w.buf[:len(w.buf)+n]
buf = buf[n:]
@@ -183,7 +154,7 @@ func (w *encryptingWriter) ReadFrom(r io.Reader) (int64, error) {
}
var nn int64
for {
- n, err := io.ReadFull(r, w.buf[len(w.buf):w.encrypter.encryptionMetadata.plaintextSegmentSize()+1])
+ n, err := io.ReadFull(r, w.buf[len(w.buf):plaintextSegmentSize+1])
nn += int64(n)
w.buf = w.buf[:len(w.buf)+n]
if err != nil {
@@ -192,8 +163,8 @@ func (w *encryptingWriter) ReadFrom(r io.Reader) (int64, error) {
}
return nn, err
}
- nextByte := w.buf[w.encrypter.encryptionMetadata.plaintextSegmentSize()]
- w.buf = w.buf[:w.encrypter.encryptionMetadata.plaintextSegmentSize()]
+ nextByte := w.buf[plaintextSegmentSize]
+ w.buf = w.buf[:plaintextSegmentSize]
if err := w.writeBuf(false); err != nil {
return nn, err
}
@@ -203,19 +174,19 @@ func (w *encryptingWriter) ReadFrom(r io.Reader) (int64, error) {
}
type decryptingReader struct {
- r *bufio.Reader
- decrypter segmentEncrypter
- buf bytes.Buffer
- initialized bool
+ r *bufio.Reader
+ decrypter segmentEncrypter
+ buf bytes.Buffer
+ initialized bool
+ readFinalBlock bool
}
-func (e *encryptionMetadata) newDecryptingReader(r io.Reader, password string, passwordMetadata *hashMetadata) *decryptingReader {
+func newDecryptingReader(r io.Reader, password string, iterations int) *decryptingReader {
return &decryptingReader{
r: bufio.NewReaderSize(r, 0), // we only need .UnreadByte
decrypter: segmentEncrypter{
- hashMetadata: *passwordMetadata,
- encryptionMetadata: *e,
- password: password,
+ password: password,
+ iterations: iterations,
},
}
}
@@ -224,7 +195,7 @@ func (r *decryptingReader) initialize() error {
if r.initialized {
return nil
}
- header := make([]byte, r.decrypter.hashMetadata.SaltSize)
+ header := make([]byte, saltSize)
if _, err := io.ReadFull(r.r, header); err != nil {
if err == io.EOF {
return io.ErrUnexpectedEOF
@@ -234,7 +205,7 @@ func (r *decryptingReader) initialize() error {
if err := r.decrypter.initialize(header); err != nil {
return err
}
- r.buf = *bytes.NewBuffer(make([]byte, 0, r.decrypter.encryptionMetadata.SegmentSize+1))
+ r.buf = *bytes.NewBuffer(make([]byte, 0, segmentSize+1))
r.initialized = true
return nil
}
@@ -242,17 +213,22 @@ func (r *decryptingReader) initialize() error {
func (r *decryptingReader) fillBuf() error {
r.buf.Reset()
// Read 1 extra byte to make sure if we're at EOF.
- buf := r.buf.AvailableBuffer()[:r.decrypter.encryptionMetadata.SegmentSize+1]
+ buf := r.buf.AvailableBuffer()[:segmentSize+1]
n, err := io.ReadFull(r.r, buf)
- if err != nil && err != io.ErrUnexpectedEOF {
+ if err == io.ErrUnexpectedEOF {
+ r.readFinalBlock = true
+ } else if err != nil {
+ if err == io.EOF && !r.readFinalBlock {
+ return errors.New("premature EOF")
+ }
return err
}
buf = buf[:n]
- if len(buf) == int(r.decrypter.encryptionMetadata.SegmentSize)+1 {
+ if len(buf) == int(segmentSize)+1 {
r.r.UnreadByte()
- buf = buf[:r.decrypter.encryptionMetadata.SegmentSize]
+ buf = buf[:segmentSize]
}
- buf, err = r.decrypter.decrypt(buf[:0], buf, err == io.ErrUnexpectedEOF)
+ buf, err = r.decrypter.decrypt(buf[:0], buf, r.readFinalBlock)
if err != nil {
return err
}
diff --git a/oae_test.go b/oae_test.go
index 8a0a639..0cd5dd3 100644
--- a/oae_test.go
+++ b/oae_test.go
@@ -7,16 +7,7 @@ import (
"testing"
)
-var testEncryptionMetadata = encryptionMetadata{
- EncryptionType: encryptionAlgAES256_GCM,
- SegmentSize: 18,
-}
-
-var testHashMetadata = hashMetadata{
- PasswordHashType: pwHashPBKDF2_HMAC_SHA256,
- Iterations: 10,
- SaltSize: defaultSaltSize,
-}
+const testIters = 10
func TestOAEReadWrite(t *testing.T) {
t.Parallel()
@@ -24,14 +15,14 @@ func TestOAEReadWrite(t *testing.T) {
const password = "asdf"
input := strings.Repeat("test input", 1024)
out := new(bytes.Buffer)
- writer := testEncryptionMetadata.newEncryptingWriter(out, password, &testHashMetadata)
+ writer := newEncryptingWriter(out, password, testIters)
if _, err := io.WriteString(writer, input); err != nil {
t.Fatalf("Failed to write: %s", err)
}
if err := writer.close(); err != nil {
t.Fatalf("writer.Close() failed: %s", err)
}
- got, err := io.ReadAll(testEncryptionMetadata.newDecryptingReader(bytes.NewReader(out.Bytes()), password, &testHashMetadata))
+ got, err := io.ReadAll(newDecryptingReader(bytes.NewReader(out.Bytes()), password, testIters))
if err != nil {
t.Fatalf("Failed to decrypt: %s", err)
}
diff --git a/pwhash.go b/pwhash.go
index 2d7a70f..31f1487 100644
--- a/pwhash.go
+++ b/pwhash.go
@@ -3,7 +3,6 @@ package main
import (
"crypto/pbkdf2"
"crypto/sha256"
- "fmt"
"os"
"golang.org/x/term"
@@ -11,35 +10,8 @@ import (
const defaultPBKDF2Iters = 35_000_000
-//go:generate go tool stringer -type=pwHash -linecomment
-type pwHash int8
-
-const (
- pwHashInvalid pwHash = iota
- pwHashPBKDF2_HMAC_SHA256 // PBKDF2-HMAC-SHA256
-)
-
-type hashMetadata struct {
- PasswordHashType pwHash
- Iterations int32
- SaltSize int8
-}
-
-func (h *hashMetadata) validate() error {
- if h.PasswordHashType != pwHashPBKDF2_HMAC_SHA256 {
- return fmt.Errorf("invalid hash type %q", h.PasswordHashType)
- }
- if h.Iterations <= 0 || h.Iterations > defaultPBKDF2Iters {
- return fmt.Errorf("too many iterations")
- }
- if h.SaltSize <= 0 || h.SaltSize > defaultSaltSize {
- return fmt.Errorf("salt size too long")
- }
- return nil
-}
-
-func (h *hashMetadata) hashPassword(password string, salt []byte) ([]byte, error) {
- return pbkdf2.Key(sha256.New, password, salt, int(h.Iterations), 32)
+func hashPassword(password string, salt []byte, iters int) ([]byte, error) {
+ return pbkdf2.Key(sha256.New, password, salt, iters, 32)
}
func termReadPassword() (string, error) {
diff --git a/pwhash_string.go b/pwhash_string.go
deleted file mode 100644
index 37796a8..0000000
--- a/pwhash_string.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Code generated by "stringer -type=pwHash -linecomment"; DO NOT EDIT.
-
-package main
-
-import "strconv"
-
-func _() {
- // An "invalid array index" compiler error signifies that the constant values have changed.
- // Re-run the stringer command to generate them again.
- var x [1]struct{}
- _ = x[pwHashInvalid-0]
- _ = x[pwHashPBKDF2_HMAC_SHA256-1]
-}
-
-const _pwHash_name = "pwHashInvalidPBKDF2-HMAC-SHA256"
-
-var _pwHash_index = [...]uint8{0, 13, 31}
-
-func (i pwHash) String() string {
- idx := int(i) - 0
- if i < 0 || idx >= len(_pwHash_index)-1 {
- return "pwHash(" + strconv.FormatInt(int64(i), 10) + ")"
- }
- return _pwHash_name[_pwHash_index[idx]:_pwHash_index[idx+1]]
-}
diff --git a/sym_test.go b/sym_test.go
index 7a223e3..4d648d3 100644
--- a/sym_test.go
+++ b/sym_test.go
@@ -13,6 +13,12 @@ var testEncryptOptions = func() encryptOptions {
return opts
}()
+var testDecryptOptions = func() decryptOptions {
+ opts := defaultDecryptOptions
+ opts.iterations = 10
+ return opts
+}()
+
func mustWriteFile(t *testing.T, path string, content []byte) {
t.Helper()
if err := os.WriteFile(path, content, 0600); err != nil {
@@ -65,7 +71,7 @@ func TestEncryptDecrypt(t *testing.T) {
t.Fatalf("EncryptFile failed: %s", err)
}
mustRemove(t, fileName)
- if err := defaultDecryptOptions.decryptFile(fileName+".enc", password); err != nil {
+ if err := testDecryptOptions.decryptFile(fileName+".enc", password); err != nil {
t.Fatalf("DecryptFile failed: %s", err)
}
gotContents := mustReadFile(t, fileName)