Skip to content
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

crypto/rand: add package example #25326

Open
kevinburke opened this issue May 10, 2018 · 6 comments
Open

crypto/rand: add package example #25326

kevinburke opened this issue May 10, 2018 · 6 comments
Labels
Documentation help wanted NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@kevinburke
Copy link
Contributor

The crypto/rand package has no package example; even just copying the Read example up to the package level would be helpful.

The crypto/rand package also doesn't have the same convenience helpers that math/rand has, so it might be helpful to see e.g. how to implement Intn using the crypto/rand package.

@agnivade
Copy link
Contributor

Agree that the Read example should be a package level example. It mostly demonstrates how the package is used most commonly.

@slrz
Copy link

slrz commented May 10, 2018

Wanting cryptographically-secure random machine-sized integers seems like an awfully obscure use case to me. The convenience helpers from math/rand just don't have many sensible applications in cryptographic code.

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone May 31, 2018
@ianlancetaylor ianlancetaylor added help wanted NeedsFix The path to resolution is known, but the work has not been done. labels May 31, 2018
@smasher164
Copy link
Member

If we don't show how to implement one of the math/rand functions, then we have two options.

  1. Show how to generate a key of a certain size needed for signing or encryption.
    a. Key generation is pretty much just calling rand.Read with a slice of a certain size, so I'm not sure this would be a useful example.
  2. Actually implement a rudimentary cipher that makes use of randomness.
    a. I like the idea of providing a simple one-time pad implementation, to show how random bytes are used in an encryption algorithm.

Here's an example implementation:

package main

import (
	"crypto/rand"
	"fmt"
)

func main() {
	plaintext := []byte("Something something gopher...")
	n := len(plaintext)
	key := make([]byte, n)
	ciphertext := make([]byte, n)
	// Read n random bytes into key. A one-time pad requires the key to be at least as long as the plaintext.
	if _, err := rand.Read(key); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Original: %x\n", plaintext)
	// Encrypt message by XOR'ing the plaintext and the key.
	for i := 0; i < n; i++ {
		ciphertext[i] = plaintext[i] ^ key[i]
	}
	fmt.Printf("Encrypted: %x\n", ciphertext)
	// Decrypt message by XOR'ing the ciphertext and the key.
	for i := 0; i < n; i++ {
		ciphertext[i] = ciphertext[i] ^ key[i]
	}
	fmt.Printf("Decrypted: %x\n", ciphertext)
}

An example output would produce something similar:

Original: 536f6d657468696e6720736f6d657468696e6720676f706865722e2e2e
Encrypted: 43595ee3ae72a73a8da5a253bd4fce592a27c91cbae902128a56e42be4
Decrypted: 536f6d657468696e6720736f6d657468696e6720676f706865722e2e2e

@smasher164
Copy link
Member

I'm not sure if this is the right track to go, but an example for rand.Prime can be plain old RSA key generation. Obviously, we would have to warn users not to actually run this in production.

package main

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

func main() {
	// Choose two random primes p and q
	p, err := rand.Prime(rand.Reader, 100)
	if err != nil {
		fmt.Println(err)
		return
	}
	q, err := rand.Prime(rand.Reader, 100)
	if err != nil {
		fmt.Println(err)
		return
	}
	// Let n = p * q
	var n big.Int
	n.Mul(p, q)
	// Let totient = (p - 1) * (q - 1)
	one := big.NewInt(1)
	p.Sub(p, one)
	q.Sub(q, one)
	var totient big.Int
	totient.Mul(p, q)
	// Let e be coprime to the totient
	e := big.NewInt(3)
	// Let d satisfy d*e ≡ 1 mod totient
	var d big.Int
	d.ModInverse(e, &totient)
	fmt.Printf("Public Key-Pair: (%s, %s)\n", n.Text(10), e.Text(10))
	fmt.Printf("Private Key-Pair: (%s, %s)\n", n.Text(10), d.Text(10))
}

@gopherbot
Copy link

Change https://golang.org/cl/119335 mentions this issue: crypto/rand: Add package-level examples

@smasher164
Copy link
Member

I would appreciate feedback or criticism to these examples so that they can be useful for Go programmers. The CL is just a starting point, and hopefully your comments can be incorporated into proper package-level examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation help wanted NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants