diff --git a/README.md b/README.md index df1b4b4..9766344 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # sputter -_WARNING: I AM NOT CRYPTO FRIENDLY_ - POSIX basic regular expressions to psuedo random string generator, just for fun :) ### Usage @@ -31,6 +29,8 @@ WordWord Њѯѹկ¢↔≡♲ ``` +_For cryptographically insecure usage, use the `GenInsecure` function in place of `Gen`_ + ### Supported Operations diff --git a/sputter.go b/sputter.go index 8258a85..7aa2da5 100644 --- a/sputter.go +++ b/sputter.go @@ -2,7 +2,9 @@ package sputter import ( "bytes" + crypto "crypto/rand" "fmt" + "math/big" "math/rand" "regexp/syntax" "time" @@ -11,15 +13,33 @@ import ( const ( repetitionMax = 100 + maxUint64 = ^uint64(0) + maxInt64 = int64(maxUint64 >> 1) ) +func init() { + rand.Seed(time.Now().UTC().UnixNano()) +} + // Gen takes a regular expression and attempts // to generate a pseudo-randomized string that // matches the input expression. func Gen(exp string) (string, error) { - // setup random package - rand.Seed(time.Now().UTC().UnixNano()) + // cryptographically seed random package + bigSeed, err := crypto.Int(crypto.Reader, big.NewInt(maxInt64)) + if err != nil { + return "", err + } + rand.Seed(bigSeed.Int64()) + + r, err := syntax.Parse(exp, 0) + if err != nil { + return "", err + } + return sput(r) +} +func GenInsecure(exp string) (string, error) { r, err := syntax.Parse(exp, 0) if err != nil { return "", err diff --git a/sputter_test.go b/sputter_test.go index 9ca2b92..7c9101e 100644 --- a/sputter_test.go +++ b/sputter_test.go @@ -62,6 +62,7 @@ func TestEndLine(t *testing.T) { } func testSputHundredEmoji(t *testing.T, exp string) { + // test cryptographically secure function 100 times for i := 0; i < 100; i++ { s, err := Gen(exp) if err != nil { @@ -77,4 +78,21 @@ func testSputHundredEmoji(t *testing.T, exp string) { t.Error(err) } } + + // do same for cryptographically insecure function + for i := 0; i < 100; i++ { + s, err := GenInsecure(exp) + if err != nil { + t.Error(`error from Gen:`, err) + } + + match, err := regexp.Match(exp, []byte(s)) + if !match { + t.Errorf(`output string "%s" does not match expression "%s"`, s, exp) + } + + if err != nil { + t.Error(err) + } + } }