example_test.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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. package rsa
  5. import (
  6. "crypto"
  7. "crypto/aes"
  8. "crypto/cipher"
  9. "crypto/rand"
  10. "crypto/sha256"
  11. "encoding/hex"
  12. "fmt"
  13. "io"
  14. "os"
  15. )
  16. // RSA is able to encrypt only a very limited amount of data. In order
  17. // to encrypt reasonable amounts of data a hybrid scheme is commonly
  18. // used: RSA is used to encrypt a key for a symmetric primitive like
  19. // AES-GCM.
  20. //
  21. // Before encrypting, data is “padded” by embedding it in a known
  22. // structure. This is done for a number of reasons, but the most
  23. // obvious is to ensure that the value is large enough that the
  24. // exponentiation is larger than the modulus. (Otherwise it could be
  25. // decrypted with a square-root.)
  26. //
  27. // In these designs, when using PKCS#1 v1.5, it's vitally important to
  28. // avoid disclosing whether the received RSA message was well-formed
  29. // (that is, whether the result of decrypting is a correctly padded
  30. // message) because this leaks secret information.
  31. // DecryptPKCS1v15SessionKey is designed for this situation and copies
  32. // the decrypted, symmetric key (if well-formed) in constant-time over
  33. // a buffer that contains a random key. Thus, if the RSA result isn't
  34. // well-formed, the implementation uses a random key in constant time.
  35. func ExampleDecryptPKCS1v15SessionKey() {
  36. // crypto/rand.Reader is a good source of entropy for blinding the RSA
  37. // operation.
  38. rng := rand.Reader
  39. // The hybrid scheme should use at least a 16-byte symmetric key. Here
  40. // we read the random key that will be used if the RSA decryption isn't
  41. // well-formed.
  42. key := make([]byte, 32)
  43. if _, err := io.ReadFull(rng, key); err != nil {
  44. panic("RNG failure")
  45. }
  46. rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
  47. if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil {
  48. // Any errors that result will be “public” – meaning that they
  49. // can be determined without any secret information. (For
  50. // instance, if the length of key is impossible given the RSA
  51. // public key.)
  52. fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err)
  53. return
  54. }
  55. // Given the resulting key, a symmetric scheme can be used to decrypt a
  56. // larger ciphertext.
  57. block, err := aes.NewCipher(key)
  58. if err != nil {
  59. panic("aes.NewCipher failed: " + err.Error())
  60. }
  61. // Since the key is random, using a fixed nonce is acceptable as the
  62. // (key, nonce) pair will still be unique, as required.
  63. var zeroNonce [12]byte
  64. aead, err := cipher.NewGCM(block)
  65. if err != nil {
  66. panic("cipher.NewGCM failed: " + err.Error())
  67. }
  68. ciphertext, _ := hex.DecodeString("00112233445566")
  69. plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil)
  70. if err != nil {
  71. // The RSA ciphertext was badly formed; the decryption will
  72. // fail here because the AES-GCM key will be incorrect.
  73. fmt.Fprintf(os.Stderr, "Error decrypting: %s\n", err)
  74. return
  75. }
  76. fmt.Printf("Plaintext: %s\n", string(plaintext))
  77. }
  78. func ExampleSignPKCS1v15() {
  79. // crypto/rand.Reader is a good source of entropy for blinding the RSA
  80. // operation.
  81. rng := rand.Reader
  82. message := []byte("message to be signed")
  83. // Only small messages can be signed directly; thus the hash of a
  84. // message, rather than the message itself, is signed. This requires
  85. // that the hash function be collision resistant. SHA-256 is the
  86. // least-strong hash function that should be used for this at the time
  87. // of writing (2016).
  88. hashed := sha256.Sum256(message)
  89. signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:])
  90. if err != nil {
  91. fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
  92. return
  93. }
  94. fmt.Printf("Signature: %x\n", signature)
  95. }
  96. func ExampleVerifyPKCS1v15() {
  97. message := []byte("message to be signed")
  98. signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")
  99. // Only small messages can be signed directly; thus the hash of a
  100. // message, rather than the message itself, is signed. This requires
  101. // that the hash function be collision resistant. SHA-256 is the
  102. // least-strong hash function that should be used for this at the time
  103. // of writing (2016).
  104. hashed := sha256.Sum256(message)
  105. err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature)
  106. if err != nil {
  107. fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
  108. return
  109. }
  110. // signature is a valid signature of message from the public key.
  111. }
  112. func ExampleEncryptOAEP() {
  113. secretMessage := []byte("send reinforcements, we're going to advance")
  114. label := []byte("orders")
  115. // crypto/rand.Reader is a good source of entropy for randomizing the
  116. // encryption function.
  117. rng := rand.Reader
  118. ciphertext, err := EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label)
  119. if err != nil {
  120. fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
  121. return
  122. }
  123. // Since encryption is a randomized function, ciphertext will be
  124. // different each time.
  125. fmt.Printf("Ciphertext: %x\n", ciphertext)
  126. }
  127. func ExampleDecryptOAEP() {
  128. ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
  129. label := []byte("orders")
  130. // crypto/rand.Reader is a good source of entropy for blinding the RSA
  131. // operation.
  132. rng := rand.Reader
  133. plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label)
  134. if err != nil {
  135. fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
  136. return
  137. }
  138. fmt.Printf("Plaintext: %s\n", string(plaintext))
  139. // Remember that encryption only provides confidentiality. The
  140. // ciphertext should be signed before authenticity is assumed and, even
  141. // then, consider that messages might be reordered.
  142. }