Go Language - Multilevel Data Encryption Using AES and RSA - Implementation

Advanced Encryption Standard(AES) is a symmetric encryption algorithm. AES encryption is used by the U.S. for securing sensitive but unclassified material, so we can say it is enough secure. It allows 128 bit, 192 bit and 256-bit encryption. Symmetric encryption is very fast as compared to asymmetric encryption and are used in systems such as database system. 

The RSA algorithm (Rivest-Shamir-Adleman) is a cryptographic algorithm that is used for specific security services or purposes, which enables public-key encryption and is widely used to secure sensitive data, particularly when it is being sent over an insecure network such as the HTTP. A public key is shared publicly, while a private key is secret and must not be shared with anyone.

  • Encryption's primary purpose is to protect against brute force attacks. It is composed of a cipher, the message/data, and a key (the password). With a wide range of free tools available like(Aircrack-ng, John the Ripper, Rainbow Crack, L0phtCrack ), even baby hackers can attempt to hack passwords using brute force. 
  • In my opinion, as a layperson in cryptography, multiple double-layer encryptions may not increase security, but they may slow down attackers. 
  • Using encryption may cause performance issues. Or maybe not. It really depends on how you use it. If you understand just how "expensive" each part of your enterprise encryption operation is, it's possible you can avoid the expensive parts and dramatically increase the performance of your applications.

Example Program

// RSA + AES Multilevel Data Encryption
package main

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
)

// Main function
func main() {

//Your secret text
secretMessage := "My Secret Text"

//2048 is the number of bits for RSA
bitSize := 2048

//Generate RSA keys
privateKey, err := rsa.
GenerateKey(rand.Reader, bitSize)
CheckError(err)

publicKey := privateKey.PublicKey

//Generate a random 32 byte AES key
key := GenerateRandomKey()

//RSA Encryption
encryptedMessage := EncryptWithPublicKey(key,
publicKey)

fmt.Println("\nRSA encryption:", encryptedMessage)

//RSA Decryption
aeskey := DecryptWithPrivateKey(encryptedMessage, *privateKey)

//AES encryption(secretMessage)
encrypted := encrypt(secretMessage, aeskey)

fmt.Println("\nAES encryption:", encrypted)

//decryption
decrypted := decrypt(encrypted, aeskey)
fmt.Printf("\noriginal data: %s\n", decrypted)

}

//RSA Encryption
func EncryptWithPublicKey(secretMessage string,
key rsa.PublicKey) string {

rng := rand.Reader
ciphertext, err := rsa.EncryptOAEP(sha256.New(),
rng, &key, []byte(secretMessage), nil)

if err != nil {
panic(err)
}

return base64.StdEncoding.EncodeToString(ciphertext)
}

//RSA Decryption
func DecryptWithPrivateKey(cipherText string,
privKey rsa.PrivateKey) string {

//Decode the Cipher text
ct, err := base64.StdEncoding.DecodeString(cipherText)
rng := rand.Reader
secrettext, err := rsa.DecryptOAEP(sha256.New(),
rng, &privKey, ct, nil)

if err != nil {
panic(err)
}

return string(secrettext)
}

//AES encryption
func encrypt(stringToEncrypt string,
keyString string) (encryptedString string) {

//convert decode it to bytes
key := Decode(keyString)
plaintext := []byte(stringToEncrypt)

//Create a new Cipher Block from the key
block, err := aes.NewCipher(key)
CheckError(err)

//Create a new GCM
aesGCM, err := cipher.NewGCM(block)
CheckError(err)

//Create a nonce.
nonce := make([]byte, aesGCM.NonceSize())
_, err = io.ReadFull(rand.Reader, nonce)
CheckError(err)

//Encrypt the data
ciphertext := aesGCM.
Seal(nonce, nonce, plaintext, nil)
return fmt.Sprintf("%x", ciphertext)
}

//AES decryption
func decrypt(encryptedString string,
keyString string) (decryptedString string) {

key := Decode(keyString)
enc := Decode(encryptedString)

//Create a new Cipher Block from the key
block, err := aes.NewCipher(key)
CheckError(err)

//Create a new GCM
aesGCM, err := cipher.NewGCM(block)
CheckError(err)

//Get the nonce size
nonceSize := aesGCM.NonceSize()

//Extract the nonce from the encrypted data
nonce, ciphertext := enc[:nonceSize], enc[nonceSize:]

//Decrypt the data
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
CheckError(err)

return fmt.Sprintf("%s", plaintext)
}

//AES generate a random 32 byte key
func GenerateRandomKey() string {

bytes := make([]byte, 32)
_, err := rand.Read(bytes)
CheckError(err)
key := hex.EncodeToString(bytes)
return key
}

//Convert to bytes
func Decode(text string) []byte {

bytes, err := hex.DecodeString(text)
CheckError(err)
return bytes
}

func CheckError(err error) {
if err != nil {
panic(err)
}
}

Run the application:

go run rsaaes.go
Output:


Let's see the architecture of the RSA + AES system in Client-Server Model


Developer Name,
Zafin

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete