key.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. Copyright 2018 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Package keyutil contains utilities for managing public/private key pairs.
  14. package keyutil
  15. import (
  16. "crypto"
  17. "crypto/ecdsa"
  18. "crypto/elliptic"
  19. cryptorand "crypto/rand"
  20. "crypto/rsa"
  21. "crypto/x509"
  22. "encoding/pem"
  23. "fmt"
  24. "io/ioutil"
  25. "os"
  26. "path/filepath"
  27. )
  28. const (
  29. // ECPrivateKeyBlockType is a possible value for pem.Block.Type.
  30. ECPrivateKeyBlockType = "EC PRIVATE KEY"
  31. // RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
  32. RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
  33. // PrivateKeyBlockType is a possible value for pem.Block.Type.
  34. PrivateKeyBlockType = "PRIVATE KEY"
  35. // PublicKeyBlockType is a possible value for pem.Block.Type.
  36. PublicKeyBlockType = "PUBLIC KEY"
  37. )
  38. // MakeEllipticPrivateKeyPEM creates an ECDSA private key
  39. func MakeEllipticPrivateKeyPEM() ([]byte, error) {
  40. privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
  41. if err != nil {
  42. return nil, err
  43. }
  44. derBytes, err := x509.MarshalECPrivateKey(privateKey)
  45. if err != nil {
  46. return nil, err
  47. }
  48. privateKeyPemBlock := &pem.Block{
  49. Type: ECPrivateKeyBlockType,
  50. Bytes: derBytes,
  51. }
  52. return pem.EncodeToMemory(privateKeyPemBlock), nil
  53. }
  54. // WriteKey writes the pem-encoded key data to keyPath.
  55. // The key file will be created with file mode 0600.
  56. // If the key file already exists, it will be overwritten.
  57. // The parent directory of the keyPath will be created as needed with file mode 0755.
  58. func WriteKey(keyPath string, data []byte) error {
  59. if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
  60. return err
  61. }
  62. return ioutil.WriteFile(keyPath, data, os.FileMode(0600))
  63. }
  64. // LoadOrGenerateKeyFile looks for a key in the file at the given path. If it
  65. // can't find one, it will generate a new key and store it there.
  66. func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) {
  67. loadedData, err := ioutil.ReadFile(keyPath)
  68. // Call verifyKeyData to ensure the file wasn't empty/corrupt.
  69. if err == nil && verifyKeyData(loadedData) {
  70. return loadedData, false, err
  71. }
  72. if !os.IsNotExist(err) {
  73. return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err)
  74. }
  75. generatedData, err := MakeEllipticPrivateKeyPEM()
  76. if err != nil {
  77. return nil, false, fmt.Errorf("error generating key: %v", err)
  78. }
  79. if err := WriteKey(keyPath, generatedData); err != nil {
  80. return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err)
  81. }
  82. return generatedData, true, nil
  83. }
  84. // MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to
  85. // a PEM encoded block or returns an error.
  86. func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) {
  87. switch t := privateKey.(type) {
  88. case *ecdsa.PrivateKey:
  89. derBytes, err := x509.MarshalECPrivateKey(t)
  90. if err != nil {
  91. return nil, err
  92. }
  93. block := &pem.Block{
  94. Type: ECPrivateKeyBlockType,
  95. Bytes: derBytes,
  96. }
  97. return pem.EncodeToMemory(block), nil
  98. case *rsa.PrivateKey:
  99. block := &pem.Block{
  100. Type: RSAPrivateKeyBlockType,
  101. Bytes: x509.MarshalPKCS1PrivateKey(t),
  102. }
  103. return pem.EncodeToMemory(block), nil
  104. default:
  105. return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey)
  106. }
  107. }
  108. // PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file.
  109. // Returns an error if the file could not be read or if the private key could not be parsed.
  110. func PrivateKeyFromFile(file string) (interface{}, error) {
  111. data, err := ioutil.ReadFile(file)
  112. if err != nil {
  113. return nil, err
  114. }
  115. key, err := ParsePrivateKeyPEM(data)
  116. if err != nil {
  117. return nil, fmt.Errorf("error reading private key file %s: %v", file, err)
  118. }
  119. return key, nil
  120. }
  121. // PublicKeysFromFile returns the public keys in rsa.PublicKey or ecdsa.PublicKey format from a given PEM-encoded file.
  122. // Reads public keys from both public and private key files.
  123. func PublicKeysFromFile(file string) ([]interface{}, error) {
  124. data, err := ioutil.ReadFile(file)
  125. if err != nil {
  126. return nil, err
  127. }
  128. keys, err := ParsePublicKeysPEM(data)
  129. if err != nil {
  130. return nil, fmt.Errorf("error reading public key file %s: %v", file, err)
  131. }
  132. return keys, nil
  133. }
  134. // verifyKeyData returns true if the provided data appears to be a valid private key.
  135. func verifyKeyData(data []byte) bool {
  136. if len(data) == 0 {
  137. return false
  138. }
  139. _, err := ParsePrivateKeyPEM(data)
  140. return err == nil
  141. }
  142. // ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data.
  143. // Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY"
  144. func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) {
  145. var privateKeyPemBlock *pem.Block
  146. for {
  147. privateKeyPemBlock, keyData = pem.Decode(keyData)
  148. if privateKeyPemBlock == nil {
  149. break
  150. }
  151. switch privateKeyPemBlock.Type {
  152. case ECPrivateKeyBlockType:
  153. // ECDSA Private Key in ASN.1 format
  154. if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil {
  155. return key, nil
  156. }
  157. case RSAPrivateKeyBlockType:
  158. // RSA Private Key in PKCS#1 format
  159. if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil {
  160. return key, nil
  161. }
  162. case PrivateKeyBlockType:
  163. // RSA or ECDSA Private Key in unencrypted PKCS#8 format
  164. if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil {
  165. return key, nil
  166. }
  167. }
  168. // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks
  169. // originally, only the first PEM block was parsed and expected to be a key block
  170. }
  171. // we read all the PEM blocks and didn't recognize one
  172. return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key")
  173. }
  174. // ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array.
  175. // Reads public keys from both public and private key files.
  176. func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) {
  177. var block *pem.Block
  178. keys := []interface{}{}
  179. for {
  180. // read the next block
  181. block, keyData = pem.Decode(keyData)
  182. if block == nil {
  183. break
  184. }
  185. // test block against parsing functions
  186. if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil {
  187. keys = append(keys, &privateKey.PublicKey)
  188. continue
  189. }
  190. if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil {
  191. keys = append(keys, publicKey)
  192. continue
  193. }
  194. if privateKey, err := parseECPrivateKey(block.Bytes); err == nil {
  195. keys = append(keys, &privateKey.PublicKey)
  196. continue
  197. }
  198. if publicKey, err := parseECPublicKey(block.Bytes); err == nil {
  199. keys = append(keys, publicKey)
  200. continue
  201. }
  202. // tolerate non-key PEM blocks for backwards compatibility
  203. // originally, only the first PEM block was parsed and expected to be a key block
  204. }
  205. if len(keys) == 0 {
  206. return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys")
  207. }
  208. return keys, nil
  209. }
  210. // parseRSAPublicKey parses a single RSA public key from the provided data
  211. func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) {
  212. var err error
  213. // Parse the key
  214. var parsedKey interface{}
  215. if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
  216. if cert, err := x509.ParseCertificate(data); err == nil {
  217. parsedKey = cert.PublicKey
  218. } else {
  219. return nil, err
  220. }
  221. }
  222. // Test if parsed key is an RSA Public Key
  223. var pubKey *rsa.PublicKey
  224. var ok bool
  225. if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok {
  226. return nil, fmt.Errorf("data doesn't contain valid RSA Public Key")
  227. }
  228. return pubKey, nil
  229. }
  230. // parseRSAPrivateKey parses a single RSA private key from the provided data
  231. func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) {
  232. var err error
  233. // Parse the key
  234. var parsedKey interface{}
  235. if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil {
  236. if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil {
  237. return nil, err
  238. }
  239. }
  240. // Test if parsed key is an RSA Private Key
  241. var privKey *rsa.PrivateKey
  242. var ok bool
  243. if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok {
  244. return nil, fmt.Errorf("data doesn't contain valid RSA Private Key")
  245. }
  246. return privKey, nil
  247. }
  248. // parseECPublicKey parses a single ECDSA public key from the provided data
  249. func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) {
  250. var err error
  251. // Parse the key
  252. var parsedKey interface{}
  253. if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
  254. if cert, err := x509.ParseCertificate(data); err == nil {
  255. parsedKey = cert.PublicKey
  256. } else {
  257. return nil, err
  258. }
  259. }
  260. // Test if parsed key is an ECDSA Public Key
  261. var pubKey *ecdsa.PublicKey
  262. var ok bool
  263. if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok {
  264. return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key")
  265. }
  266. return pubKey, nil
  267. }
  268. // parseECPrivateKey parses a single ECDSA private key from the provided data
  269. func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
  270. var err error
  271. // Parse the key
  272. var parsedKey interface{}
  273. if parsedKey, err = x509.ParseECPrivateKey(data); err != nil {
  274. return nil, err
  275. }
  276. // Test if parsed key is an ECDSA Private Key
  277. var privKey *ecdsa.PrivateKey
  278. var ok bool
  279. if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
  280. return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key")
  281. }
  282. return privKey, nil
  283. }