Пример #1
0
// SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the
// backend as type t, without a pack. It returns the storage hash.
func (s *Repository) SaveJSONUnpacked(t backend.Type, item interface{}) (backend.ID, error) {
	// create file
	blob, err := s.be.Create()
	if err != nil {
		return nil, err
	}
	debug.Log("Repo.SaveJSONUnpacked", "create new file %p", blob)

	// hash
	hw := backend.NewHashingWriter(blob, sha256.New())

	// encrypt blob
	ewr := crypto.EncryptTo(s.key, hw)

	enc := json.NewEncoder(ewr)
	err = enc.Encode(item)
	if err != nil {
		return nil, fmt.Errorf("json.Encode: %v", err)
	}

	err = ewr.Close()
	if err != nil {
		return nil, err
	}

	// finalize blob in the backend
	sid := backend.ID(hw.Sum(nil))

	err = blob.Finalize(t, sid.String())
	if err != nil {
		return nil, err
	}

	return sid, nil
}
Пример #2
0
func TestHashingWriter(t *testing.T) {
	tests := []int{5, 23, 2<<18 + 23, 1 << 20}

	for _, size := range tests {
		data := make([]byte, size)
		_, err := io.ReadFull(rand.Reader, data)
		if err != nil {
			t.Fatalf("ReadFull: %v", err)
		}

		expectedHash := sha256.Sum256(data)

		wr := backend.NewHashingWriter(ioutil.Discard, sha256.New())

		n, err := io.Copy(wr, bytes.NewReader(data))
		OK(t, err)

		Assert(t, n == int64(size),
			"HashAppendWriter: invalid number of bytes written: got %d, expected %d",
			n, size)

		Assert(t, wr.Size() == size,
			"HashAppendWriter: invalid number of bytes returned: got %d, expected %d",
			wr.Size, size)

		resultingHash := wr.Sum(nil)
		Assert(t, bytes.Equal(expectedHash[:], resultingHash),
			"HashAppendWriter: hashes do not match: expected %02x, got %02x",
			expectedHash, resultingHash)
	}
}
Пример #3
0
// CreateEncryptedBlob returns a BlobWriter that encrypts and saves the data
// written to it in the backend. After Close() was called, ID() returns the
// backend.ID.
func (r *Repository) CreateEncryptedBlob(t backend.Type) (*BlobWriter, error) {
	blob, err := r.be.Create()
	if err != nil {
		return nil, err
	}

	// hash
	hw := backend.NewHashingWriter(blob, sha256.New())

	// encrypt blob
	ewr := crypto.EncryptTo(r.key, hw)

	return &BlobWriter{t: t, blob: blob, hw: hw, ewr: ewr}, nil
}
Пример #4
0
// SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the
// backend as type t, without a pack. It returns the storage hash.
func (r *Repository) SaveJSONUnpacked(t backend.Type, item interface{}) (backend.ID, error) {
	// create file
	blob, err := r.be.Create()
	if err != nil {
		return backend.ID{}, err
	}
	debug.Log("Repo.SaveJSONUnpacked", "create new blob %v", t)

	// hash
	hw := backend.NewHashingWriter(blob, sha256.New())

	// encrypt blob
	ewr := crypto.EncryptTo(r.key, hw)

	enc := json.NewEncoder(ewr)
	err = enc.Encode(item)
	if err != nil {
		return backend.ID{}, fmt.Errorf("json.Encode: %v", err)
	}

	err = ewr.Close()
	if err != nil {
		return backend.ID{}, err
	}

	// finalize blob in the backend
	hash := hw.Sum(nil)
	sid := backend.ID{}
	copy(sid[:], hash)

	err = blob.Finalize(t, sid.String())
	if err != nil {
		debug.Log("Repo.SaveJSONUnpacked", "error saving blob %v as %v: %v", t, sid, err)
		return backend.ID{}, err
	}

	debug.Log("Repo.SaveJSONUnpacked", "new blob %v saved as %v", t, sid)

	return sid, nil
}
Пример #5
0
// SaveIndex saves all new packs in the index in the backend, returned is the
// storage ID.
func (r *Repository) SaveIndex() (backend.ID, error) {
	debug.Log("Repo.SaveIndex", "Saving index")

	// create blob
	blob, err := r.be.Create()
	if err != nil {
		return backend.ID{}, err
	}

	debug.Log("Repo.SaveIndex", "create new pack %p", blob)

	// hash
	hw := backend.NewHashingWriter(blob, sha256.New())

	// encrypt blob
	ewr := crypto.EncryptTo(r.key, hw)

	err = r.idx.Encode(ewr)
	if err != nil {
		return backend.ID{}, err
	}

	err = ewr.Close()
	if err != nil {
		return backend.ID{}, err
	}

	// finalize blob in the backend
	sid := backend.ID{}
	copy(sid[:], hw.Sum(nil))

	err = blob.Finalize(backend.Index, sid.String())
	if err != nil {
		return backend.ID{}, err
	}

	debug.Log("Repo.SaveIndex", "Saved index as %v", sid.Str())

	return sid, nil
}
Пример #6
0
// AddKey adds a new key to an already existing repository.
func AddKey(s *Repository, password string, template *crypto.Key) (*Key, error) {
	// fill meta data about key
	newkey := &Key{
		Created: time.Now(),
		KDF:     "scrypt",
		N:       scryptN,
		R:       scryptR,
		P:       scryptP,
	}

	hn, err := os.Hostname()
	if err == nil {
		newkey.Hostname = hn
	}

	usr, err := user.Current()
	if err == nil {
		newkey.Username = usr.Username
	}

	// generate random salt
	newkey.Salt = make([]byte, scryptSaltsize)
	n, err := rand.Read(newkey.Salt)
	if n != scryptSaltsize || err != nil {
		panic("unable to read enough random bytes for salt")
	}

	// call KDF to derive user key
	newkey.user, err = crypto.KDF(newkey.N, newkey.R, newkey.P, newkey.Salt, password)
	if err != nil {
		return nil, err
	}

	if template == nil {
		// generate new random master keys
		newkey.master = crypto.NewRandomKey()
	} else {
		// copy master keys from old key
		newkey.master = template
	}

	// encrypt master keys (as json) with user key
	buf, err := json.Marshal(newkey.master)
	if err != nil {
		return nil, err
	}

	newkey.Data, err = crypto.Encrypt(newkey.user, nil, buf)

	// dump as json
	buf, err = json.Marshal(newkey)
	if err != nil {
		return nil, err
	}

	// store in repository and return
	blob, err := s.be.Create()
	if err != nil {
		return nil, err
	}

	plainhw := backend.NewHashingWriter(blob, sha256.New())

	_, err = plainhw.Write(buf)
	if err != nil {
		return nil, err
	}

	name := hex.EncodeToString(plainhw.Sum(nil))

	err = blob.Finalize(backend.Key, name)
	if err != nil {
		return nil, err
	}

	newkey.name = name

	return newkey, nil
}
Пример #7
0
// NewPacker returns a new Packer that can be used to pack blobs
// together.
func NewPacker(k *crypto.Key, w io.Writer) *Packer {
	return &Packer{k: k, wr: w, hw: backend.NewHashingWriter(w, sha256.New())}
}