| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package ssh |
| |
| import ( |
| "crypto/dsa" |
| "crypto/rsa" |
| "math/big" |
| ) |
| |
| // parsePubKey parses a public key according to RFC 4253, section 6.6. |
| func parsePubKey(in []byte) (out interface{}, rest []byte, ok bool) { |
| algo, in, ok := parseString(in) |
| if !ok { |
| return |
| } |
| |
| switch string(algo) { |
| case hostAlgoRSA: |
| return parseRSA(in) |
| case hostAlgoDSA: |
| return parseDSA(in) |
| case hostAlgoRSACertV01, hostAlgoDSACertV01: |
| return parseOpenSSHCertV01(in, string(algo)) |
| } |
| panic("ssh: unknown public key type") |
| } |
| |
| // parseRSA parses an RSA key according to RFC 4253, section 6.6. |
| func parseRSA(in []byte) (out *rsa.PublicKey, rest []byte, ok bool) { |
| key := new(rsa.PublicKey) |
| |
| bigE, in, ok := parseInt(in) |
| if !ok || bigE.BitLen() > 24 { |
| return |
| } |
| e := bigE.Int64() |
| if e < 3 || e&1 == 0 { |
| ok = false |
| return |
| } |
| key.E = int(e) |
| |
| if key.N, in, ok = parseInt(in); !ok { |
| return |
| } |
| |
| ok = true |
| return key, in, ok |
| } |
| |
| // parseDSA parses an DSA key according to RFC 4253, section 6.6. |
| func parseDSA(in []byte) (out *dsa.PublicKey, rest []byte, ok bool) { |
| key := new(dsa.PublicKey) |
| |
| if key.P, in, ok = parseInt(in); !ok { |
| return |
| } |
| |
| if key.Q, in, ok = parseInt(in); !ok { |
| return |
| } |
| |
| if key.G, in, ok = parseInt(in); !ok { |
| return |
| } |
| |
| if key.Y, in, ok = parseInt(in); !ok { |
| return |
| } |
| |
| ok = true |
| return key, in, ok |
| } |
| |
| // marshalPrivRSA serializes an RSA private key according to RFC 4253, section 6.6. |
| func marshalPrivRSA(priv *rsa.PrivateKey) []byte { |
| e := new(big.Int).SetInt64(int64(priv.E)) |
| length := stringLength(len(hostAlgoRSA)) |
| length += intLength(e) |
| length += intLength(priv.N) |
| |
| ret := make([]byte, length) |
| r := marshalString(ret, []byte(hostAlgoRSA)) |
| r = marshalInt(r, e) |
| r = marshalInt(r, priv.N) |
| |
| return ret |
| } |
| |
| // marshalPubRSA serializes an RSA public key according to RFC 4253, section 6.6. |
| func marshalPubRSA(key *rsa.PublicKey) []byte { |
| e := new(big.Int).SetInt64(int64(key.E)) |
| length := intLength(e) |
| length += intLength(key.N) |
| |
| ret := make([]byte, length) |
| r := marshalInt(ret, e) |
| r = marshalInt(r, key.N) |
| |
| return ret |
| } |
| |
| // marshalPubDSA serializes an DSA public key according to RFC 4253, section 6.6. |
| func marshalPubDSA(key *dsa.PublicKey) []byte { |
| length := intLength(key.P) |
| length += intLength(key.Q) |
| length += intLength(key.G) |
| length += intLength(key.Y) |
| |
| ret := make([]byte, length) |
| r := marshalInt(ret, key.P) |
| r = marshalInt(r, key.Q) |
| r = marshalInt(r, key.G) |
| marshalInt(r, key.Y) |
| |
| return ret |
| } |