package ssh import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/binary" "encoding/pem" "fmt" "golang.org/x/crypto/ssh" ) func signerFromBlock(block *pem.Block) (ssh.Signer, error) { var key interface{} var err error switch block.Type { case "RSA PRIVATE KEY": key, err = x509.ParsePKCS1PrivateKey(block.Bytes) case "EC PRIVATE KEY": key, err = x509.ParseECPrivateKey(block.Bytes) case "DSA PRIVATE KEY": key, err = ssh.ParseDSAPrivateKey(block.Bytes) default: return nil, fmt.Errorf("unsupported key type %q", block.Type) } if err != nil { return nil, err } signer, err := ssh.NewSignerFromKey(key) if err != nil { return nil, err } return signer, nil } func decodePemBlocks(pemData []byte) []*pem.Block { var blocks []*pem.Block var block *pem.Block for { block, pemData = pem.Decode(pemData) if block == nil { return blocks } blocks = append(blocks, block) } } func generateSigner() (ssh.Signer, error) { key, err := rsa.GenerateKey(rand.Reader, 768) if err != nil { return nil, err } return ssh.NewSignerFromKey(key) } func parsePtyRequest(s []byte) (pty Pty, ok bool) { term, s, ok := parseString(s) if !ok { return } width32, s, ok := parseUint32(s) if width32 < 1 { ok = false } if !ok { return } height32, _, ok := parseUint32(s) if height32 < 1 { ok = false } if !ok { return } pty = Pty{ Term: term, Window: Window{ Width: int(width32), Height: int(height32), }, } return } func parseWinchRequest(s []byte) (win Window, ok bool) { width32, s, ok := parseUint32(s) if width32 < 1 { ok = false } if !ok { return } height32, _, ok := parseUint32(s) if height32 < 1 { ok = false } if !ok { return } win = Window{ Width: int(width32), Height: int(height32), } return } func parseString(in []byte) (out string, rest []byte, ok bool) { if len(in) < 4 { return } length := binary.BigEndian.Uint32(in) if uint32(len(in)) < 4+length { return } out = string(in[4 : 4+length]) rest = in[4+length:] ok = true return } func parseUint32(in []byte) (uint32, []byte, bool) { if len(in) < 4 { return 0, nil, false } return binary.BigEndian.Uint32(in), in[4:], true }