key.go 9.6 KB

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