mirror of
https://github.com/FiloSottile/age.git
synced 2026-03-11 08:55:41 +00:00
tests: add scrypt tests and move Go files from testdata
This commit is contained in:
parent
787044bdb6
commit
92713afd1e
45 changed files with 186 additions and 14 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,2 +1,2 @@
|
||||||
*.age binary
|
*.age binary
|
||||||
*.test binary
|
testdata/testkit/* binary
|
||||||
|
|
|
||||||
BIN
cmd/age/testdata/fail_large_filekey_scrypt.age
vendored
BIN
cmd/age/testdata/fail_large_filekey_scrypt.age
vendored
Binary file not shown.
BIN
cmd/age/testdata/fail_scrypt_and_x25519.age
vendored
BIN
cmd/age/testdata/fail_scrypt_and_x25519.age
vendored
Binary file not shown.
BIN
cmd/age/testdata/fail_scrypt_work_factor_23.age
vendored
BIN
cmd/age/testdata/fail_scrypt_work_factor_23.age
vendored
Binary file not shown.
BIN
cmd/age/testdata/good_scrypt_work_factor_10.age
vendored
BIN
cmd/age/testdata/good_scrypt_work_factor_10.age
vendored
Binary file not shown.
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"filippo.io/age/internal/bech32"
|
"filippo.io/age/internal/bech32"
|
||||||
|
|
@ -19,6 +20,7 @@ import (
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
|
"golang.org/x/crypto/scrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TestFileKey = []byte("YELLOW SUBMARINE")
|
var TestFileKey = []byte("YELLOW SUBMARINE")
|
||||||
|
|
@ -32,13 +34,14 @@ type TestFile struct {
|
||||||
Buf bytes.Buffer
|
Buf bytes.Buffer
|
||||||
Rand func(n int) []byte
|
Rand func(n int) []byte
|
||||||
|
|
||||||
fileKey []byte
|
fileKey []byte
|
||||||
streamKey []byte
|
streamKey []byte
|
||||||
nonce [12]byte
|
nonce [12]byte
|
||||||
payload bytes.Buffer
|
payload bytes.Buffer
|
||||||
expect string
|
expect string
|
||||||
comment string
|
comment string
|
||||||
identities []string
|
identities []string
|
||||||
|
passphrases []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestFile() *TestFile {
|
func NewTestFile() *TestFile {
|
||||||
|
|
@ -117,6 +120,23 @@ func (f *TestFile) X25519NoRecordIdentity(identity []byte) {
|
||||||
f.AEADBody(key, f.fileKey)
|
f.AEADBody(key, f.fileKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *TestFile) Scrypt(passphrase string, workFactor int) {
|
||||||
|
f.ScryptRecordPassphrase(passphrase)
|
||||||
|
f.ScryptNoRecordPassphrase(passphrase, workFactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *TestFile) ScryptRecordPassphrase(passphrase string) {
|
||||||
|
f.passphrases = append(f.passphrases, passphrase)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *TestFile) ScryptNoRecordPassphrase(passphrase string, workFactor int) {
|
||||||
|
salt := f.Rand(16)
|
||||||
|
f.ArgsLine("scrypt", b64(salt), strconv.Itoa(workFactor))
|
||||||
|
key, _ := scrypt.Key([]byte(passphrase), append([]byte("age-encryption.org/v1/scrypt"), salt...),
|
||||||
|
1<<workFactor, 8, 1, 32)
|
||||||
|
f.AEADBody(key, f.fileKey)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *TestFile) HMACLine(h []byte) {
|
func (f *TestFile) HMACLine(h []byte) {
|
||||||
f.TextLine("--- " + b64(h))
|
f.TextLine("--- " + b64(h))
|
||||||
}
|
}
|
||||||
|
|
@ -176,6 +196,9 @@ func (f *TestFile) Generate() {
|
||||||
for _, id := range f.identities {
|
for _, id := range f.identities {
|
||||||
fmt.Printf("identity: %s\n", id)
|
fmt.Printf("identity: %s\n", id)
|
||||||
}
|
}
|
||||||
|
for _, p := range f.passphrases {
|
||||||
|
fmt.Printf("passphrase: %s\n", p)
|
||||||
|
}
|
||||||
if f.comment != "" {
|
if f.comment != "" {
|
||||||
fmt.Printf("comment: %s\n", f.comment)
|
fmt.Printf("comment: %s\n", f.comment)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
testdata/testkit/long_file_key_scrypt
vendored
Normal file
BIN
testdata/testkit/long_file_key_scrypt
vendored
Normal file
Binary file not shown.
BIN
testdata/testkit/scrypt
vendored
Normal file
BIN
testdata/testkit/scrypt
vendored
Normal file
Binary file not shown.
BIN
testdata/testkit/scrypt_and_x25519
vendored
Normal file
BIN
testdata/testkit/scrypt_and_x25519
vendored
Normal file
Binary file not shown.
BIN
testdata/testkit/scrypt_no_match
vendored
Normal file
BIN
testdata/testkit/scrypt_no_match
vendored
Normal file
Binary file not shown.
BIN
testdata/testkit/scrypt_work_factor_23
vendored
Normal file
BIN
testdata/testkit/scrypt_work_factor_23
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
testdata/testkit/valid_characters
vendored
Normal file
BIN
testdata/testkit/valid_characters
vendored
Normal file
Binary file not shown.
BIN
testdata/testkit/x25519_multiple_recipients
vendored
Normal file
BIN
testdata/testkit/x25519_multiple_recipients
vendored
Normal file
Binary file not shown.
|
|
@ -27,19 +27,20 @@ func TestMain(m *testing.M) {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *genFlag {
|
if *genFlag {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
tests, err := filepath.Glob("testdata/*.test")
|
tests, err := filepath.Glob("testdata/testkit/*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
os.Remove(test)
|
os.Remove(test)
|
||||||
}
|
}
|
||||||
generators, err := filepath.Glob("testdata/*.go")
|
generators, err := filepath.Glob("tests/*.go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, generator := range generators {
|
for _, generator := range generators {
|
||||||
vector := strings.TrimSuffix(generator, ".go") + ".test"
|
vector := strings.TrimSuffix(generator, ".go")
|
||||||
|
vector = "testdata/testkit/" + strings.TrimPrefix(vector, "tests/")
|
||||||
log.Printf("%s -> %s\n", generator, vector)
|
log.Printf("%s -> %s\n", generator, vector)
|
||||||
out, err := exec.Command("go", "run", generator).Output()
|
out, err := exec.Command("go", "run", generator).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -56,7 +57,7 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVectors(t *testing.T) {
|
func TestVectors(t *testing.T) {
|
||||||
tests, err := filepath.Glob("testdata/*.test")
|
tests, err := filepath.Glob("testdata/testkit/*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -65,8 +66,7 @@ func TestVectors(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
name := strings.TrimPrefix(test, "testdata/")
|
name := strings.TrimPrefix(test, "testdata/testkit/")
|
||||||
name = strings.TrimSuffix(name, ".test")
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
testVector(t, contents)
|
testVector(t, contents)
|
||||||
})
|
})
|
||||||
|
|
@ -114,6 +114,12 @@ func testVector(t *testing.T, test []byte) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
identities = append(identities, i)
|
identities = append(identities, i)
|
||||||
|
case "passphrase":
|
||||||
|
i, err := age.NewScryptIdentity(value)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
identities = append(identities, i)
|
||||||
case "file key":
|
case "file key":
|
||||||
// Ignored.
|
// Ignored.
|
||||||
case "comment":
|
case "comment":
|
||||||
|
|
|
||||||
21
tests/long_file_key_scrypt.go
Normal file
21
tests/long_file_key_scrypt.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.FileKey([]byte("A LONGER YELLOW SUBMARINE"))
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.Scrypt("password", 10)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.ExpectHeaderFailure()
|
||||||
|
f.Comment("the file key must be checked to be 16 bytes before decrypting it")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
18
tests/scrypt.go
Normal file
18
tests/scrypt.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.Scrypt("password", 10)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
21
tests/scrypt_and_x25519.go
Normal file
21
tests/scrypt_and_x25519.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.X25519NoRecordIdentity(testkit.TestX25519Identity)
|
||||||
|
f.Scrypt("password", 10)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.ExpectHeaderFailure()
|
||||||
|
f.Comment("scrypt stanzas must be alone in the header")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
20
tests/scrypt_no_match.go
Normal file
20
tests/scrypt_no_match.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.ScryptRecordPassphrase("wrong")
|
||||||
|
f.ScryptNoRecordPassphrase("password", 10)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.ExpectHeaderFailure()
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
23
tests/scrypt_work_factor_23.go
Normal file
23
tests/scrypt_work_factor_23.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
// Hardcoded because it would be too slow to regenerate every time.
|
||||||
|
// f.Scrypt("password", 23)
|
||||||
|
f.ArgsLine("scrypt", "rF0/NwblUHHTpgQgRpe5CQ", "23")
|
||||||
|
f.TextLine("qW9eVsT0NVb/Vswtw8kPIxUnaYmm9Px1dYmq2+4+qZA")
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.ExpectHeaderFailure()
|
||||||
|
f.Comment("work factor is very high, would take a long time to compute")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
21
tests/valid_characters.go
Normal file
21
tests/valid_characters.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.ArgsLine("!\"#$%&'", "()*+,-./", "01234567", "89:;<=>?", "@ABCDEFG",
|
||||||
|
"HIJKLMNO", "PQRSTUVW", "XYZ[\\]^_", "`abcdefg", "hijklmno", "pqrstuvw", "xyz{|}~")
|
||||||
|
f.Body([]byte(""))
|
||||||
|
f.X25519(testkit.TestX25519Recipient)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
19
tests/x25519_multiple_recipients.go
Normal file
19
tests/x25519_multiple_recipients.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2022 The age Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "filippo.io/age/internal/testkit"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f := testkit.NewTestFile()
|
||||||
|
f.VersionLine("v1")
|
||||||
|
f.X25519NoRecordIdentity(f.Rand(32))
|
||||||
|
f.X25519(testkit.TestX25519Recipient)
|
||||||
|
f.HMAC()
|
||||||
|
f.Payload("age")
|
||||||
|
f.Generate()
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue