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.
Agree that the Read example should be a package level example. It mostly demonstrates how the package is used most commonly.
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.
If we don't show how to implement one of the math/rand functions, then we have two options.
rand.Read with a slice of a certain size, so I'm not sure this would be a useful example.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
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))
}
Change https://golang.org/cl/119335 mentions this issue: crypto/rand: Add package-level examples
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.
Most helpful comment
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.