...

Source file src/crypto/rsa/example_test.go

Documentation: crypto/rsa

		 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.
		 4  
		 5  package rsa
		 6  
		 7  import (
		 8  	"crypto"
		 9  	"crypto/aes"
		10  	"crypto/cipher"
		11  	"crypto/rand"
		12  	"crypto/sha256"
		13  	"encoding/hex"
		14  	"fmt"
		15  	"io"
		16  	"os"
		17  )
		18  
		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
		22  // AES-GCM.
		23  //
		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.)
		29  //
		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
		40  	// operation.
		41  	rng := rand.Reader
		42  
		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
		45  	// well-formed.
		46  	key := make([]byte, 32)
		47  	if _, err := io.ReadFull(rng, key); err != nil {
		48  		panic("RNG failure")
		49  	}
		50  
		51  	rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
		52  
		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
		57  		// public key.)
		58  		fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err)
		59  		return
		60  	}
		61  
		62  	// Given the resulting key, a symmetric scheme can be used to decrypt a
		63  	// larger ciphertext.
		64  	block, err := aes.NewCipher(key)
		65  	if err != nil {
		66  		panic("aes.NewCipher failed: " + err.Error())
		67  	}
		68  
		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)
		73  	if err != nil {
		74  		panic("cipher.NewGCM failed: " + err.Error())
		75  	}
		76  	ciphertext, _ := hex.DecodeString("00112233445566")
		77  	plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil)
		78  	if err != 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)
		82  		return
		83  	}
		84  
		85  	fmt.Printf("Plaintext: %s\n", string(plaintext))
		86  }
		87  
		88  func ExampleSignPKCS1v15() {
		89  	// crypto/rand.Reader is a good source of entropy for blinding the RSA
		90  	// operation.
		91  	rng := rand.Reader
		92  
		93  	message := []byte("message to be signed")
		94  
		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
		99  	// of writing (2016).
	 100  	hashed := sha256.Sum256(message)
	 101  
	 102  	signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:])
	 103  	if err != nil {
	 104  		fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
	 105  		return
	 106  	}
	 107  
	 108  	fmt.Printf("Signature: %x\n", signature)
	 109  }
	 110  
	 111  func ExampleVerifyPKCS1v15() {
	 112  	message := []byte("message to be signed")
	 113  	signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")
	 114  
	 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)
	 121  
	 122  	err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature)
	 123  	if err != nil {
	 124  		fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
	 125  		return
	 126  	}
	 127  
	 128  	// signature is a valid signature of message from the public key.
	 129  }
	 130  
	 131  func ExampleEncryptOAEP() {
	 132  	secretMessage := []byte("send reinforcements, we're going to advance")
	 133  	label := []byte("orders")
	 134  
	 135  	// crypto/rand.Reader is a good source of entropy for randomizing the
	 136  	// encryption function.
	 137  	rng := rand.Reader
	 138  
	 139  	ciphertext, err := EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label)
	 140  	if err != nil {
	 141  		fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
	 142  		return
	 143  	}
	 144  
	 145  	// Since encryption is a randomized function, ciphertext will be
	 146  	// different each time.
	 147  	fmt.Printf("Ciphertext: %x\n", ciphertext)
	 148  }
	 149  
	 150  func ExampleDecryptOAEP() {
	 151  	ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
	 152  	label := []byte("orders")
	 153  
	 154  	// crypto/rand.Reader is a good source of entropy for blinding the RSA
	 155  	// operation.
	 156  	rng := rand.Reader
	 157  
	 158  	plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label)
	 159  	if err != nil {
	 160  		fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
	 161  		return
	 162  	}
	 163  
	 164  	fmt.Printf("Plaintext: %s\n", string(plaintext))
	 165  
	 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.
	 169  }
	 170  

View as plain text