Go: crypto/rand: add package example

Created on 10 May 2018  Â·  6Comments  Â·  Source: golang/go

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.

Documentation NeedsFix help wanted

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.

All 6 comments

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.

  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

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.

Was this page helpful?
0 / 5 - 0 ratings