package filters import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/sha256" "encoding/binary" "hash" "io" "strings" "unicode/utf16" ) var km keyManager func init() { km.cache = make(map[string][]byte) km.hasher = sha256.New() } // AESDecrypter is an AES-256 decryptor. type AESDecrypter struct { r io.Reader rbuf bytes.Buffer cbc cipher.BlockMode buf [aes.BlockSize]byte } type keyManager struct { hasher hash.Hash cache map[string][]byte } func (km *keyManager) Key(power int, salt []byte, password string) []byte { var cacheKey strings.Builder cacheKey.WriteString(password) cacheKey.Write(salt) cacheKey.WriteByte(byte(power)) key, ok := km.cache[cacheKey.String()] if ok { return key } b := bytes.NewBuffer(nil) for _, p := range utf16.Encode([]rune(password)) { binary.Write(b, binary.LittleEndian, p) } if power == 0x3f { key = km.stretch(salt, b.Bytes()) } else { key = km.sha256Stretch(power, salt, b.Bytes()) } km.cache[cacheKey.String()] = key return key } func (km *keyManager) stretch(salt, password []byte) []byte { var key [aes.BlockSize]byte var pos int for pos = 0; pos < len(salt); pos++ { key[pos] = salt[pos] } for i := 0; i < len(password) && pos < len(key); i++ { key[pos] = password[i] pos++ } for ; pos < len(key); pos++ { key[pos] = 0 } return key[:] } func (km *keyManager) sha256Stretch(power int, salt, password []byte) []byte { var temp [8]byte for round := 0; round < 1<