func (a *archive50) parseFileEncryptionRecord(b readBuf, f *fileBlockHeader) error {
	if ver := b.uvarint(); ver != 0 {
		return errUnknownEncMethod
	}
	flags := b.uvarint()
	keys, err := a.getKeys(&b)
	if err != nil {
		return err
	}
	f.key = keys[0]
	if len(b) < 16 {
		return errCorruptEncrypt
	}
	f.iv = b.bytes(16)
	if flags&file5EncCheckPresent > 0 {
		if err := checkPassword(&b, keys); err != nil {
			return err
		}
	}
	if flags&file5EncUseMac > 0 {
		a.checksum.key = keys[1]
	}
	return nil
}
parseFileEncryptionRecord processes the optional file encryption record from a file header.
package rardecode
import (
	"bufio"
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"errors"
	"hash"
	"hash/crc32"
	"io"
	"io/ioutil"
	"time"
)
const (
	block5Arc     = 1
	block5File    = 2
	block5Service = 3
	block5Encrypt = 4
	block5End     = 5
	block5HasExtra     = 0x0001
	block5HasData      = 0x0002
	block5DataNotFirst = 0x0008
	block5DataNotLast  = 0x0010
	endArc5NotLast = 0x0001
	enc5CheckPresent = 0x0001  
	arc5MultiVol = 0x0001
	arc5Solid    = 0x0004
	file5IsDir          = 0x0001
	file5HasUnixMtime   = 0x0002
	file5HasCRC32       = 0x0004
	file5UnpSizeUnknown = 0x0008
	file5EncCheckPresent = 0x0001  
	file5EncUseMac       = 0x0002  
	cacheSize50   = 4
	maxPbkdf2Salt = 64
	pwCheckSize   = 8
	maxKdfCount   = 24
	minHeaderSize = 7
)
var (
	errBadPassword      = errors.New("rardecode: incorrect password")
	errCorruptEncrypt   = errors.New("rardecode: corrupt encryption data")
	errUnknownEncMethod = errors.New("rardecode: unknown encryption method")
)
type extra struct {
	ftype uint64   
	data  readBuf  
}
type blockHeader50 struct {
	htype    uint64  
	flags    uint64
	data     readBuf  
	extra    []extra  
	dataSize int64    
}
type leHash32 struct {
	hash.Hash32
}
func (h leHash32) Sum(b []byte) []byte {
	s := h.Sum32()
	return append(b, byte(s), byte(s>>8), byte(s>>16), byte(s>>24))
}
func newLittleEndianCRC32() hash.Hash32 {
	return leHash32{crc32.NewIEEE()}
}
type hash50 struct {
	hash.Hash         
	sum       []byte  
	key       []byte  
}
func (h *hash50) valid() bool {
	sum := h.Sum(nil)
	if len(h.key) > 0 {
		mac := hmac.New(sha256.New, h.key)
		mac.Write(sum)
		sum = mac.Sum(sum[:0])
		if len(h.sum) == 4 {
			for i, v := range sum[4:] {
				sum[i&3] ^= v
			}
			sum = sum[:4]
		}
	}
	return bytes.Equal(sum, h.sum)
}
type archive50 struct {
	byteReader                
	v          *bufio.Reader  
	pass       []byte
	blockKey   []byte                 
	multi      bool                   
	solid      bool                   
	checksum   hash50                 
	dec        decoder                
	buf        readBuf                
	keyCache   [cacheSize50]struct {  
		kdfCount int
		salt     []byte
		keys     [][]byte
	}
}
func calcKeys50(pass, salt []byte, kdfCount int) [][]byte {
	if len(salt) > maxPbkdf2Salt {
		salt = salt[:maxPbkdf2Salt]
	}
	keys := make([][]byte, 3)
	if len(keys) == 0 {
		return keys
	}
	prf := hmac.New(sha256.New, pass)
	prf.Write(salt)
	prf.Write([]byte{0, 0, 0, 1})
	t := prf.Sum(nil)
	u := append([]byte(nil), t...)
	kdfCount--
	for i, iter := range []int{kdfCount, 16, 16} {
		for iter > 0 {
			prf.Reset()
			prf.Write(u)
			u = prf.Sum(u[:0])
			for j := range u {
				t[j] ^= u[j]
			}
			iter--
		}
		keys[i] = append([]byte(nil), t...)
	}
	pwcheck := keys[2]
	for i, v := range pwcheck[pwCheckSize:] {
		pwcheck[i&(pwCheckSize-1)] ^= v
	}
	keys[2] = pwcheck[:pwCheckSize]
	return keys
}
func (a *archive50) getKeys(b *readBuf) (keys [][]byte, err error) {
	if len(*b) < 17 {
		return nil, errCorruptEncrypt
	}
	kdfCount := int(b.byte())
	if kdfCount > maxKdfCount {
		return nil, errCorruptEncrypt
	}
	kdfCount = 1 << uint(kdfCount)
	salt := b.bytes(16)
	for _, v := range a.keyCache {
		if kdfCount == v.kdfCount && bytes.Equal(salt, v.salt) {
			return v.keys, nil
		}
	}
	keys = calcKeys50(a.pass, salt, kdfCount)
	copy(a.keyCache[1:], a.keyCache[:])
	a.keyCache[0].kdfCount = kdfCount
	a.keyCache[0].salt = append([]byte(nil), salt...)
	a.keyCache[0].keys = keys
	return keys, nil
}
func checkPassword(b *readBuf, keys [][]byte) error {
	if len(*b) < 12 {
		return nil  
	}
	pwcheck := b.bytes(8)
	sum := b.bytes(4)
	csum := sha256.Sum256(pwcheck)
	if bytes.Equal(sum, csum[:len(sum)]) && !bytes.Equal(pwcheck, keys[2]) {
		return errBadPassword
	}
	return nil
}