%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/waritko/go/src/github.com/odeke-em/drive/src/dcrypto/
Upload File :
Create Path :
Current File : //home/waritko/go/src/github.com/odeke-em/drive/src/dcrypto/dcrypto.go

// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package dcrypto provides end to end encryption for drive.

package dcrypto

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"hash"
	"io"

	"github.com/odeke-em/drive/src/dcrypto/v1"
)

// Version is the version of the en/decryption library used.
type Version uint32

// decrypter is a function that creates a decrypter.
type decrypter func(io.Reader, []byte) (io.ReadCloser, error)

// encrypter is a function that creates a encrypter.
type encrypter func(io.Reader, []byte) (io.Reader, error)

// hasher is a function that returns the hash of a plaintext as if it were encrypted.
type hasher func(io.Reader, io.Reader, []byte, hash.Hash) ([]byte, error)

// These are the different versions of the en/decryption library.
const (
	V1 Version = iota
)

// PreferedVersion is the preferred version of encryption.
const PreferedVersion = V1

var encrypters map[Version]encrypter
var decrypters map[Version]decrypter
var hashers map[Version]hasher

// MaxHeaderSize is the maximum header size of all versions.
// This many bytes at the beginning of a file should be enough to compute
// a hash of a local file.
var MaxHeaderSize = v1.HeaderSize + 4

// Overhead is the overhead added by the preferred encryption library plus the version.
var Overhead = v1.Overhead + 4

func init() {
	decrypters = map[Version]decrypter{
		V1: v1.NewDecryptReader,
	}

	encrypters = map[Version]encrypter{
		V1: v1.NewEncryptReader,
	}
	hashers = map[Version]hasher{
		V1: v1.Hash,
	}
}

// NewEncrypter returns an encrypting reader using the PreferedVersion.
func NewEncrypter(r io.Reader, password []byte) (io.Reader, error) {
	v, err := writeVersion(PreferedVersion)
	if err != nil {
		return nil, err
	}
	encrypterFn, ok := encrypters[PreferedVersion]
	if !ok {
		return nil, fmt.Errorf("%v version could not be found", PreferedVersion)
	}
	encReader, err := encrypterFn(r, password)
	if err != nil {
		return nil, err
	}
	return io.MultiReader(bytes.NewReader(v), encReader), nil
}

// NewDecrypter returns a decrypting reader based on the version used to encrypt.
func NewDecrypter(r io.Reader, password []byte) (io.ReadCloser, error) {
	version, err := readVersion(r)
	if err != nil {
		return nil, err
	}
	decrypterFn, ok := decrypters[version]
	if !ok {
		return nil, fmt.Errorf("unknown decrypter for version(%d)", version)
	}
	return decrypterFn(r, password)
}

// Hash will hash of plaintext based on the header of the encrypted file and returns the hash Sum.
func Hash(r io.Reader, header io.Reader, password []byte, hashFunc func() hash.Hash) ([]byte, error) {
	h := hashFunc()
	version, err := readVersion(io.TeeReader(header, h))
	if err != nil {
		return nil, err
	}
	hasherFn, ok := hashers[version]
	if !ok {
		return nil, fmt.Errorf("unknown hasher for version(%d)", version)
	}
	return hasherFn(r, header, password, h)
}

// writeVersion converts a Version to a []byte.
func writeVersion(i Version) ([]byte, error) {
	buf := new(bytes.Buffer)
	if err := binary.Write(buf, binary.LittleEndian, i); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// readVersion reads and returns a Version from reader.
func readVersion(r io.Reader) (v Version, err error) {
	err = binary.Read(r, binary.LittleEndian, &v)
	return v, err
}

Zerion Mini Shell 1.0