Beispiel #1
0
// Returns a new Reader that reads from r
//
// The header section storing the salt and keys is read from r to verify the file is
// actually a psafe3 file and the password is correct.
//
// All reads from this reader will return unencrypted data.
func NewReader(r io.Reader, password string) (*Reader, error) {
	reader := &Reader{r: r, password: password}

	var header psv3Header
	binary.Read(r, binary.LittleEndian, &header)
	if string(header.Tag[:]) != "PWS3" {
		return nil, ErrBadFileType
	}

	sk := computeStretchKey(header.Salt[:], []byte(password), int(header.Iter))
	hashsk := sha256.Sum256(sk)

	if hashsk != header.HashPPrime {
		return nil, ErrInvalidPassword
	}

	var key, hmacKey [32]byte
	tfish, _ := twofish.NewCipher(sk)
	tfish.Decrypt(key[:16], header.B1[:])
	tfish.Decrypt(key[16:], header.B2[:])
	tfish.Decrypt(hmacKey[:16], header.B3[:])
	tfish.Decrypt(hmacKey[16:], header.B4[:])

	tfish, _ = twofish.NewCipher(key[:])
	reader.tfishDecrypter = cipher.NewCBCDecrypter(tfish, header.IV[:])
	reader.hmacHash = hmac.New(sha256.New, hmacKey[:])

	return reader, nil
}
Beispiel #2
0
func decrypt(blob []byte) {
	c, err := twofish.NewCipher(key)
	if err != nil {
		panic(err)
	}
	s := cipher.NewCFBDecrypter(c, iv)
	s.XORKeyStream(blob, blob)
}
Beispiel #3
0
func encrypt_data(plain, keys []byte) ([]byte, error) {
	var iv, key []byte
	var block cipher.Block
	var stream cipher.Stream

	iv_offset := TotalIVLen
	res := make([]byte, len(plain)+iv_offset)

	iv = res[iv_offset-SalsaIVLen : iv_offset]
	_, err := rand.Read(iv)
	if err != nil {
		return nil, err
	}
	// For some reason salsa20 API is different
	key_array := new([32]byte)
	copy(key_array[:], keys[cipherKeyLen*2:])
	salsa20.XORKeyStream(res[iv_offset:], plain, iv, key_array)
	iv_offset -= SalsaIVLen

	iv = res[iv_offset-IVLen : iv_offset]
	_, err = rand.Read(iv)
	if err != nil {
		return nil, err
	}
	key = keys[cipherKeyLen : cipherKeyLen*2]
	block, err = twofish.NewCipher(key)
	if err != nil {
		return nil, err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(res[iv_offset:], res[iv_offset:])
	iv_offset -= IVLen

	iv = res[iv_offset-IVLen : iv_offset]
	_, err = rand.Read(iv)
	if err != nil {
		return nil, err
	}
	key = keys[:cipherKeyLen]
	block, err = aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(res[iv_offset:], res[iv_offset:])
	iv_offset -= IVLen

	if iv_offset != 0 {
		panic(fmt.Errorf("something went terribly wrong: iv_offset final value non-zero"))
	}

	return res, nil
}
Beispiel #4
0
func decrypt_data(dst, data, keys []byte) error {
	var iv, key []byte
	var block cipher.Block
	var stream cipher.Stream
	var err error

	buffer := append([]byte{}, data...)

	iv_offset := IVLen
	iv = buffer[:iv_offset]
	key = keys[:cipherKeyLen]
	block, err = aes.NewCipher(key)
	if err != nil {
		return err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(buffer[iv_offset:], buffer[iv_offset:])

	iv_offset += IVLen
	iv = buffer[iv_offset-IVLen : iv_offset]
	key = keys[cipherKeyLen : cipherKeyLen*2]
	block, err = twofish.NewCipher(key)
	if err != nil {
		return err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(buffer[iv_offset:], buffer[iv_offset:])

	iv_offset += SalsaIVLen
	iv = buffer[iv_offset-SalsaIVLen : iv_offset]
	key_array := new([32]byte)
	copy(key_array[:], keys[cipherKeyLen*2:])
	salsa20.XORKeyStream(dst, buffer[iv_offset:], iv, key_array)

	if len(buffer[iv_offset:]) != len(data)-TotalIVLen {
		return fmt.Errorf("something went terribly wrong: bufsz is wrong")
	}

	return nil
}
Beispiel #5
0
// NewCipher creates a new Twofish cipher from the key.
func (key TwofishKey) NewCipher() cipher.Block {
	// NOTE: NewCipher only returns an error if len(key) != 16, 24, or 32.
	cipher, _ := twofish.NewCipher(key[:])
	return cipher
}
Beispiel #6
0
// Write the password safe to an encrypted psafe3 file
func OutputFile(outputfile, password string, safe Safe) error {
	outfile, err := os.Create(outputfile)
	if err != nil {
		log.Fatal(err)
	}
	defer outfile.Close()

	safe.Headers.LastSave = time.Now()
	safe.Headers.ProgramSave = "pwsafe 0.1"

	user, uerr := user.Current()
	if uerr == nil && user.Username != "" {
		safe.Headers.User = user.Username
	}

	if host, herr := os.Hostname(); herr == nil {
		safe.Headers.Host = host
	}

	fmt.Fprint(outfile, "PWS3")

	var randbytes [112]byte
	if _, rerr := rand.Read(randbytes[:]); rerr != nil {
		return rerr
	}
	salt := randbytes[:32]
	iv := randbytes[32:48]
	k := randbytes[48:80]
	l := randbytes[80:]

	outfile.Write(salt)
	binary.Write(outfile, binary.LittleEndian, uint32(iterations))

	sk := computeStretchKey(salt[:], []byte(password), iterations)
	hashsk := sha256.Sum256(sk)
	outfile.Write(hashsk[:])

	var b1, b2, b3, b4 [16]byte
	tfish, _ := twofish.NewCipher(sk)
	tfish.Encrypt(b1[:], k[:16])
	tfish.Encrypt(b2[:], k[16:])
	tfish.Encrypt(b3[:], l[:16])
	tfish.Encrypt(b4[:], l[16:])

	binary.Write(outfile, binary.LittleEndian, b1[:])
	binary.Write(outfile, binary.LittleEndian, b2[:])
	binary.Write(outfile, binary.LittleEndian, b3[:])
	binary.Write(outfile, binary.LittleEndian, b4[:])

	outfile.Write(iv[:])

	tfish, _ = twofish.NewCipher(k[:])
	engine := cipher.NewCBCEncrypter(tfish, iv[:])
	hmacEngine := hmac.New(sha256.New, l[:])

	var buf bytes.Buffer
	var endSection, blockData [16]byte
	endSection[4] = 0xFF

	// Headers
	writeField(outfile, engine, hmacEngine, 0x00, []byte{safe.Headers.VersionMinor, safe.Headers.VersionMajor})
	binary.Write(&buf, binary.LittleEndian, uint32(safe.Headers.LastSave.Unix()))
	writeField(outfile, engine, hmacEngine, 0x04, buf.Bytes())
	buf.Reset()
	writeField(outfile, engine, hmacEngine, 0x06, []byte(safe.Headers.ProgramSave))
	writeField(outfile, engine, hmacEngine, 0x07, []byte(safe.Headers.User))
	writeField(outfile, engine, hmacEngine, 0x08, []byte(safe.Headers.Host))
	engine.CryptBlocks(blockData[:], endSection[:])
	outfile.Write(blockData[:])

	for _, record := range safe.Records {
		id := uuid.NewV4()
		writeField(outfile, engine, hmacEngine, 0x01, id.Bytes())
		writeField(outfile, engine, hmacEngine, 0x02, []byte(record.Group))
		writeField(outfile, engine, hmacEngine, 0x03, []byte(record.Title))
		writeField(outfile, engine, hmacEngine, 0x04, []byte(record.Username))
		writeField(outfile, engine, hmacEngine, 0x05, []byte(record.Notes))
		writeField(outfile, engine, hmacEngine, 0x06, []byte(record.Password))

		binary.Write(&buf, binary.LittleEndian, uint32(record.CreationTime.Unix()))
		writeField(outfile, engine, hmacEngine, 0x07, buf.Bytes())
		buf.Reset()

		writeField(outfile, engine, hmacEngine, 0x0d, []byte(record.Url))
		writeField(outfile, engine, hmacEngine, 0x14, []byte(record.Email))

		engine.CryptBlocks(blockData[:], endSection[:])
		outfile.Write(blockData[:])
	}
	outfile.Write([]byte("PWS3-EOFPWS3-EOF"))

	outfile.Write(hmacEngine.Sum(nil))

	return nil
}
Beispiel #7
0
func (e *Engine) twofish_ctr() error {
	return e.ctr(func(key []byte) (cipher.Block, error) { return twofish.NewCipher(key) })
}
Beispiel #8
0
func (e *Engine) untwofish_cfb() error {
	return e.uncfb(func(key []byte) (cipher.Block, error) { return twofish.NewCipher(key) })
}
Beispiel #9
0
// Twofish cipher
func BenchmarkTwofish_1K(b *testing.B) {
	block, _ := twofish.NewCipher(buf[:16])
	benchmarkBlock(b, block, 1024)
}