github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/rsa/example_test.go (about) 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 "encoding/hex" 9 "fmt" 10 "github.com/insolar/x-crypto" 11 "crypto/aes" 12 "crypto/cipher" 13 "github.com/insolar/x-crypto/rand" 14 "github.com/insolar/x-crypto/sha256" 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 }