SSHNativeParsePublicKey extracts the key type and length using the golang SSH library.
(keyLine string)
| 215 | |
| 216 | // SSHNativeParsePublicKey extracts the key type and length using the golang SSH library. |
| 217 | func SSHNativeParsePublicKey(keyLine string) (string, int, error) { |
| 218 | fields := strings.Fields(keyLine) |
| 219 | if len(fields) < 2 { |
| 220 | return "", 0, errors.Newf("not enough fields in public key line: %s", keyLine) |
| 221 | } |
| 222 | |
| 223 | raw, err := base64.StdEncoding.DecodeString(fields[1]) |
| 224 | if err != nil { |
| 225 | return "", 0, err |
| 226 | } |
| 227 | |
| 228 | pkey, err := ssh.ParsePublicKey(raw) |
| 229 | if err != nil { |
| 230 | if strings.Contains(err.Error(), "ssh: unknown key algorithm") { |
| 231 | return "", 0, ErrKeyUnableVerify{err.Error()} |
| 232 | } |
| 233 | return "", 0, errors.Newf("ParsePublicKey: %v", err) |
| 234 | } |
| 235 | |
| 236 | // The ssh library can parse the key, so next we find out what key exactly we have. |
| 237 | switch pkey.Type() { |
| 238 | case ssh.KeyAlgoDSA: |
| 239 | rawPub := struct { |
| 240 | Name string |
| 241 | P, Q, G, Y *big.Int |
| 242 | }{} |
| 243 | if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil { |
| 244 | return "", 0, err |
| 245 | } |
| 246 | // as per https://bugzilla.mindrot.org/show_bug.cgi?id=1647 we should never |
| 247 | // see dsa keys != 1024 bit, but as it seems to work, we will not check here |
| 248 | return "dsa", rawPub.P.BitLen(), nil // use P as per crypto/dsa/dsa.go (is L) |
| 249 | case ssh.KeyAlgoRSA: |
| 250 | rawPub := struct { |
| 251 | Name string |
| 252 | E *big.Int |
| 253 | N *big.Int |
| 254 | }{} |
| 255 | if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil { |
| 256 | return "", 0, err |
| 257 | } |
| 258 | return "rsa", rawPub.N.BitLen(), nil // use N as per crypto/rsa/rsa.go (is bits) |
| 259 | case ssh.KeyAlgoECDSA256: |
| 260 | return "ecdsa", 256, nil |
| 261 | case ssh.KeyAlgoECDSA384: |
| 262 | return "ecdsa", 384, nil |
| 263 | case ssh.KeyAlgoECDSA521: |
| 264 | return "ecdsa", 521, nil |
| 265 | case ssh.KeyAlgoED25519: |
| 266 | return "ed25519", 256, nil |
| 267 | } |
| 268 | return "", 0, errors.Newf("unsupported key length detection for type: %s", pkey.Type()) |
| 269 | } |
| 270 | |
| 271 | // CheckPublicKeyString checks if the given public key string is recognized by SSH. |
| 272 | // It returns the actual public key line on success. |