github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/exp/validate/validate.go (about) 1 // Copyright 2016-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This program validates a file by verifying a checksum and a signature file. 6 // 7 // Synopsis: 8 // validate [OPTIONS...] FILE PUBLIC_KEY_FILE 9 // 10 // Description: 11 // Return code: 0-OK, 1-Any error, 2-Bad signature, 3-Bad checksum 12 // 13 // Options: 14 // -a: signature is ASCII armored 15 // -i FILE: checksum file 16 // -alg FILE: algorithms to check 17 // -v: verbose 18 package main 19 20 import ( 21 "crypto" 22 "flag" 23 "fmt" 24 "io/ioutil" 25 "log" 26 "os" 27 "strings" 28 29 _ "crypto/md5" 30 _ "crypto/sha1" 31 _ "crypto/sha256" 32 _ "crypto/sha512" 33 34 _ "golang.org/x/crypto/md4" 35 _ "golang.org/x/crypto/openpgp" 36 _ "golang.org/x/crypto/ripemd160" 37 _ "golang.org/x/crypto/sha3" 38 ) 39 40 var ( 41 algs = map[string]crypto.Hash{ 42 "MD4": crypto.MD4, 43 "MD5": crypto.MD5, 44 "SHA1": crypto.SHA1, 45 "SHA224": crypto.SHA224, 46 "SHA256": crypto.SHA256, 47 "SHA384": crypto.SHA384, 48 "SHA512": crypto.SHA512, 49 "RIPEMD160": crypto.RIPEMD160, 50 "SHA3_224": crypto.SHA3_224, 51 "SHA3_256": crypto.SHA3_256, 52 "SHA3_384": crypto.SHA3_384, 53 "SHA3_512": crypto.SHA3_512, 54 } 55 56 armored = flag.Bool("a", false, "signature is ASCII armored") 57 sumfile = flag.String("i", "", "checksum file") 58 alg = flag.String("alg", "", "algorithms to check") 59 verbose = flag.Bool("v", false, "verbose") 60 debug = func(string, ...interface{}) {} 61 try, tried []string 62 ) 63 64 func init() { 65 for v := range algs { 66 try = append(try, v) 67 } 68 } 69 70 func one(n string, b []byte, sig string) bool { 71 if !algs[n].Available() { 72 log.Printf("Hash %v did not get linked in", n) 73 return false 74 } 75 debug("Check alg %v", n) 76 checker := algs[n].New() 77 checker.Write(b) 78 r := checker.Sum([]byte{}) 79 debug("sum is %d bytes %v\n", len(r), r) 80 tried = append(tried, n) 81 82 // There has to be a better way. 83 sumText := "" 84 for _, v := range r { 85 sumText += fmt.Sprintf("%02x", v) 86 } 87 debug("Compare to %v", sumText) 88 if sumText == sig { 89 return true 90 } 91 return false 92 } 93 94 func sign(n string, k crypto.PrivateKey, b []byte, sig string) bool { 95 if !algs[n].Available() { 96 log.Printf("Hash %v did not get linked in", n) 97 return false 98 } 99 debug("Check alg %v", n) 100 b, err := k.(crypto.Signer).Sign(nil, b, algs[n]) 101 log.Printf("For %v we get %v %v", n, b, err) 102 return false 103 } 104 105 func main() { 106 flag.Parse() 107 if flag.NArg() < 2 { 108 log.Fatalf("Need at least a file to be validated and one public key") 109 } 110 111 if *verbose { 112 debug = log.Printf 113 } 114 115 v, f := flag.Args()[0], flag.Args()[1] 116 117 sigData, err := ioutil.ReadFile(v) 118 if err != nil { 119 log.Fatalf("%v", err) 120 } 121 122 if *alg != "" { 123 try = []string{} 124 for _, v := range strings.Split(*alg, ",") { 125 try = append(try, v) 126 } 127 } 128 129 log.Printf("Try %v", try) 130 131 sig := strings.Split(string(sigData), " ") 132 133 debug("Signature is %v len %v", sig[0], len(sig[0])) 134 135 b, err := ioutil.ReadFile(f) 136 if err != nil { 137 log.Fatalf("%s: %v", f, err) 138 } 139 140 if *sumfile != "" { 141 sum, err := ioutil.ReadFile(*sumfile) 142 if err != nil { 143 log.Fatalf("Can't read sumfile: %v", *sumfile) 144 } 145 for i := range try { 146 if sign(try[i], crypto.PrivateKey(sum), b, sig[0]) { 147 fmt.Printf("%v\n", try[i]) 148 os.Exit(0) 149 } 150 debug("not ok") 151 } 152 153 } else { 154 for i := range try { 155 debug("Check %v", try[i]) 156 if one(try[i], b, sig[0]) { 157 fmt.Printf("%v\n", try[i]) 158 os.Exit(0) 159 } 160 // Sometimes it's not a file in the standard format, but some binary thing. 161 // Check that too. 162 if one(try[i], b, string(sigData)) { 163 fmt.Printf("%v\n", try[i]) 164 os.Exit(0) 165 } 166 debug("not ok") 167 } 168 } 169 log.Fatalf("No matches found for %v", tried) 170 }