1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 // RSA is able to encrypt only a very limited amount of data. In order
20 // to encrypt reasonable amounts of data a hybrid scheme is commonly
21 // used: RSA is used to encrypt a key for a symmetric primitive like
24 // Before encrypting, data is “padded” by embedding it in a known
25 // structure. This is done for a number of reasons, but the most
26 // obvious is to ensure that the value is large enough that the
27 // exponentiation is larger than the modulus. (Otherwise it could be
28 // decrypted with a square-root.)
30 // In these designs, when using PKCS#1 v1.5, it's vitally important to
31 // avoid disclosing whether the received RSA message was well-formed
32 // (that is, whether the result of decrypting is a correctly padded
33 // message) because this leaks secret information.
34 // DecryptPKCS1v15SessionKey is designed for this situation and copies
35 // the decrypted, symmetric key (if well-formed) in constant-time over
36 // a buffer that contains a random key. Thus, if the RSA result isn't
37 // well-formed, the implementation uses a random key in constant time.
38 func ExampleDecryptPKCS1v15SessionKey() {
39 // crypto/rand.Reader is a good source of entropy for blinding the RSA
43 // The hybrid scheme should use at least a 16-byte symmetric key. Here
44 // we read the random key that will be used if the RSA decryption isn't
46 key
:= make([]byte, 32)
47 if _
, err
:= io
.ReadFull(rng
, key
); err
!= nil {
51 rsaCiphertext
, _
:= hex
.DecodeString("aabbccddeeff")
53 if err
:= DecryptPKCS1v15SessionKey(rng
, rsaPrivateKey
, rsaCiphertext
, key
); err
!= nil {
54 // Any errors that result will be “public” – meaning that they
55 // can be determined without any secret information. (For
56 // instance, if the length of key is impossible given the RSA
58 fmt
.Fprintf(os
.Stderr
, "Error from RSA decryption: %s\n", err
)
62 // Given the resulting key, a symmetric scheme can be used to decrypt a
64 block
, err
:= aes
.NewCipher(key
)
66 panic("aes.NewCipher failed: " + err
.Error())
69 // Since the key is random, using a fixed nonce is acceptable as the
70 // (key, nonce) pair will still be unique, as required.
71 var zeroNonce
[12]byte
72 aead
, err
:= cipher
.NewGCM(block
)
74 panic("cipher.NewGCM failed: " + err
.Error())
76 ciphertext
, _
:= hex
.DecodeString("00112233445566")
77 plaintext
, err
:= aead
.Open(nil, zeroNonce
[:], ciphertext
, nil)
79 // The RSA ciphertext was badly formed; the decryption will
80 // fail here because the AES-GCM key will be incorrect.
81 fmt
.Fprintf(os
.Stderr
, "Error decrypting: %s\n", err
)
85 fmt
.Printf("Plaintext: %s\n", string(plaintext
))
88 func ExampleSignPKCS1v15() {
89 // crypto/rand.Reader is a good source of entropy for blinding the RSA
93 message
:= []byte("message to be signed")
95 // Only small messages can be signed directly; thus the hash of a
96 // message, rather than the message itself, is signed. This requires
97 // that the hash function be collision resistant. SHA-256 is the
98 // least-strong hash function that should be used for this at the time
100 hashed
:= sha256
.Sum256(message
)
102 signature
, err
:= SignPKCS1v15(rng
, rsaPrivateKey
, crypto
.SHA256
, hashed
[:])
104 fmt
.Fprintf(os
.Stderr
, "Error from signing: %s\n", err
)
108 fmt
.Printf("Signature: %x\n", signature
)
111 func ExampleVerifyPKCS1v15() {
112 message
:= []byte("message to be signed")
113 signature
, _
:= hex
.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")
115 // Only small messages can be signed directly; thus the hash of a
116 // message, rather than the message itself, is signed. This requires
117 // that the hash function be collision resistant. SHA-256 is the
118 // least-strong hash function that should be used for this at the time
119 // of writing (2016).
120 hashed
:= sha256
.Sum256(message
)
122 err
:= VerifyPKCS1v15(&rsaPrivateKey
.PublicKey
, crypto
.SHA256
, hashed
[:], signature
)
124 fmt
.Fprintf(os
.Stderr
, "Error from verification: %s\n", err
)
128 // signature is a valid signature of message from the public key.
131 func ExampleEncryptOAEP() {
132 secretMessage
:= []byte("send reinforcements, we're going to advance")
133 label
:= []byte("orders")
135 // crypto/rand.Reader is a good source of entropy for randomizing the
136 // encryption function.
139 ciphertext
, err
:= EncryptOAEP(sha256
.New(), rng
, &test2048Key
.PublicKey
, secretMessage
, label
)
141 fmt
.Fprintf(os
.Stderr
, "Error from encryption: %s\n", err
)
145 // Since encryption is a randomized function, ciphertext will be
146 // different each time.
147 fmt
.Printf("Ciphertext: %x\n", ciphertext
)
150 func ExampleDecryptOAEP() {
151 ciphertext
, _
:= hex
.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
152 label
:= []byte("orders")
154 // crypto/rand.Reader is a good source of entropy for blinding the RSA
158 plaintext
, err
:= DecryptOAEP(sha256
.New(), rng
, test2048Key
, ciphertext
, label
)
160 fmt
.Fprintf(os
.Stderr
, "Error from decryption: %s\n", err
)
164 fmt
.Printf("Plaintext: %s\n", string(plaintext
))
166 // Remember that encryption only provides confidentiality. The
167 // ciphertext should be signed before authenticity is assumed and, even
168 // then, consider that messages might be reordered.