@@ -2,6 +2,8 @@ package sshutil
2
2
3
3
import (
4
4
"bytes"
5
+ "encoding/base64"
6
+ "encoding/binary"
5
7
"errors"
6
8
"fmt"
7
9
"io/fs"
@@ -94,7 +96,7 @@ func DefaultPubKeys(loadDotSSH bool) ([]PubKey, error) {
94
96
}
95
97
entry , err := readPublicKey (f )
96
98
if err == nil {
97
- if strings . ContainsRune ( entry . Content , '\n' ) || ! strings . HasPrefix (entry .Content , "ssh-" ) {
99
+ if ! detectValidPublicKey (entry .Content ) {
98
100
logrus .Warnf ("public key %q doesn't seem to be in ssh format" , entry .Filename )
99
101
} else {
100
102
res = append (res , entry )
@@ -261,3 +263,28 @@ func detectOpenSSHVersion() semver.Version {
261
263
}
262
264
return v
263
265
}
266
+
267
+ // detectValidPublicKey returns whether content represent a public key.
268
+ // OpenSSH public key format have the structure of '<algorithm> <key> <comment>'.
269
+ // By checking 'algorithm' with signature format identifier in 'key' part,
270
+ // this function may report false positive but provide better compatibility.
271
+ func detectValidPublicKey (content string ) bool {
272
+ if strings .ContainsRune (content , '\n' ) {
273
+ return false
274
+ }
275
+ var spaced = strings .SplitN (content , " " , 3 )
276
+ if len (spaced ) < 2 {
277
+ return false
278
+ }
279
+ var algo , base64Key = spaced [0 ], spaced [1 ]
280
+ var decodedKey , err = base64 .StdEncoding .DecodeString (base64Key )
281
+ if err != nil || len (decodedKey ) < 4 {
282
+ return false
283
+ }
284
+ var sigLength = binary .BigEndian .Uint32 (decodedKey )
285
+ if uint32 (len (decodedKey )) < sigLength {
286
+ return false
287
+ }
288
+ var sigFormat = string (decodedKey [4 : 4 + sigLength ])
289
+ return algo == sigFormat
290
+ }
0 commit comments