func BenchmarkEncryptDecryptReader(b *testing.B) { k := crypto.NewRandomKey() size := 8 << 20 // 8MiB rd := RandomReader(23, size) b.ResetTimer() b.SetBytes(int64(size)) buf := bytes.NewBuffer(nil) for i := 0; i < b.N; i++ { rd.Seek(0, 0) buf.Reset() wr := crypto.EncryptTo(k, buf) _, err := io.Copy(wr, rd) OK(b, err) OK(b, wr.Close()) r, err := crypto.DecryptFrom(k, buf) OK(b, err) _, err = io.Copy(ioutil.Discard, r) OK(b, err) } }
func TestDecryptStreamReader(t *testing.T) { k := crypto.NewRandomKey() tests := []int{5, 23, 2<<18 + 23, 1 << 20} if testLargeCrypto { tests = append(tests, 7<<20+123) } for _, size := range tests { data := make([]byte, size) _, err := io.ReadFull(RandomReader(42, size), data) OK(t, err) ciphertext := make([]byte, size+crypto.Extension) // encrypt with default function ciphertext, err = crypto.Encrypt(k, ciphertext, data) OK(t, err) Assert(t, len(ciphertext) == len(data)+crypto.Extension, "wrong number of bytes returned after encryption: expected %d, got %d", len(data)+crypto.Extension, len(ciphertext)) rd, err := crypto.DecryptFrom(k, bytes.NewReader(ciphertext)) OK(t, err) plaintext, err := ioutil.ReadAll(rd) OK(t, err) Assert(t, bytes.Equal(data, plaintext), "wrong plaintext after decryption: expected %02x, got %02x", data, plaintext) } }
// NewUnpacker returns a pointer to Unpacker which can be used to read // individual Blobs from a pack. func NewUnpacker(k *crypto.Key, rd io.ReadSeeker) (*Unpacker, error) { var err error ls := binary.Size(uint32(0)) // reset to the end to read header length _, err = rd.Seek(-int64(ls), 2) if err != nil { return nil, fmt.Errorf("seeking to read header length failed: %v", err) } var length uint32 err = binary.Read(rd, binary.LittleEndian, &length) if err != nil { return nil, fmt.Errorf("reading header length failed: %v", err) } // reset to the beginning of the header _, err = rd.Seek(-int64(ls)-int64(length), 2) if err != nil { return nil, fmt.Errorf("seeking to read header length failed: %v", err) } // read header hrd, err := crypto.DecryptFrom(k, io.LimitReader(rd, int64(length))) if err != nil { return nil, err } var entries []Blob pos := uint(0) for { e := headerEntry{} err = binary.Read(hrd, binary.LittleEndian, &e) if err == io.EOF { break } if err != nil { return nil, err } entries = append(entries, Blob{ Type: e.Type, Length: uint(e.Length), ID: e.ID, Offset: pos, }) pos += uint(e.Length) } p := &Unpacker{ rd: rd, k: k, Entries: entries, } return p, nil }
// LoadJSONPack calls LoadBlob() to load a blob from the backend, decrypt the // data and afterwards call json.Unmarshal on the item. func (r *Repository) LoadJSONPack(t pack.BlobType, id backend.ID, item interface{}) error { // lookup pack blob, err := r.idx.Lookup(id) if err != nil { return err } // load blob from pack rd, err := r.be.GetReader(backend.Data, blob.PackID.String(), blob.Offset, blob.Length) if err != nil { return err } defer rd.Close() // decrypt decryptRd, err := crypto.DecryptFrom(r.key, rd) defer decryptRd.Close() if err != nil { return err } // decode decoder := json.NewDecoder(decryptRd) err = decoder.Decode(item) if err != nil { return err } return nil }
// loadIndex loads the index id and merges it with the currently used index. func (s *Repository) loadIndex(id string) error { debug.Log("Repo.loadIndex", "Loading index %v", id[:8]) before := len(s.idx.pack) rd, err := s.be.Get(backend.Index, id) defer rd.Close() if err != nil { return err } // decrypt decryptRd, err := crypto.DecryptFrom(s.key, rd) defer decryptRd.Close() if err != nil { return err } idx, err := DecodeIndex(decryptRd) if err != nil { debug.Log("Repo.loadIndex", "error while decoding index %v: %v", id, err) return err } s.idx.Merge(idx) after := len(s.idx.pack) debug.Log("Repo.loadIndex", "Loaded index %v, added %v blobs", id[:8], after-before) return nil }
func newDecryptReadCloser(key *crypto.Key, rd io.ReadCloser) (io.ReadCloser, error) { dr, err := crypto.DecryptFrom(key, rd) if err != nil { return nil, err } return &decryptReadCloser{r: rd, dr: dr}, nil }
func BenchmarkDecryptReader(b *testing.B) { size := 8 << 20 // 8MiB buf := Random(23, size) k := crypto.NewRandomKey() ciphertext := make([]byte, len(buf)+crypto.Extension) _, err := crypto.Encrypt(k, ciphertext, buf) OK(b, err) rd := bytes.NewReader(ciphertext) b.ResetTimer() b.SetBytes(int64(size)) for i := 0; i < b.N; i++ { rd.Seek(0, 0) decRd, err := crypto.DecryptFrom(k, rd) OK(b, err) _, err = io.Copy(ioutil.Discard, decRd) OK(b, err) } }
// LoadJSONUnpacked decrypts the data and afterwards calls json.Unmarshal on // the item. func (r *Repository) LoadJSONUnpacked(t backend.Type, id backend.ID, item interface{}) error { // load blob from backend rd, err := r.be.Get(t, id.String()) if err != nil { return err } defer rd.Close() // decrypt decryptRd, err := crypto.DecryptFrom(r.key, rd) defer decryptRd.Close() if err != nil { return err } // decode decoder := json.NewDecoder(decryptRd) err = decoder.Decode(item) if err != nil { return err } return nil }
// LoadIndex loads the index id from backend and returns it. func LoadIndex(repo *Repository, id string) (*Index, error) { debug.Log("LoadIndex", "Loading index %v", id[:8]) rd, err := repo.be.Get(backend.Index, id) defer rd.Close() if err != nil { return nil, err } // decrypt decryptRd, err := crypto.DecryptFrom(repo.key, rd) defer decryptRd.Close() if err != nil { return nil, err } idx, err := DecodeIndex(decryptRd) if err != nil { debug.Log("LoadIndex", "error while decoding index %v: %v", id, err) return nil, err } return idx, nil }