// aes256.go
// This file is part of AES-everywhere project (https://github.com/mervick/aes-everywhere)
//
// This is an implementation of the AES algorithm, specifically CBC mode,
// with 256 bits key length and PKCS7 padding.
//
// Copyright Andrey Izman (c) 2018-2019 <izmanw@gmail.com>
// Licensed under the MIT license
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package aes256

import (
	
	
	
	
	b64 
	
	
)

// Encrypts text with the passphrase
func ( string,  string) (string) {
	 := make([]byte, 8)
	if ,  := io.ReadFull(rand.Reader, );  != nil {
		panic(.Error())
	}

	,  := __DeriveKeyAndIv(, string())

	,  := aes.NewCipher([]byte())
	if  != nil {
		panic()
	}

	 := __PKCS7Padding([]byte(), .BlockSize())
	 := cipher.NewCBCEncrypter(, []byte())
	 := make([]byte, len())
	.CryptBlocks(, )

	return b64.StdEncoding.EncodeToString([]byte("Salted__" + string() + string()))
}

// Decrypts encrypted text with the passphrase
func ( string,  string) (string) {
	,  := b64.StdEncoding.DecodeString()
	if len() < 16 || string([:8]) != "Salted__" {
		return ""
	}

	 := [8:16]
	 = [16:]
	,  := __DeriveKeyAndIv(, string())

	,  := aes.NewCipher([]byte())
	if  != nil {
		panic()
	}

	 := cipher.NewCBCDecrypter(, []byte())
	 := make([]byte, len())
	.CryptBlocks(, )

	return string(__PKCS7Trimming())
}

func __PKCS7Padding( []byte,  int) []byte {
	 :=  - len()%
	 := bytes.Repeat([]byte{byte()}, )
	return append(, ...)
}

func __PKCS7Trimming( []byte) []byte {
	 := [len()-1]
	return [:len()-int()]
}

func __DeriveKeyAndIv( string,  string) (string, string) {
	 := ""
	 := ""

	for len() < 48 {
		 := md5.New()
		.Write([]byte( +  + ))
		 := .Sum(nil)
		 = string([:16])
		 =  + 
	}

	 := [0:32]
	 := [32:48]

	return , 
}