First I want to say that your code is very well written and idiomatic for someone who is new to Go.

Here are a few suggestions:

- Prefer standard library tools for error handling rather than using an external library. `errors.Wrapf` can be replaced by `fmt.Errorf`.
- Call `file.Close` with defer, so that if writing to the file fails it will still get closed. The documentation for `file.Close` specifies that it will only return an error if the file is already closed, so you could consider just ignoring any error from `file.Close`.
- This is kind of subjective, but I think `downFile` should return the file name instead of an `*os.File` because the file is already closed, so any attempt to read or write it would fail.
- `SaveAsFile` has a lot of string arguments, and some of them are optional. If a caller calls `SaveAsFile(url, digest, "", "")`, it's not obvious that the empty strings are the username and password.

What you can use for this last point is the option pattern, I would define `SaveAsFile` as follows:

```
type opts struct {
    user string
    pass string
}

type SaveAsFileOption func(*opts)

func Auth(user, pass string) SaveAsFileOption {
    return func(o *opts) {
        o.user = user
        o.pass = pass
    }
}
func SaveAsFile(url, digest string, options SaveAsFileOption...) {
    var o opts
    for opt in options {
        opt(&o)
    }
    // Then you can access user and pass through o.user and o.pass.
}
```

Callers can call `SaveAsFile` either with `SaveAsFile(url, digest)`, or with `SaveAsFile(url, digest, Auth(user, pass))`. This also gives you the flexibility to define more options in the future.