Skip to content

crypto/rand: Documentation for non-specialists #54979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Deleplace opened this issue Sep 9, 2022 · 5 comments
Closed

crypto/rand: Documentation for non-specialists #54979

Deleplace opened this issue Sep 9, 2022 · 5 comments
Labels
Documentation Issues describing a change to documentation. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@Deleplace
Copy link
Contributor

The crypto/rand package contains 1 documented exported global object "Reader", 3 documented exported funcs, and 1 full example showing how to produce 10 random bytes.

It may be non-trivial for some developers to correctly derive common use cases from this API and this example.

It seems that we may have 2 opposite approaches A and B about how we want the crypto/rand package to be used:

A. Crypto is subtle in general. If one is not sure of what they're doing, they shouldn't use the crypto/rand package, risking to use it incorrectly and getting a false feeling of security. This is more or less the warning of the crypto/subtle, applied to all things crypto. So our best advice is to discourage many developers from using crypto/rand.

B. Generating sensitive secrets (nonces, passwords) is a common use case, for which using math/rand is mostly incorrect. math/rand has a useful warning about this "This package's outputs might be easily predictable regardless of how it's seeded. For random numbers suitable for security-sensitive work, see the crypto/rand package." We want to strongly discourage math/rand for sensitive numbers, thus we expect developers to use crypto/rand and encourage them to do so.

The following assumes that our approach is B, not A.

math/rand and crypto/rand have a different API, and sometimes what we want is the convenience and features of the "math" API, with the security provided by the "crypto" package.

As a contrived but realistic example, let's say a non-cryptographer needs to generate a secure random string of 16 characters, where each character is in range 'a'-'z', uniform, per some 3rd party API requirements.

This would be straightforward with the math/rand API:

var alphabet = "abcdefghijklmnopqrstuvwxyz"

func generateNonce() string {
	a := make([]byte, 16)
	for i := range a {
		a[i] = alphabet[rand.Intn(len(alphabet))]
	}
	return string(a)
}

and more complicated with the crypto/rand API:

func generateNonce() (string, error) {
	a := make([]byte, 16)
	for i := range a {
		bi, err := rand.Int(rand.Reader, big.NewInt(int64(len(alphabet))))
		if err != nil {
			return "", err
		}
		k := int(bi.Int64())
		a[i] = alphabet[k]
	}
	return string(a), nil
}

Even worse, the developer could use incorrect shortcuts in good faith, without noticing:

func generateNonce() (string, error) {
	a := make([]byte, 16)
	_, err := rand.Read(a)
	if err != nil {
		return "", err
	}
	for i := range a {
		k := a[i] % byte(len(alphabet))     // <- probable bug here
		a[i] = alphabet[k]
	}
	return string(a), nil
}

(this distribution is skewed, which could be bad for security, though I'm not sure how bad exactly)

My suggestion is to embrace B and enrich the documentation of crypto/rand with vetted examples for a few use cases. Before writing any, I'd like to discuss the idea.

@gopherbot gopherbot added the Documentation Issues describing a change to documentation. label Sep 9, 2022
@Deleplace
Copy link
Contributor Author

Deleplace commented Sep 9, 2022

Also, it's currently not explicit why the crypto/rand API returns errors: #54980

@mknyszek mknyszek added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 9, 2022
@mknyszek mknyszek added this to the Backlog milestone Sep 9, 2022
@mknyszek
Copy link
Contributor

mknyszek commented Sep 9, 2022

CC @golang/security

@seankhliao
Copy link
Member

Note we've recently declined adding such a random string generator in crypto/rand: #53447

It seems unlikely we will want to put the same thing in the docs or examples.
Like the conclusion of that proposal, it seems better suited for a third party package.

@Deleplace
Copy link
Contributor Author

Thanks Sean for the link, I wasn't aware of #53447 yet

@seankhliao
Copy link
Member

Duplicate of #25326

@seankhliao seankhliao marked this as a duplicate of #25326 Sep 13, 2022
@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Sep 13, 2022
@golang golang locked and limited conversation to collaborators Sep 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Documentation Issues describing a change to documentation. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants