Problem using AES decryption (cipher: message authentication failed)

I am making a custom AES-256 encryption and decryption function, i saved the functions in a package called zeus

/*
Index:
101 --> Hashing functions
102 --> Encryption functions
*/

package zeus

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"fmt"
	"golang.org/x/crypto/bcrypt"
	"io"
	"log"
)

// 101 --> Hashing functions

// Takes a string, hashes it using sha256 and returns a hashed string
func SHA_256(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha256.Sum256(bytes)
	hashedString = fmt.Sprintf("%X\n", hash)
	return hashedString
}

// Takes a string, hashes it using sha512 and returns a hashed string
func SHA_512(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha512.Sum512(bytes)
	hashedString = fmt.Sprintf("%X\n", hash)
	return hashedString
}

// Takes the plainText and cost, hashes it using bcrypt and returns a
// hashed string
func Bcrypt(plainText string, cost int) (hashedString string) {
	bytes := []byte(plainText)
	// generate hashed string
	hash, err := bcrypt.GenerateFromPassword(bytes, cost)
	if err != nil {
		log.Fatal(err)
	}
	hashedString = fmt.Sprintf("%s\n", hash)
	return hashedString
}

// Checks to see if the hash matches the Plain Text
func Bcrypt_Check(hashedString string, plainText string) {
	hashedString_bytes := []byte(hashedString)
	plainText_bytes := []byte(plainText)
	result := bcrypt.CompareHashAndPassword(hashedString_bytes, plainText_bytes)
	if result != nil {
		log.Fatal(result)
	}
	fmt.Println("Matched!")
}

// hashes the key string you enter, trim it to 32 bytes and convert it to bytes
func GenerateKey(key string) (final_key []byte) {
	hashed_key := SHA_256(key)
	// trimming the key to fit 32 bytes (AES-256)
	trimmed_key := hashed_key[0:32]
	// converting the trimmed key to bytes
	final_key = []byte(trimmed_key)
	return final_key
}

// 102 --> Encryption functions

// AES_256 encryption, takes plainText and a key, returns cipherText_String
func Encrypt_AES_256(plainText string, key string) (cipherText_String string) {
	// convert the message (text) to bytes
	plainText_bytes := []byte(plainText)
	// generate key
	final_key := GenerateKey(key)
	// creating a new cipher block
	cipher1, err := aes.NewCipher(final_key)
	// checking if there is an error, if so exit the script
	if err != nil {
		log.Fatal(err)
	}
	// passing the cipher block to Galois/Counter Mode (GCM)
	gcm, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	// create a new byte array the size of Nonce
	nonce := make([]byte, gcm.NonceSize())
	// populate the byte array with a cryptographically secure random sequence
	_, err = io.ReadFull(rand.Reader, nonce)
	if err != nil {
		log.Fatal(err)
	}
	// Seal encrypts and authenticates plaintext, authenticates additional data
	cipherText := gcm.Seal(nonce, nonce, plainText_bytes, nil)
	cipherText_String = fmt.Sprintf("%X\n", cipherText)
	return cipherText_String
}

This is my main file:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	// "crypto/rand"
	// "crypto/sha256"
	// "crypto/sha512"
	// "encoding/hex"
	"fmt"
	"github.com/kkaskdf/zeus"
	// "golang.org/x/crypto/bcrypt"
	// "io"
	// "io/ioutil"
	"log"
)

func Decrypt_AES_256(cipherText_String string, key string) (plainText string) {
	final_key := zeus.GenerateKey(key)
	cipher1, err := aes.NewCipher(final_key)
	if err != nil {
		log.Fatal(err)
	}
	gcmDecrypt, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	nonceSize := gcmDecrypt.NonceSize()
	cipherText_byte := []byte(cipherText_String)
	if len(cipherText_byte) < nonceSize {
		log.Fatal(err)
	}
	nonce, encryptedMessage := cipherText_byte[:nonceSize],
		cipherText_byte[nonceSize:]
	nonce_byte := []byte(nonce)
	encryptedMessage_byte := []byte(encryptedMessage)
	plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)
	fmt.Println("err0")
	if err != nil {
		log.Fatal(err)
	}
	return fmt.Sprintf("%s", plaintext)
}

func main() {
	// str1 := "Hi man Can"
	// str2 := "Hi man Can"
	// fmt.Printf("%v", zeus.SHA_256(str1))
	// fmt.Printf("%v", zeus.SHA_512(str1))
	// fmt.Printf("%v", zeus.Bcrypt(str1, 5))

	// zeus.Bcrypt_Check(zeus.Bcrypt(str1, 5), str2)

	password := "This is the password"
	plainText := "Hi man Can 32 Hi man Can 23 Hi man Can"
	cipherText := zeus.Encrypt_AES_256(plainText, password)
	fmt.Printf("%v", cipherText)
	fmt.Printf("%v", Decrypt_AES_256(cipherText, password))

}

Now when i try decrypting the cipherText , i get this output

4E4E31C4D70AC4F6F6696CB2921C208BE3124F3CBB5E73AFEE7FBB81F503034AA64EFAB3CC35784D25ED125943E835B9371BA4D3AAC9A292C00A4F256CECEF9A815B
err0
2020/12/11 00:51:49 cipher: message authentication failed

