diff --git a/cmd/fingerprintCmd.go b/cmd/fingerprintCmd.go new file mode 100644 index 0000000..9f097da --- /dev/null +++ b/cmd/fingerprintCmd.go @@ -0,0 +1,91 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/nhalstead/ssl-fingerprint/pkg" + "github.com/spf13/cobra" +) + +var ( + useMd5 bool + useSha1 bool + useSha256 bool + useSha512 bool + disableNth bool + separator string + + fingerprintCmd = &cobra.Command{ + Use: "host [fqdn or ip]", + Short: "Get ssl fingerprint of a URL", + Run: func(cmd *cobra.Command, args []string) { + host := args[0] + + // Default to show SHA 1 if no modes are selected + if useMd5 == false && useSha1 == false && useSha256 == false && useSha512 == false { + useSha1 = true + } + + // If the URL is HTTP, Do not process it as it does NOT have SSL Cert we are looking for. + if !strings.HasPrefix(host, "http://") { + crt, err := sslfingerprint.GetFingerprint(host, disableNth) + + if err != nil { + fmt.Println(err) + os.Exit(2) + return + } + + // Used to insert `,` (separator) between the hashes if multiple are selected. + alreadyExportedOnce := false + + // MD5 Hash Export + if useMd5 == true { + alreadyExportedOnce = true + fmt.Print(crt.MD5) // MD5 Hash + } + + // SHA1 Hash Export + if useSha1 == true { + if alreadyExportedOnce == true { + fmt.Printf("%+v", separator) + } + alreadyExportedOnce = true + fmt.Print(crt.SHA1) // SHA1 Hash + } + + // SHA256 Hash Export + if useSha256 == true { + if alreadyExportedOnce == true { + fmt.Printf("%+v", separator) + } + alreadyExportedOnce = true + fmt.Print(crt.SHA256) // SHA256 Hash + } + + // SHA512 Hash Export + if useSha512 == true { + if alreadyExportedOnce == true { + fmt.Printf("%+v", separator) + } + fmt.Print(crt.SHA512) // SHA512 Hash + } + fmt.Println() + } else { + os.Exit(2) + } + + }, + } +) + +func init() { + fingerprintCmd.Flags().BoolVarP(&useMd5, "md5", "m", false, "return md5 fingerprint") + fingerprintCmd.Flags().BoolVarP(&useSha1, "sha-1", "1", false, "return sha1 fingerprint") + fingerprintCmd.Flags().BoolVarP(&useSha256, "sha-256", "2", false, "return sha256 fingerprint") + fingerprintCmd.Flags().BoolVarP(&useSha512, "sha-512", "5", false, "return sha512 fingerprint") + fingerprintCmd.Flags().BoolVarP(&disableNth, "disable-nth", "d", false, "disable Nth separator") + fingerprintCmd.Flags().StringVarP(&separator, "separator", "s", ",", "separator between many hashes") +} diff --git a/cmd/matchCmd.go b/cmd/matchCmd.go new file mode 100644 index 0000000..215e023 --- /dev/null +++ b/cmd/matchCmd.go @@ -0,0 +1,60 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/nhalstead/ssl-fingerprint/pkg" + "github.com/spf13/cobra" +) + +var ( + matchCmd = &cobra.Command{ + Use: "match [fqdn or ip] [fingerprint]", + Short: "Get ssl fingerprint of a URL and check if it matches the given fqdn or ip", + Run: func(cmd *cobra.Command, args []string) { + domainURL := args[0] + fingerprint := args[1] + + crt, err := sslfingerprint.GetFingerprint(domainURL, false) + + if err != nil { + fmt.Println(err) + os.Exit(2) + return + } + + // Create a new slice with set a defined size of 12 (4 fingerprint types, 3 formats) + certFingerprints := make([]string, 4 * 3) + + certFingerprints = append(certFingerprints, crt.MD5) + certFingerprints = append(certFingerprints, crt.SHA1) + certFingerprints = append(certFingerprints, crt.SHA256) + certFingerprints = append(certFingerprints, crt.SHA512) + + for _, fingerprint := range certFingerprints { + certFingerprints = append(certFingerprints, strings.ReplaceAll(fingerprint, ":", " ")) + certFingerprints = append(certFingerprints, strings.ReplaceAll(fingerprint, ":", "")) + } + + if contains(certFingerprints, fingerprint) { + os.Exit(0) + } + + // Does not match given format. + os.Exit(1) + + }, + } +) + +// @link https://stackoverflow.com/a/10485970/5779200 +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..5fb19b8 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +var ( + rootCmd = &cobra.Command{ + Use: "sprint", + Long: "Get a certificate fingerprint from a FQDN or URL.", + } +) + +// Execute executes the root command. +func Execute() error { + return rootCmd.Execute() +} + +func init() { + rootCmd.AddCommand(fingerprintCmd) + rootCmd.AddCommand(matchCmd) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..3b25aed --- /dev/null +++ b/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "os" + + "github.com/nhalstead/ssl-fingerprint/cmd" +) + +func main() { + if err := cmd.Execute(); err != nil { + os.Exit(1) + } +} \ No newline at end of file