github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/actions/lua/crypto/aes/aes.go (about)

     1  package aes
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/rand"
     8  	"io"
     9  
    10  	"github.com/Shopify/go-lua"
    11  )
    12  
    13  func Open(l *lua.State) {
    14  	aesOpen := func(l *lua.State) int {
    15  		lua.NewLibrary(l, aesLibrary)
    16  		return 1
    17  	}
    18  	lua.Require(l, "crypto/aes", aesOpen, false)
    19  	l.Pop(1)
    20  }
    21  
    22  var aesLibrary = []lua.RegistryFunction{
    23  	{Name: "encryptCBC", Function: encryptCBC},
    24  	{Name: "decryptCBC", Function: decryptCBC},
    25  }
    26  
    27  func encryptCBC(l *lua.State) int {
    28  	key := []byte(lua.CheckString(l, 1))
    29  	plaintext := []byte(lua.CheckString(l, 2))
    30  
    31  	block, err := aes.NewCipher(key)
    32  	if err != nil {
    33  		lua.Errorf(l, "%s", err.Error())
    34  		panic("unreachable")
    35  	}
    36  
    37  	content := PKCS5Padding(plaintext, aes.BlockSize, len(plaintext))
    38  
    39  	ciphertext := make([]byte, aes.BlockSize+len(content))
    40  	iv := ciphertext[:aes.BlockSize]
    41  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    42  		lua.Errorf(l, "%s", err.Error())
    43  		panic("unreachable")
    44  	}
    45  
    46  	encrypter := cipher.NewCBCEncrypter(block, iv)
    47  	encrypter.CryptBlocks(ciphertext[aes.BlockSize:], content)
    48  
    49  	l.PushString(string(ciphertext))
    50  
    51  	return 1
    52  }
    53  
    54  func decryptCBC(l *lua.State) int {
    55  	key := []byte(lua.CheckString(l, 1))
    56  	ciphertext := []byte(lua.CheckString(l, 2))
    57  
    58  	block, err := aes.NewCipher(key)
    59  	if err != nil {
    60  		lua.Errorf(l, "%s", err.Error())
    61  		panic("unreachable")
    62  	}
    63  
    64  	iv := ciphertext[:aes.BlockSize]
    65  	ciphertext = ciphertext[aes.BlockSize:]
    66  
    67  	decrypter := cipher.NewCBCDecrypter(block, iv)
    68  	decrypter.CryptBlocks(ciphertext, ciphertext)
    69  
    70  	l.PushString(string(PKCS5UnPadding(ciphertext)))
    71  
    72  	return 1
    73  }
    74  
    75  func PKCS5Padding(ciphertext []byte, blockSize int, after int) []byte {
    76  	block := blockSize - len(ciphertext)%blockSize
    77  	padding := bytes.Repeat([]byte{byte(block)}, block)
    78  	return append(ciphertext, padding...)
    79  }
    80  
    81  func PKCS5UnPadding(src []byte) []byte {
    82  	srcLength := len(src)
    83  	paddingLength := int(src[srcLength-1])
    84  	return src[:(srcLength - paddingLength)]
    85  }