package main import ( "crypto/sha256" "errors" "fmt" "io" "os" "strconv" "time" ) var errNotFound = fmt.Errorf("Not found") type config struct { pepper []byte maxReads int } const defaultMaxReads = 2000 func NewConfig() (*config, error) { awlfilePepper := os.Getenv("AWLFILE_PEPPER") if awlfilePepper == "" { return nil, fmt.Errorf("Must provide a pepper") } awlfileMaxReadsStr := os.Getenv("AWLFILE_MAX_READS") maxReads := defaultMaxReads if maxReadsFromEnv, err := strconv.Atoi(awlfileMaxReadsStr); err == nil { maxReads = maxReadsFromEnv } return &config{ pepper: []byte(awlfilePepper), maxReads: maxReads, }, nil } func doHash(filePath string, pepper []byte, accessPolicy []byte) ([]byte, []byte, []byte, error) { file, err := os.Open(filePath) if errors.Is(err, os.ErrNotExist) { return nil, nil, nil, errNotFound } else if err != nil { return nil, nil, nil, err } defer file.Close() h := sha256.New() if _, err := io.Copy(h, file); err != nil { return nil, nil, nil, err } contentHash := h.Sum(nil) if _, err := h.Write(pepper); err != nil { return nil, nil, nil, err } pepperHash := h.Sum(nil) if _, err := h.Write(accessPolicy); err != nil { return nil, nil, nil, err } accessPolicyHash := h.Sum(nil) return contentHash, pepperHash, accessPolicyHash, nil } func main() { config, err := NewConfig() if err != nil { fmt.Println("err getting config", err.Error()) os.Exit(1) } // policy // filename args := os.Args if len(args) < 2 { fmt.Println("must pass file name") os.Exit(1) } if len(args) > 3 { fmt.Println("may only pass filename and optional access policy") os.Exit(1) } var accessPolicy []byte if len(args) == 3 && args[2] != "" { expirePolicyStr := args[2] var expireTime time.Time accessPolicy = []byte(expirePolicyStr) _, err = strconv.Atoi(expirePolicyStr) if err != nil { expireTime, err = time.Parse(time.RFC3339, expirePolicyStr) if err != nil { fmt.Println("bad access policy", err.Error()) os.Exit(1) } accessPolicy = []byte(expireTime.Format(time.RFC3339)) } } _, _, accessPolicyHash, err := doHash(args[1], config.pepper, accessPolicy) if err != nil { fmt.Println("err making hash", err.Error()) os.Exit(1) } fmt.Printf("%x\n", accessPolicyHash) }