key.go 10 KB

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