First line in the output is the encrypted text and its the output of Encrypt_AES_256()

Second line is a string i printed to detect where the error is inside the Decrypt_AES_256() function

Third line is the output of the err here:

plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)
	fmt.Println("err0")
	if err != nil {
		log.Fatal(err)
	}

The error is in the Decrypt_AES_256() in line

plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)

Do anyone know how to solve this problem ?

I followed the instructions from this article:

I modified the code to be easier to read:

Main file:

package main

import (
	"fmt"
	"github.com/pmgfg/zeus"
)

func main() {
	plainText := "This is plain text"
	plainText2 := "This is plain text 2"
	fmt.Println("SHA_256 -->", zeus.SHA_256(plainText))
	fmt.Println("SHA_512 -->", zeus.SHA_512(plainText))

	bcrypt_hash := zeus.Bcrypt(plainText, 4)
	fmt.Println("Bcrypt -->", bcrypt_hash)

	//checking if the hash and the plain text match
	zeus.Bcrypt_Check(bcrypt_hash, plainText)
	zeus.Bcrypt_Check(bcrypt_hash, plainText2)

	fmt.Println()

	//encrypting the plain text
	key := "This is a key password"
	cipherText := zeus.Encrypt_AES_256(plainText, key)
	fmt.Println("Encrypt_AES_256 -->", cipherText)
	fmt.Println("Decrypt_AES_256 -->", zeus.Decrypt_AES_256(cipherText, key))
}

Package zeus:

/*
Index:
101 --> Hashing functions
102 --> Encryption functions
*/

package zeus

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"fmt"
	"golang.org/x/crypto/bcrypt"
	"io"
	"log"
)

// 101 --> Hashing functions

// Takes a string, hashes it using sha256 and returns a hashed string
func SHA_256(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha256.Sum256(bytes)
	hashedString = fmt.Sprintf("%x\n", hash)
	return hashedString
}

// Takes a string, hashes it using sha512 and returns a hashed string
func SHA_512(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha512.Sum512(bytes)
	hashedString = fmt.Sprintf("%x\n", hash)
	return hashedString
}

// Takes the plainText and cost, hashes it using bcrypt and returns a
// hashed string
func Bcrypt(plainText string, cost int) (hashedString string) {
	bytes := []byte(plainText)
	// generate hashed string
	hash, err := bcrypt.GenerateFromPassword(bytes, cost)
	if err != nil {
		log.Fatal(err)
	}
	hashedString = fmt.Sprintf("%s\n", hash)
	return hashedString
}

// Checks to see if the hash matches the Plain Text
func Bcrypt_Check(hashedString string, plainText string) {
	hashedString_bytes := []byte(hashedString)
	plainText_bytes := []byte(plainText)
	result := bcrypt.CompareHashAndPassword(hashedString_bytes, plainText_bytes)
	if result != nil {
		log.Println(result)
	} else {
		fmt.Println("Matched!")
	}
}

// hashes the key string you enter, trim it to 32 bytes and convert it to bytes
func GenerateKey(key string) (final_key []byte) {
	hashed_key := SHA_256(key)
	// trimming the key to fit 32 bytes (AES-256)
	trimmed_key := hashed_key[0:32]
	// converting the trimmed key to bytes
	final_key = []byte(trimmed_key)
	return final_key
}

// 102 --> Encryption functions

// AES_256 encryption, takes plainText and a key, returns cipherText_String
func Encrypt_AES_256(plainText string, key string) (cipherText_String string) {
	// convert the message (text) to bytes
	plainText_bytes := []byte(plainText)
	// generate key
	final_key := GenerateKey(key)
	// creating a new cipher block
	cipher1, err := aes.NewCipher(final_key)
	// checking if there is an error, if so exit the script
	if err != nil {
		log.Fatal(err)
	}
	// passing the cipher block to Galois/Counter Mode (GCM)
	gcm, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	// create a new byte array the size of Nonce
	nonce := make([]byte, gcm.NonceSize())
	// populate the byte array with a cryptographically secure random sequence
	_, err = io.ReadFull(rand.Reader, nonce)
	if err != nil {
		log.Fatal(err)
	}
	// Seal encrypts and authenticates plaintext, authenticates additional data
	cipherText := gcm.Seal(nonce, nonce, plainText_bytes, nil)
	cipherText_String = fmt.Sprintf("%X\n", cipherText)
	return cipherText_String
}

// AES_256 decryption, takes cipherText_String and a key, returns plainText
func Decrypt_AES_256(cipherText_String string, key string) (plainText string) {
	final_key := GenerateKey(key)
	cipher1, err := aes.NewCipher(final_key)
	if err != nil {
		log.Fatal(err)
	}
	gcmDecrypt, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	nonceSize := gcmDecrypt.NonceSize()
	cipherText_byte := []byte(cipherText_String)
	if len(cipherText_byte) < nonceSize {
		log.Fatal(err)
	}
	nonce, encryptedMessage := cipherText_byte[:nonceSize],
		cipherText_byte[nonceSize:]
	nonce_byte := []byte(nonce)
	encryptedMessage_byte := []byte(encryptedMessage)
	plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)
	fmt.Println("err0")
	if err != nil {
		log.Fatal(err)
	}
	return fmt.Sprintf("%s", plaintext)
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.