github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/config/secrets/encryption.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/config/secrets/encryption.go
    14  
    15  package secrets
    16  
    17  import (
    18  	"crypto/aes"
    19  	"crypto/cipher"
    20  	"crypto/rand"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"io"
    24  )
    25  
    26  // encrypt/decrypt functions are taken from https://www.melvinvivas.com/how-to-encrypt-and-decrypt-data-using-aes/
    27  
    28  func encrypt(stringToEncrypt string, key []byte) (string, error) {
    29  	plaintext := []byte(stringToEncrypt)
    30  
    31  	//Create a new Cipher Block from the key
    32  	block, err := aes.NewCipher(key)
    33  	if err != nil {
    34  		return "", err
    35  	}
    36  
    37  	//Create a new GCM - https://en.wikipedia.org/wiki/Galois/Counter_Mode
    38  	//https://golang.org/pkg/crypto/cipher/#NewGCM
    39  	aesGCM, err := cipher.NewGCM(block)
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  
    44  	//Create a nonce. Nonce should be from GCM
    45  	nonce := make([]byte, aesGCM.NonceSize())
    46  	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
    47  		return "", err
    48  	}
    49  
    50  	//Encrypt the data using aesGCM.Seal
    51  	//Since we don't want to save the nonce somewhere else in this case, we add it as a prefix to the encrypted data. The first nonce argument in Seal is the prefix.
    52  	ciphertext := aesGCM.Seal(nonce, nonce, plaintext, nil)
    53  	return fmt.Sprintf("%x", ciphertext), nil
    54  }
    55  
    56  func decrypt(encryptedString string, key []byte) (string, error) {
    57  	enc, _ := hex.DecodeString(encryptedString)
    58  
    59  	//Create a new Cipher Block from the key
    60  	block, err := aes.NewCipher(key)
    61  	if err != nil {
    62  		return "", err
    63  	}
    64  
    65  	//Create a new GCM
    66  	aesGCM, err := cipher.NewGCM(block)
    67  	if err != nil {
    68  		return "", err
    69  	}
    70  
    71  	//Get the nonce size
    72  	nonceSize := aesGCM.NonceSize()
    73  
    74  	//Extract the nonce from the encrypted data
    75  	nonce, ciphertext := enc[:nonceSize], enc[nonceSize:]
    76  
    77  	//Decrypt the data
    78  	plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
    79  	if err != nil {
    80  		return "", err
    81  	}
    82  
    83  	return fmt.Sprintf("%s", plaintext), nil
    84  }