|
@@ -0,0 +1,71 @@
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "crypto/aes"
|
|
|
+ "crypto/cipher"
|
|
|
+ "crypto/rand"
|
|
|
+)
|
|
|
+
|
|
|
+func encrypt(plaintext, key []byte) ([]byte, error) {
|
|
|
+ block, err := aes.NewCipher(key)
|
|
|
+ if err != nil {
|
|
|
+ return []byte{}, err
|
|
|
+ }
|
|
|
+
|
|
|
+ iv := make([]byte, aes.BlockSize)
|
|
|
+ rand.Read(iv)
|
|
|
+
|
|
|
+ plaintextPadded := pad(plaintext)
|
|
|
+ encrypted := make([]byte, len(plaintextPadded))
|
|
|
+
|
|
|
+ mode := cipher.NewCBCEncrypter(block, iv)
|
|
|
+ mode.CryptBlocks(encrypted, plaintextPadded)
|
|
|
+
|
|
|
+ return append(iv, encrypted...), nil
|
|
|
+}
|
|
|
+
|
|
|
+func decrypt(encryptedIVandData, key []byte) ([]byte, error) {
|
|
|
+ block, err := aes.NewCipher(key)
|
|
|
+ if err != nil {
|
|
|
+ return []byte{}, err
|
|
|
+ }
|
|
|
+
|
|
|
+ iv := encryptedIVandData[0:aes.BlockSize]
|
|
|
+ encrypted := encryptedIVandData[aes.BlockSize:]
|
|
|
+
|
|
|
+ mode := cipher.NewCBCDecrypter(block, iv)
|
|
|
+
|
|
|
+ plaintextPadded := make([]byte, len(encrypted))
|
|
|
+ mode.CryptBlocks(plaintextPadded, encrypted)
|
|
|
+ plaintext := unpad(plaintextPadded)
|
|
|
+
|
|
|
+ return plaintext, nil
|
|
|
+}
|
|
|
+
|
|
|
+func unpad(in []byte) []byte {
|
|
|
+ if len(in) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ padding := in[len(in)-1]
|
|
|
+ if int(padding) > len(in) || padding > aes.BlockSize {
|
|
|
+ return nil
|
|
|
+ } else if padding == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ for i := len(in) - 1; i > len(in)-int(padding)-1; i-- {
|
|
|
+ if in[i] != padding {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return in[:len(in)-int(padding)]
|
|
|
+}
|
|
|
+
|
|
|
+func pad(in []byte) []byte {
|
|
|
+ padding := aes.BlockSize - (len(in) % aes.BlockSize)
|
|
|
+ for i := 0; i < padding; i++ {
|
|
|
+ in = append(in, byte(padding))
|
|
|
+ }
|
|
|
+ return in
|
|
|
+}
|