1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
package sshutil
import (
"fmt"
"time"
"golang.org/x/crypto/ssh"
)
// using the same layout than ssh-keygen
const certificateInspectLayout = "2006-01-02T15:04:05"
// CertificateInspect contains details of an ssh.Certificate in human readable
// format.
type CertificateInspect struct {
Type string
KeyName string
KeyID string
KeyAlgo string
KeyFingerprint string
SigningKeyAlgo string
SigningKeyFingerprint string
Serial uint64
ValidAfter time.Time
ValidBefore time.Time
Principals []string
CriticalOptions map[string]string
Extensions map[string]string
}
// InspectCertificate returns a CertificateInspect with the properties of the
// given ssh.Certificate.
func InspectCertificate(cert *ssh.Certificate) (*CertificateInspect, error) {
var certType string
var validAfter, validBefore time.Time
switch cert.CertType {
case ssh.HostCert:
certType = "host"
case ssh.UserCert:
certType = "user"
default:
certType = "unknown"
}
algo, sum, err := inspectPublicKey(cert.Key)
if err != nil {
return nil, err
}
sigAlgo, sigSum, err := inspectPublicKey(cert.SignatureKey)
if err != nil {
return nil, err
}
validAfter = time.Unix(int64(cert.ValidAfter), 0)
if cert.ValidBefore != ssh.CertTimeInfinity {
validBefore = time.Unix(int64(cert.ValidBefore), 0)
}
return &CertificateInspect{
Type: certType,
KeyName: cert.Type(),
KeyID: cert.KeyId,
KeyAlgo: algo,
KeyFingerprint: sum,
SigningKeyAlgo: sigAlgo,
SigningKeyFingerprint: sigSum,
Serial: cert.Serial,
ValidAfter: validAfter,
ValidBefore: validBefore,
Principals: cert.ValidPrincipals,
CriticalOptions: cert.CriticalOptions,
Extensions: cert.Extensions,
}, nil
}
// Validity returns a human version of the validity of the certificate. It
// returns the dates using the local time zone to behave as ssh-keygen.
func (c *CertificateInspect) Validity() string {
if c.ValidBefore.IsZero() {
return "forever"
}
return fmt.Sprintf("from %s to %s",
c.ValidAfter.Local().Format(certificateInspectLayout),
c.ValidBefore.Local().Format(certificateInspectLayout),
)
}
func inspectPublicKey(key ssh.PublicKey) (string, string, error) {
fp := ssh.FingerprintSHA256(key)
typ, _, err := publicKeyTypeAndSize(key)
if err != nil {
return "", "", err
}
return typ, fp, nil
}
|