Skip to content

Commit

Permalink
randutil: introduce an utility package for random value generation
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronis committed Feb 3, 2020
1 parent 69a017f commit 0464160
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 0 deletions.
46 changes: 46 additions & 0 deletions randutil/crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package randutil

import (
cryptorand "crypto/rand"
"encoding/base64"
"fmt"
)

// CryptoTokenBytes returns a crypthographically random token byte sequence.
func CryptoTokenBytes(nbytes int) ([]byte, error) {
b := make([]byte, nbytes)
_, err := cryptorand.Read(b)
if err != nil {
return nil, fmt.Errorf("canot obtain %d crypto random bytes: %v", nbytes, err)
}
return b, nil
}

// CryptoToken returns a crypthographically random token string.
// The result is URL-safe.
func CryptoToken(nbytes int) (string, error) {
b, err := CryptoTokenBytes(nbytes)
if err != nil {
return "", err
}
return base64.RawURLEncoding.EncodeToString(b), nil
}
47 changes: 47 additions & 0 deletions randutil/crypto_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package randutil_test

import (
"encoding/base64"

. "gopkg.in/check.v1"

"github.com/snapcore/snapd/randutil"
)

type cryptoRandutilSuite struct{}

var _ = Suite(&cryptoRandutilSuite{})

func (s *cryptoRandutilSuite) TestCryptoTokenBytes(c *C) {
x, err := randutil.CryptoTokenBytes(5)
c.Assert(err, IsNil)
c.Check(x, HasLen, 5)
}

func (s *cryptoRandutilSuite) TestCryptoToken(c *C) {
x, err := randutil.CryptoToken(5)
c.Assert(err, IsNil)

b, err := base64.RawURLEncoding.DecodeString(x)
c.Assert(err, IsNil)
c.Check(b, HasLen, 5)
}
63 changes: 63 additions & 0 deletions randutil/rand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2014-2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

// Package randutil initialises properly random value generation and
// exposes a streamlined set of functions for it, including for crypto
// random tokens.
package randutil

import (
cryptorand "crypto/rand"
"fmt"
"math"
"math/big"
"math/rand"
)

func init() {
// golang does not init Seed() itself
bigSeed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
panic(fmt.Sprintf("cannot obtain random seed: %v", err))
}
rand.Seed(bigSeed.Int64())
}

const letters = "BCDFGHJKLMNPQRSTVWXYbcdfghjklmnpqrstvwxy0123456789"

// MakeRandomString returns a random string of length length
//
// The vowels are omitted to avoid that words are created by pure
// chance. Numbers are included.
//
// Not cryptographically safe.
func MakeRandomString(length int) string {
out := ""
for i := 0; i < length; i++ {
out += string(letters[rand.Intn(len(letters))])
}

return out
}

// Rexported from math/rand for streamlining.
var (
Intn = rand.Intn
Int63n = rand.Int63n
)
46 changes: 46 additions & 0 deletions randutil/rand_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2014-2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package randutil_test

import (
"math/rand"
"testing"

. "gopkg.in/check.v1"

"github.com/snapcore/snapd/randutil"
)

func Test(t *testing.T) { TestingT(t) }

type randutilSuite struct{}

var _ = Suite(&randutilSuite{})

func (s *randutilSuite) TestMakeRandomString(c *C) {
// for our tests
rand.Seed(1)

s1 := randutil.MakeRandomString(10)
c.Assert(s1, Equals, "pw7MpXh0JB")

s2 := randutil.MakeRandomString(5)
c.Assert(s2, Equals, "4PQyl")
}

0 comments on commit 0464160

Please sign in to comment.