Example #1
0
func newEncReader(r io.Reader, secrets *Secrets, length int) (reader *encReader, err error) {
	buf := make([]byte, 48)
	n, err := r.Read(buf[:1])
	if n != 1 {
		return nil, fmt.Errorf("Error decoding chunk")
	}
	if err != nil {
		return nil, err
	}
	version := buf[0]
	if version != 0 {
		return nil, fmt.Errorf("Unsupported chunk version %d", version)
	}
	n, err = r.Read(buf)
	if n != 48 {
		return nil, fmt.Errorf("Error decoding chunk")
	}
	if err != nil {
		return nil, err
	}
	nonce := make([]byte, 48)
	copy(nonce, buf)
	digester := hmac.New(sha512.New384, secrets.chunkMaster)
	digester.Write([]byte("\000chunk encryption\000"))
	digester.Write(nonce)
	digester.Write([]byte{0x01, 0x80})
	derivedKey := digester.Sum(nil)
	key := derivedKey[0:32]
	iv := derivedKey[32:48]
	aesCypher, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	cypher := cipher.NewCTR(aesCypher, iv)
	authHMAC := hmac.New(sha512.New384, secrets.chunkAuthentication)
	authHMAC.Write([]byte{0})
	authHMAC.Write(nonce)
	authHMAC.Write(key)
	authHMAC.Write(iv)
	cypherStream := cipher.StreamReader{S: cypher, R: io.TeeReader(r, authHMAC)}
	n, err = cypherStream.Read(buf[0:1])
	if n != 1 {
		return nil, fmt.Errorf("Error decoding chunk")
	}
	if err != nil {
		return nil, err
	}
	//compressed_p := buf[0] != 0
	return &encReader{source: r, reader: cypherStream, authHMAC: authHMAC, length: length - 48, numRead: 50}, nil
}
Example #2
0
func ReadSecrets(backend Backend) (secrets *Secrets, err error) {
	passphrase := termios.Password("Enter passphrase: ")

	encSecrets, err := backend.ReadSecrets()
	if err != nil {
		return nil, err
	}
	file := bytes.NewBuffer(encSecrets)
	version := make([]byte, 1)
	n, err := file.Read(version)
	if err != nil {
		return nil, err
	}
	if n != 1 {
		return nil, fmt.Errorf("Error reading secrets file")
	}
	if version[0] != 0 {
		return nil, fmt.Errorf("Cannot read file version %d", version[0])
	}

	salt := make([]byte, 32)
	n, err = file.Read(salt)
	if err != nil {
		return nil, err
	}
	if n != len(salt) {
		return nil, fmt.Errorf("Error reading secrets file")
	}

	iterBytes := make([]byte, 8)
	n, err = file.Read(iterBytes)
	if err != nil {
		return nil, err
	}
	if n != len(iterBytes) {
		return nil, fmt.Errorf("Error reading secrets file")
	}
	iterBig := big.NewInt(0)
	iterBig.SetBytes(iterBytes)
	iterations := int(iterBig.Int64())

	// FIXME: add some code to the iterations and rewrite the file
	// if the time to generate a key is too far from the target of 1
	// second
	secretsKeys := pbkdf2.Key([]byte(passphrase), salt, iterations, 80, sha512.New384)
	secretsDigest := sha512.New384()
	// don't need to check for errors, per spec
	secretsDigest.Write(secretsKeys)
	secretsKeysHash := secretsDigest.Sum(nil)
	storedHash := make([]byte, len(secretsKeysHash))
	n, err = file.Read(storedHash)
	if err != nil {
		return nil, err
	}
	if n != len(storedHash) {
		return nil, fmt.Errorf("Error reading secrets file")
	}
	if !bytes.Equal(storedHash, secretsKeysHash) {
		return nil, fmt.Errorf("Bad password")
	}

	iv := make([]byte, 16)
	n, err = file.Read(iv)
	if err != nil {
		return nil, err
	}
	if n != len(iv) {
		return nil, fmt.Errorf("Error reading secrets file")
	}

	secretsEncKey := secretsKeys[:32]
	secretsAuthKey := secretsKeys[32:]
	authHMAC := hmac.New(sha512.New384, secretsAuthKey)
	authHMAC.Write(version)
	authHMAC.Write(salt)
	authHMAC.Write(iterBytes)
	authHMAC.Write(secretsKeysHash)
	authHMAC.Write(iv)

	reader := io.TeeReader(file, authHMAC)
	cypher, err := aes.NewCipher(secretsEncKey)
	if err != nil {
		return nil, err
	}
	ctrReader := cipher.StreamReader{S: cipher.NewCTR(cypher, iv),
		R: reader}

	secrets = &Secrets{}
	secrets.metadataMaster = make([]byte, 32)
	n, err = ctrReader.Read(secrets.metadataMaster)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.metadataMaster) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}
	secrets.metadataAuthentication = make([]byte, 48)
	n, err = ctrReader.Read(secrets.metadataAuthentication)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.metadataAuthentication) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}
	secrets.metadataStorage = make([]byte, 48)
	n, err = ctrReader.Read(secrets.metadataStorage)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.metadataStorage) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}
	secrets.chunkMaster = make([]byte, 32)
	n, err = ctrReader.Read(secrets.chunkMaster)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.chunkMaster) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}
	secrets.chunkAuthentication = make([]byte, 48)
	n, err = ctrReader.Read(secrets.chunkAuthentication)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.chunkAuthentication) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}
	secrets.chunkStorage = make([]byte, 48)
	n, err = ctrReader.Read(secrets.chunkStorage)
	if err != nil {
		ZeroSecrets(secrets)
		return nil, err
	}
	if n != len(secrets.chunkStorage) {
		ZeroSecrets(secrets)
		return nil, fmt.Errorf("Error reading secrets file")
	}

	calcSum := authHMAC.Sum(nil)
	authSum := make([]byte, authHMAC.Size())
	n, err = reader.Read(authSum)
	if err != nil && err != io.EOF {
		return nil, err
	}
	if n != len(authSum) {
		return nil, fmt.Errorf("Error reading secrets file: %d", n)
	}
	if !bytes.Equal(calcSum, authSum) {
		return nil, fmt.Errorf("Corrupted secrets file")
	}
	return secrets, nil
}