56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
package vaultik
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"filippo.io/age"
|
|
"git.eeqj.de/sneak/vaultik/internal/blobgen"
|
|
)
|
|
|
|
// FetchAndDecryptBlobResult holds the result of fetching and decrypting a blob.
|
|
type FetchAndDecryptBlobResult struct {
|
|
Data []byte
|
|
}
|
|
|
|
// FetchAndDecryptBlob downloads a blob, decrypts it, and returns the plaintext data.
|
|
func (v *Vaultik) FetchAndDecryptBlob(ctx context.Context, blobHash string, expectedSize int64, identity age.Identity) (*FetchAndDecryptBlobResult, error) {
|
|
rc, _, err := v.FetchBlob(ctx, blobHash, expectedSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = rc.Close() }()
|
|
|
|
reader, err := blobgen.NewReader(rc, identity)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating blob reader: %w", err)
|
|
}
|
|
defer func() { _ = reader.Close() }()
|
|
|
|
data, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading blob data: %w", err)
|
|
}
|
|
|
|
return &FetchAndDecryptBlobResult{Data: data}, nil
|
|
}
|
|
|
|
// FetchBlob downloads a blob and returns a reader for the encrypted data.
|
|
func (v *Vaultik) FetchBlob(ctx context.Context, blobHash string, expectedSize int64) (io.ReadCloser, int64, error) {
|
|
blobPath := fmt.Sprintf("blobs/%s/%s/%s", blobHash[:2], blobHash[2:4], blobHash)
|
|
|
|
rc, err := v.Storage.Get(ctx, blobPath)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("downloading blob %s: %w", blobHash[:16], err)
|
|
}
|
|
|
|
info, err := v.Storage.Stat(ctx, blobPath)
|
|
if err != nil {
|
|
_ = rc.Close()
|
|
return nil, 0, fmt.Errorf("stat blob %s: %w", blobHash[:16], err)
|
|
}
|
|
|
|
return rc, info.Size, nil
|
|
}
|