tests: add scrypt tests and move Go files from testdata

This commit is contained in:
Filippo Valsorda
2022-06-15 20:16:36 +02:00
parent 787044bdb6
commit 92713afd1e
45 changed files with 231 additions and 31 deletions

2
.gitattributes vendored
View File

@@ -1,2 +1,2 @@
*.age binary
*.test binary
testdata/testkit/* binary

View File

@@ -1,7 +0,0 @@
age-encryption.org/v1
-> scrypt z8U9dYMQuK1fFdvtpQYLEQ 10
5SVjw1bbFCZLdI1FR7RqfTd3yWo4KS1ikOjvz60Bpqhrv0W6o6/2oszxZEm1gEUC
--- YXxSwONGPBbV7woMuEFTYuA03qTYUF1k0Y8j/NDEu1o
’Ì
Å!í‡ i<7F>Þ.f¦æš{ŸdËIE]© ñn”$È!b®2

Binary file not shown.

View File

@@ -1,5 +0,0 @@
age-encryption.org/v1
-> scrypt 1Q6WlGmsRulbN7bmUw8A1Q 23
GP2lnzFuk1dgEkcMPmK6KkmuOm5gIWJzLeuwGcRsvAY
--- vXvOsVbDbMc0x5Js1FS6k1ViOJ3H2ZdSUZo9bfvbzmU
=ñÅÙœ£¨v>¹vhKMû'ÕßúÙ½NeçS†Äñ\(_ó

View File

@@ -1,5 +0,0 @@
age-encryption.org/v1
-> scrypt qEa/WztCd2KJ4mKwNf1Yrw 10
TQZ4GpAaH4aR4oSDWZTgeRT4wRby4jwmtB02dElWmVQ
--- kOiEP6uoMyK9GKIsV77o4oaPuEr2Q0vdcu+1RKC3lLU
hŸo²P¤V w§\5~4ôënE½oÕd>rOš°mÒÛ¨

View File

@@ -12,6 +12,7 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"filippo.io/age/internal/bech32"
@@ -19,6 +20,7 @@ import (
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/scrypt"
)
var TestFileKey = []byte("YELLOW SUBMARINE")
@@ -39,6 +41,7 @@ type TestFile struct {
expect string
comment string
identities []string
passphrases []string
}
func NewTestFile() *TestFile {
@@ -117,6 +120,23 @@ func (f *TestFile) X25519NoRecordIdentity(identity []byte) {
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) {
f.TextLine("--- " + b64(h))
}
@@ -176,6 +196,9 @@ func (f *TestFile) Generate() {
for _, id := range f.identities {
fmt.Printf("identity: %s\n", id)
}
for _, p := range f.passphrases {
fmt.Printf("passphrase: %s\n", p)
}
if f.comment != "" {
fmt.Printf("comment: %s\n", f.comment)
}

BIN
testdata/testkit/long_file_key_scrypt vendored Normal file

Binary file not shown.

BIN
testdata/testkit/scrypt vendored Normal file

Binary file not shown.

12
testdata/testkit/scrypt_and_x25519 vendored Normal file
View File

@@ -0,0 +1,12 @@
expect: header failure
file key: 59454c4c4f57205355424d4152494e45
passphrase: password
comment: scrypt stanzas must be alone in the header
age-encryption.org/v1
-> X25519 TEiF0ypqr+bpvcqXNyCVJpL7OuwPdVwPL7KQEbFDOCc
hjabGXwSLQ9c3S6Lw2i+S2Tu2fiwQHHslbBN6B41FLE
-> scrypt 7s9ix86RtDMnTmjU8vkTTA 10
0U4Pbxsl9pr9g4nHjPgkvtYkNrGiYJ43x1vbM5X5mhg
--- f2AoyFXU2R5Cn7s38vH1pFkuKqzPh3ibwwHc/7y6RRU
[æè. ½Ó#ÈwÏ…=a×Yök×z©66Ú¦<01>âRùÛL

BIN
testdata/testkit/scrypt_no_match vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,9 @@
expect: header failure
file key: 59454c4c4f57205355424d4152494e45
comment: work factor is very high, would take a long time to compute
age-encryption.org/v1
-> scrypt rF0/NwblUHHTpgQgRpe5CQ 23
qW9eVsT0NVb/Vswtw8kPIxUnaYmm9Px1dYmq2+4+qZA
--- 38TpQMxQRRNMfmYYpBX6DDrPx4/QY5UmJnhPyVoX/cw
¬]?7åPqÓ¦ F—¹ •Â÷õÛ®è zŒ(rŠóÎ|

12
testdata/testkit/valid_characters vendored Normal file
View File

@@ -0,0 +1,12 @@
expect: success
payload: 013f54400c82da08037759ada907a8b864e97de81c088a182062c4b5622fd2ab
file key: 59454c4c4f57205355424d4152494e45
identity: AGE-SECRET-KEY-1XMWWC06LY3EE5RYTXM9MFLAZ2U56JJJ36S0MYPDRWSVLUL66MV4QX3S7F6
age-encryption.org/v1
-> !"#$%&' ()*+,-./ 01234567 89:;<=>? @ABCDEFG HIJKLMNO PQRSTUVW XYZ[\]^_ `abcdefg hijklmno pqrstuvw xyz{|}~
-> X25519 TEiF0ypqr+bpvcqXNyCVJpL7OuwPdVwPL7KQEbFDOCc
EmECAEcKN+n/Vs9SbWiV+Hu0r+E8R77DdWYyd83nw7U
--- XdSsgCFKtyPBxU0ard+ElUYUfOp6XQtDhzDGFUCLbjo
îÏbÇδ3'NhÔòùL·L[þ÷¾ªRÈð¼™,ƒ1ûf

View File

@@ -0,0 +1,12 @@
expect: success
payload: 013f54400c82da08037759ada907a8b864e97de81c088a182062c4b5622fd2ab
file key: 59454c4c4f57205355424d4152494e45
identity: AGE-SECRET-KEY-1XMWWC06LY3EE5RYTXM9MFLAZ2U56JJJ36S0MYPDRWSVLUL66MV4QX3S7F6
age-encryption.org/v1
-> X25519 ajtqAvDEkVNr2B7zUOtq2mAQXDSBlNrVAuM/dKb5sT4
0evrK/HQXVsQ4YaDe+659l5OQzvAzD2ytLGHQLQiqxg
-> X25519 0qC7u6AbLxuwnM8tPFOWVtWZn/ZZe7z7gcsP5kgA0FI
T/PZg76MmVt2IaLntrxppzDnzeFDYHsHFcnTnhbRLQ8
--- 7W07ef2PhsTAl74pn+9vSj/Xzukwa6SuTqMc16cdBk0
ð¸¾5TB9™ ­€„Ko•Ãm³^OYØøž<òo-¥B

View File

@@ -27,19 +27,20 @@ func TestMain(m *testing.M) {
flag.Parse()
if *genFlag {
log.SetFlags(0)
tests, err := filepath.Glob("testdata/*.test")
tests, err := filepath.Glob("testdata/testkit/*")
if err != nil {
log.Fatal(err)
}
for _, test := range tests {
os.Remove(test)
}
generators, err := filepath.Glob("testdata/*.go")
generators, err := filepath.Glob("tests/*.go")
if err != nil {
log.Fatal(err)
}
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)
out, err := exec.Command("go", "run", generator).Output()
if err != nil {
@@ -56,7 +57,7 @@ func TestMain(m *testing.M) {
}
func TestVectors(t *testing.T) {
tests, err := filepath.Glob("testdata/*.test")
tests, err := filepath.Glob("testdata/testkit/*")
if err != nil {
log.Fatal(err)
}
@@ -65,8 +66,7 @@ func TestVectors(t *testing.T) {
if err != nil {
t.Fatal(err)
}
name := strings.TrimPrefix(test, "testdata/")
name = strings.TrimSuffix(name, ".test")
name := strings.TrimPrefix(test, "testdata/testkit/")
t.Run(name, func(t *testing.T) {
testVector(t, contents)
})
@@ -114,6 +114,12 @@ func testVector(t *testing.T, test []byte) {
t.Fatal(err)
}
identities = append(identities, i)
case "passphrase":
i, err := age.NewScryptIdentity(value)
if err != nil {
t.Fatal(err)
}
identities = append(identities, i)
case "file key":
// Ignored.
case "comment":

View 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
View 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()
}

View 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
View 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()
}

View 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
View 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()
}

View 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()
}