keys.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // Copyright 2012 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 ssh
  5. import (
  6. "bytes"
  7. "crypto/dsa"
  8. "crypto/ecdsa"
  9. "crypto/elliptic"
  10. "crypto/rsa"
  11. "encoding/base64"
  12. "math/big"
  13. )
  14. // Key types supported by OpenSSH 5.9
  15. const (
  16. keyAlgoRSA = "ssh-rsa"
  17. keyAlgoDSA = "ssh-dss"
  18. keyAlgoECDSA256 = "ecdsa-sha2-nistp256"
  19. keyAlgoECDSA384 = "ecdsa-sha2-nistp384"
  20. keyAlgoECDSA521 = "ecdsa-sha2-nistp521"
  21. )
  22. // parsePubKey parses a public key according to RFC 4253, section 6.6.
  23. func parsePubKey(in []byte) (out interface{}, rest []byte, ok bool) {
  24. algo, in, ok := parseString(in)
  25. if !ok {
  26. return
  27. }
  28. switch string(algo) {
  29. case keyAlgoRSA:
  30. return parseRSA(in)
  31. case keyAlgoDSA:
  32. return parseDSA(in)
  33. case keyAlgoECDSA256, keyAlgoECDSA384, keyAlgoECDSA521:
  34. return parseECDSA(in)
  35. case certAlgoRSAv01, certAlgoDSAv01, certAlgoECDSA256v01, certAlgoECDSA384v01, certAlgoECDSA521v01:
  36. return parseOpenSSHCertV01(in, string(algo))
  37. }
  38. panic("ssh: unknown public key type")
  39. }
  40. // parseRSA parses an RSA key according to RFC 4253, section 6.6.
  41. func parseRSA(in []byte) (out *rsa.PublicKey, rest []byte, ok bool) {
  42. key := new(rsa.PublicKey)
  43. bigE, in, ok := parseInt(in)
  44. if !ok || bigE.BitLen() > 24 {
  45. return
  46. }
  47. e := bigE.Int64()
  48. if e < 3 || e&1 == 0 {
  49. ok = false
  50. return
  51. }
  52. key.E = int(e)
  53. if key.N, in, ok = parseInt(in); !ok {
  54. return
  55. }
  56. ok = true
  57. return key, in, ok
  58. }
  59. // parseDSA parses an DSA key according to RFC 4253, section 6.6.
  60. func parseDSA(in []byte) (out *dsa.PublicKey, rest []byte, ok bool) {
  61. key := new(dsa.PublicKey)
  62. if key.P, in, ok = parseInt(in); !ok {
  63. return
  64. }
  65. if key.Q, in, ok = parseInt(in); !ok {
  66. return
  67. }
  68. if key.G, in, ok = parseInt(in); !ok {
  69. return
  70. }
  71. if key.Y, in, ok = parseInt(in); !ok {
  72. return
  73. }
  74. ok = true
  75. return key, in, ok
  76. }
  77. // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
  78. func parseECDSA(in []byte) (out *ecdsa.PublicKey, rest []byte, ok bool) {
  79. var identifier []byte
  80. if identifier, in, ok = parseString(in); !ok {
  81. return
  82. }
  83. key := new(ecdsa.PublicKey)
  84. switch string(identifier) {
  85. case "nistp256":
  86. key.Curve = elliptic.P256()
  87. case "nistp384":
  88. key.Curve = elliptic.P384()
  89. case "nistp521":
  90. key.Curve = elliptic.P521()
  91. default:
  92. ok = false
  93. return
  94. }
  95. var keyBytes []byte
  96. if keyBytes, in, ok = parseString(in); !ok {
  97. return
  98. }
  99. key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes)
  100. if key.X == nil || key.Y == nil {
  101. ok = false
  102. return
  103. }
  104. return key, in, ok
  105. }
  106. // marshalPrivRSA serializes an RSA private key according to RFC 4253, section 6.6.
  107. func marshalPrivRSA(priv *rsa.PrivateKey) []byte {
  108. e := new(big.Int).SetInt64(int64(priv.E))
  109. length := stringLength(len(keyAlgoRSA))
  110. length += intLength(e)
  111. length += intLength(priv.N)
  112. ret := make([]byte, length)
  113. r := marshalString(ret, []byte(keyAlgoRSA))
  114. r = marshalInt(r, e)
  115. r = marshalInt(r, priv.N)
  116. return ret
  117. }
  118. // marshalPubRSA serializes an RSA public key according to RFC 4253, section 6.6.
  119. func marshalPubRSA(key *rsa.PublicKey) []byte {
  120. e := new(big.Int).SetInt64(int64(key.E))
  121. length := intLength(e)
  122. length += intLength(key.N)
  123. ret := make([]byte, length)
  124. r := marshalInt(ret, e)
  125. r = marshalInt(r, key.N)
  126. return ret
  127. }
  128. // marshalPubDSA serializes an DSA public key according to RFC 4253, section 6.6.
  129. func marshalPubDSA(key *dsa.PublicKey) []byte {
  130. length := intLength(key.P)
  131. length += intLength(key.Q)
  132. length += intLength(key.G)
  133. length += intLength(key.Y)
  134. ret := make([]byte, length)
  135. r := marshalInt(ret, key.P)
  136. r = marshalInt(r, key.Q)
  137. r = marshalInt(r, key.G)
  138. r = marshalInt(r, key.Y)
  139. return ret
  140. }
  141. // marshalPubECDSA serializes an ECDSA public key according to RFC 5656, section 3.1.
  142. func marshalPubECDSA(key *ecdsa.PublicKey) []byte {
  143. var identifier []byte
  144. switch key.Params().BitSize {
  145. case 256:
  146. identifier = []byte("nistp256")
  147. case 384:
  148. identifier = []byte("nistp384")
  149. case 521:
  150. identifier = []byte("nistp521")
  151. default:
  152. panic("ssh: unsupported ecdsa key size")
  153. }
  154. keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
  155. length := stringLength(len(identifier))
  156. length += stringLength(len(keyBytes))
  157. ret := make([]byte, length)
  158. r := marshalString(ret, identifier)
  159. r = marshalString(r, keyBytes)
  160. return ret
  161. }
  162. // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
  163. // (see sshd(8) manual page) once the options and key type fields have been
  164. // removed.
  165. func parseAuthorizedKey(in []byte) (out interface{}, comment string, ok bool) {
  166. in = bytes.TrimSpace(in)
  167. i := bytes.IndexAny(in, " \t")
  168. if i == -1 {
  169. i = len(in)
  170. }
  171. base64Key := in[:i]
  172. key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
  173. n, err := base64.StdEncoding.Decode(key, base64Key)
  174. if err != nil {
  175. return
  176. }
  177. key = key[:n]
  178. out, _, ok = parsePubKey(key)
  179. if !ok {
  180. return nil, "", false
  181. }
  182. comment = string(bytes.TrimSpace(in[i:]))
  183. return
  184. }
  185. // ParseAuthorizedKeys parses a public key from an authorized_keys
  186. // file used in OpenSSH according to the sshd(8) manual page.
  187. func ParseAuthorizedKey(in []byte) (out interface{}, comment string, options []string, rest []byte, ok bool) {
  188. for len(in) > 0 {
  189. end := bytes.IndexByte(in, '\n')
  190. if end != -1 {
  191. rest = in[end+1:]
  192. in = in[:end]
  193. } else {
  194. rest = nil
  195. }
  196. end = bytes.IndexByte(in, '\r')
  197. if end != -1 {
  198. in = in[:end]
  199. }
  200. in = bytes.TrimSpace(in)
  201. if len(in) == 0 || in[0] == '#' {
  202. in = rest
  203. continue
  204. }
  205. i := bytes.IndexAny(in, " \t")
  206. if i == -1 {
  207. in = rest
  208. continue
  209. }
  210. field := string(in[:i])
  211. switch field {
  212. case keyAlgoRSA, keyAlgoDSA:
  213. out, comment, ok = parseAuthorizedKey(in[i:])
  214. if ok {
  215. return
  216. }
  217. case keyAlgoECDSA256, keyAlgoECDSA384, keyAlgoECDSA521:
  218. // We don't support these keys.
  219. in = rest
  220. continue
  221. case certAlgoRSAv01, certAlgoDSAv01,
  222. certAlgoECDSA256v01, certAlgoECDSA384v01, certAlgoECDSA521v01:
  223. // We don't support these certificates.
  224. in = rest
  225. continue
  226. }
  227. // No key type recognised. Maybe there's an options field at
  228. // the beginning.
  229. var b byte
  230. inQuote := false
  231. var candidateOptions []string
  232. optionStart := 0
  233. for i, b = range in {
  234. isEnd := !inQuote && (b == ' ' || b == '\t')
  235. if (b == ',' && !inQuote) || isEnd {
  236. if i-optionStart > 0 {
  237. candidateOptions = append(candidateOptions, string(in[optionStart:i]))
  238. }
  239. optionStart = i + 1
  240. }
  241. if isEnd {
  242. break
  243. }
  244. if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
  245. inQuote = !inQuote
  246. }
  247. }
  248. for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
  249. i++
  250. }
  251. if i == len(in) {
  252. // Invalid line: unmatched quote
  253. in = rest
  254. continue
  255. }
  256. in = in[i:]
  257. i = bytes.IndexAny(in, " \t")
  258. if i == -1 {
  259. in = rest
  260. continue
  261. }
  262. field = string(in[:i])
  263. switch field {
  264. case keyAlgoRSA, keyAlgoDSA:
  265. out, comment, ok = parseAuthorizedKey(in[i:])
  266. if ok {
  267. options = candidateOptions
  268. return
  269. }
  270. }
  271. in = rest
  272. continue
  273. }
  274. return
  275. }
  276. // ParsePublicKey parses an SSH public key formatted for use in
  277. // the SSH wire protocol.
  278. func ParsePublicKey(in []byte) (out interface{}, rest []byte, ok bool) {
  279. return parsePubKey(in)
  280. }
  281. // MarshalAuthorizedKey returns a byte stream suitable for inclusion
  282. // in an OpenSSH authorized_keys file following the format specified
  283. // in the sshd(8) manual page.
  284. func MarshalAuthorizedKey(key interface{}) []byte {
  285. b := &bytes.Buffer{}
  286. switch keyType := key.(type) {
  287. case *rsa.PublicKey:
  288. b.WriteString(keyAlgoRSA)
  289. case *dsa.PublicKey:
  290. b.WriteString(keyAlgoDSA)
  291. case *ecdsa.PublicKey:
  292. switch keyType.Params().BitSize {
  293. case 256:
  294. b.WriteString(keyAlgoECDSA256)
  295. case 384:
  296. b.WriteString(keyAlgoECDSA384)
  297. case 521:
  298. b.WriteString(keyAlgoECDSA521)
  299. default:
  300. panic("unexpected key type")
  301. }
  302. case *OpenSSHCertV01:
  303. switch keyType.Key.(type) {
  304. case *rsa.PublicKey:
  305. b.WriteString(certAlgoRSAv01)
  306. case *dsa.PublicKey:
  307. b.WriteString(certAlgoDSAv01)
  308. case *ecdsa.PublicKey:
  309. switch keyType.Key.(*ecdsa.PublicKey).Params().BitSize {
  310. case 256:
  311. b.WriteString(certAlgoECDSA256v01)
  312. case 384:
  313. b.WriteString(certAlgoECDSA384v01)
  314. case 521:
  315. b.WriteString(certAlgoECDSA521v01)
  316. default:
  317. panic("unexpected key type")
  318. }
  319. default:
  320. panic("unexpected key type")
  321. }
  322. default:
  323. panic("unexpected key type")
  324. }
  325. b.WriteByte(' ')
  326. e := base64.NewEncoder(base64.StdEncoding, b)
  327. e.Write(serializePublickey(key))
  328. e.Close()
  329. b.WriteByte('\n')
  330. return b.Bytes()
  331. }
  332. // MarshalPublicKey serializes a *rsa.PublicKey, *dsa.PublicKey or
  333. // *OpenSSHCertV01 for use in the SSH wire protocol. It can be used for
  334. // comparison with the pubkey argument of ServerConfig's PublicKeyCallback as
  335. // well as for generating an authorized_keys or host_keys file.
  336. func MarshalPublicKey(key interface{}) []byte {
  337. return serializePublickey(key)
  338. }