1package box_test
2
3import (
4	crypto_rand "crypto/rand" // Custom so it's clear which rand we're using.
5	"fmt"
6	"io"
7
8	"golang.org/x/crypto/nacl/box"
9)
10
11func Example() {
12	senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
13	if err != nil {
14		panic(err)
15	}
16
17	recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
18	if err != nil {
19		panic(err)
20	}
21
22	// You must use a different nonce for each message you encrypt with the
23	// same key. Since the nonce here is 192 bits long, a random value
24	// provides a sufficiently small probability of repeats.
25	var nonce [24]byte
26	if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
27		panic(err)
28	}
29
30	msg := []byte("Alas, poor Yorick! I knew him, Horatio")
31	// This encrypts msg and appends the result to the nonce.
32	encrypted := box.Seal(nonce[:], msg, &nonce, recipientPublicKey, senderPrivateKey)
33
34	// The recipient can decrypt the message using their private key and the
35	// sender's public key. When you decrypt, you must use the same nonce you
36	// used to encrypt the message. One way to achieve this is to store the
37	// nonce alongside the encrypted message. Above, we stored the nonce in the
38	// first 24 bytes of the encrypted text.
39	var decryptNonce [24]byte
40	copy(decryptNonce[:], encrypted[:24])
41	decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
42	if !ok {
43		panic("decryption error")
44	}
45	fmt.Println(string(decrypted))
46	// Output: Alas, poor Yorick! I knew him, Horatio
47}
48
49func Example_precompute() {
50	senderPublicKey, senderPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
51	if err != nil {
52		panic(err)
53	}
54
55	recipientPublicKey, recipientPrivateKey, err := box.GenerateKey(crypto_rand.Reader)
56	if err != nil {
57		panic(err)
58	}
59
60	// The shared key can be used to speed up processing when using the same
61	// pair of keys repeatedly.
62	sharedEncryptKey := new([32]byte)
63	box.Precompute(sharedEncryptKey, recipientPublicKey, senderPrivateKey)
64
65	// You must use a different nonce for each message you encrypt with the
66	// same key. Since the nonce here is 192 bits long, a random value
67	// provides a sufficiently small probability of repeats.
68	var nonce [24]byte
69	if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
70		panic(err)
71	}
72
73	msg := []byte("A fellow of infinite jest, of most excellent fancy")
74	// This encrypts msg and appends the result to the nonce.
75	encrypted := box.SealAfterPrecomputation(nonce[:], msg, &nonce, sharedEncryptKey)
76
77	// The shared key can be used to speed up processing when using the same
78	// pair of keys repeatedly.
79	var sharedDecryptKey [32]byte
80	box.Precompute(&sharedDecryptKey, senderPublicKey, recipientPrivateKey)
81
82	// The recipient can decrypt the message using the shared key. When you
83	// decrypt, you must use the same nonce you used to encrypt the message.
84	// One way to achieve this is to store the nonce alongside the encrypted
85	// message. Above, we stored the nonce in the first 24 bytes of the
86	// encrypted text.
87	var decryptNonce [24]byte
88	copy(decryptNonce[:], encrypted[:24])
89	decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey)
90	if !ok {
91		panic("decryption error")
92	}
93	fmt.Println(string(decrypted))
94	// Output: A fellow of infinite jest, of most excellent fancy
95}
96