summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/scrypt.go92
-rwxr-xr-xtests/cli-opts.sh45
-rwxr-xr-xtests/integration.sh16
-rw-r--r--tests/scrypt.go56
4 files changed, 114 insertions, 95 deletions
diff --git a/src/scrypt.go b/src/scrypt.go
index 1cb3b44..be00674 100644
--- a/src/scrypt.go
+++ b/src/scrypt.go
@@ -1,6 +1,7 @@
package scrypt
import (
+ "bufio"
"crypto/rand"
"encoding/hex"
"flag"
@@ -8,6 +9,7 @@ import (
"io"
"os"
"slices"
+ "strings"
gt "gotext"
g "gobang"
@@ -54,7 +56,7 @@ type CheckInputT struct{
type argsT struct{
allArgs []string
- input HashInputT
+ isCheck bool
}
type envT struct{
@@ -168,7 +170,7 @@ func Check(input CheckInputT) (bool, error) {
func usage(argv0 string, w io.Writer) {
fmt.Fprintf(
w,
- gt.Gettext("Usage: %s PASSWORD SALT\n"),
+ gt.Gettext("Usage: %s [-c]\n"),
argv0,
)
}
@@ -177,6 +179,7 @@ func getopt(allArgs []string, w io.Writer) (argsT, int) {
argv0 := allArgs[0]
argv := allArgs[1:]
fs := flag.NewFlagSet("", flag.ContinueOnError)
+ isCheck := fs.Bool("c", false, "")
fs.Usage = func() {}
fs.SetOutput(w)
@@ -185,34 +188,85 @@ func getopt(allArgs []string, w io.Writer) (argsT, int) {
return argsT{}, 2
}
- subArgs := fs.Args()
- if len(subArgs) != 2 {
- usage(argv0, w)
- return argsT{}, 2
- }
-
- password := []byte(subArgs[0])
- salt := []byte(subArgs[1])
- input := HashInputT{
- Password: password,
- Salt: salt,
- }
return argsT{
allArgs: allArgs,
- input: input,
+ isCheck: *isCheck,
}, 0
}
func run(env envT) int {
- payload, err := Hash(env.args.input)
+ reader := bufio.NewReader(env.in)
+
+ hexPassword, err := reader.ReadString('\n')
if err != nil {
fmt.Fprintln(env.err, err)
- return 1
+ return 2
}
- fmt.Fprintln(env.out, hex.EncodeToString(payload))
- return 0
+ password, err := hex.DecodeString(strings.TrimSpace(hexPassword))
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ hexSalt, err := reader.ReadString('\n')
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ salt, err := hex.DecodeString(strings.TrimSpace(hexSalt))
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ if !env.args.isCheck {
+ input := HashInputT{
+ Password: password,
+ Salt: salt,
+ }
+
+ payload, err := Hash(input)
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ fmt.Fprintln(env.out, hex.EncodeToString(payload))
+ return 0
+ } else {
+ hexHash, err := reader.ReadString('\n')
+ if err != nil {
+ fmt.Println(env.err, err)
+ return 2
+ }
+
+ hash, err := hex.DecodeString(strings.TrimSpace(hexHash))
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ input := CheckInputT{
+ Password: password,
+ Salt: salt,
+ Hash: hash,
+ }
+
+ match, err := Check(input)
+ if err != nil {
+ fmt.Fprintln(env.err, err)
+ return 2
+ }
+
+ if match {
+ return 0
+ } else {
+ return 1
+ }
+ }
}
diff --git a/tests/cli-opts.sh b/tests/cli-opts.sh
index 4f59185..92b70ea 100755
--- a/tests/cli-opts.sh
+++ b/tests/cli-opts.sh
@@ -1,47 +1,2 @@
#!/bin/sh
set -eu
-
-. tests/lib.sh
-
-
-test_needs_2_arguments() {
- testing 'needs 2 arguments'
-
- N="$LINENO"
- OUT="$(mkstemp)"
- ERR="$(mkstemp)"
- trap 'rm -f "$OUT" "$ERR"' EXIT
- STATUS=0
- ./scrypt.bin 1>"$OUT" 2>"$ERR" || STATUS=$?
- assert_status 2
- assert_empty_stdout
- assert_usage "$ERR"
- rm -f "$OUT" "$ERR"
-
- N="$LINENO"
- OUT="$(mkstemp)"
- ERR="$(mkstemp)"
- trap 'rm -f "$OUT" "$ERR"' EXIT
- STATUS=0
- ./scrypt.bin password 1>"$OUT" 2>"$ERR" || STATUS=$?
- assert_status 2
- assert_empty_stdout
- assert_usage "$ERR"
- rm -f "$OUT" "$ERR"
-
- N="$LINENO"
- OUT="$(mkstemp)"
- ERR="$(mkstemp)"
- trap 'rm -f "$OUT" "$ERR"' EXIT
- STATUS=0
- ./scrypt.bin salt 1>"$OUT" 2>"$ERR" || STATUS=$?
- assert_status 2
- assert_empty_stdout
- assert_usage "$ERR"
- rm -f "$OUT" "$ERR"
-
- test_ok
-}
-
-
-test_needs_2_arguments
diff --git a/tests/integration.sh b/tests/integration.sh
index 8115ce5..d8d8dcd 100755
--- a/tests/integration.sh
+++ b/tests/integration.sh
@@ -12,8 +12,11 @@ test_needs_minimum_salt_length() {
ERR="$(mkstemp)"
trap 'rm -f "$OUT" "$ERR"' EXIT
STATUS=0
- ./scrypt.bin password salt 1>"$OUT" 2>"$ERR" || STATUS=$?
- assert_status 1
+ PASSWORD='71617373776f7264'
+ SALT='73616c74'
+ printf '%s\n%s\n' "$PASSWORD" "$SALT" |
+ ./scrypt.bin 1>"$OUT" 2>"$ERR" || STATUS=$?
+ assert_status 2
assert_empty_stdout
assert_fgrep_stderr 'salt is too small'
rm -f "$OUT" "$ERR"
@@ -29,11 +32,12 @@ test_same_input_same_output() {
ERR="$(mkstemp)"
trap 'rm -f "$OUT" "$ERR"' EXIT
STATUS=0
- # 8 16 24 32
- # v v v v
- SALT='saltsaltsaltsaltsaltsaltsaltsalti'
+ PASSWORD='70617373776f7264'
+ SALT='73616c7473616c7473616c7473616c7473616c7473616c7473616c7473616c74'
+ SALT="${SALT}69"
HASH='969a539633fd531309197c26a671d593da0eadbd31c1194c23bd1b143a0ecb5e'
- ./scrypt.bin password "$SALT" 1>"$OUT" 2>"$ERR" || STATUS=$?
+ printf '%s\n%s\n' "$PASSWORD" "$SALT" |
+ ./scrypt.bin 1>"$OUT" 2>"$ERR" || STATUS=$?
assert_status 0
assert_stdout "$HASH"
assert_empty_stderr
diff --git a/tests/scrypt.go b/tests/scrypt.go
index 0a9f599..2158e64 100644
--- a/tests/scrypt.go
+++ b/tests/scrypt.go
@@ -309,7 +309,7 @@ func test_usage() {
usage("xxx", &w)
expected := g.Heredoc(`
- Usage: xxx PASSWORD SALT
+ Usage: xxx [-c]
`)
g.TAssertEqual(w.String(), expected)
})
@@ -319,7 +319,7 @@ func test_getopt() {
g.TestStart("getopt()")
usage := g.Heredoc(`
- Usage: $0 PASSWORD SALT
+ Usage: $0 [-c]
`)
g.Testing("we suppress the default error message", func() {
@@ -341,17 +341,28 @@ func test_getopt() {
g.TAssertEqual(rc, 2)
})
- g.Testing("the args have the input data", func() {
+ g.Testing("the args have the strings untouched", func() {
w := strings.Builder{}
argv := []string{"$0", "abcdef", "aaaabbbbccccdddd"}
args, rc := getopt(argv, &w)
expected := argsT{
allArgs: []string{"$0", "abcdef", "aaaabbbbccccdddd"},
- input: HashInputT{
- Password: []byte("abcdef"),
- Salt: []byte("aaaabbbbccccdddd"),
- },
+ isCheck: false,
+ }
+
+ g.TAssertEqual(args, expected)
+ g.TAssertEqual(rc, 0)
+ })
+
+ g.Testing("isCheck is true", func() {
+ w := strings.Builder{}
+ argv := []string{"$0", "-c", "aaaabbbbccccdddd"}
+ args, rc := getopt(argv, &w)
+
+ expected := argsT{
+ allArgs: []string{"$0", "-c", "aaaabbbbccccdddd"},
+ isCheck: true,
}
g.TAssertEqual(args, expected)
@@ -365,39 +376,34 @@ func test_run() {
g.Testing("a small salt returns 1", func() {
w := strings.Builder{}
env := envT{
- args: argsT{
- input: HashInputT{
- Salt: []byte("a salt"),
- },
- },
+ in: strings.NewReader("612073616C74\naa\n"),
err: &w,
}
rc := run(env)
- g.TAssertEqual(rc, 1)
+ g.TAssertEqual(rc, 2)
g.TAssertEqual(w.String(), "scrypt: salt is too small\n")
})
g.Testing("return of 0 and output otherwise", func() {
- w := strings.Builder{}
+ out := strings.Builder{}
+ err := strings.Builder{}
env := envT{
- args: argsT{
- input: HashInputT{
- Salt: []byte(
- "eeeeffffgggghhhh" +
- "iiiijjjjjkkkkllll",
- ),
- Password: []byte("password"),
- },
- },
- out: &w,
+ in: strings.NewReader(
+ "70617373776F7264\n" +
+ "6565656566666666676767676868686869" +
+ "6969696A6A6A6A6A6B6B6B6B6C6C6C6C\n",
+ ),
+ out: &out,
+ err: &err,
}
const expected =
"9073ca9ad51942a30b20af1747e98195" +
"960e76fd8f20b246821692ce82c2d6f7\n"
rc := run(env)
- g.TAssertEqual(w.String(), expected)
+ g.TAssertEqual(out.String(), expected)
+ g.TAssertEqual(err.String(), "")
g.TAssertEqual(rc, 0)
})
}