Cryptography in Go (Golang): Encryption and Hashing

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Cryptography in Go (Golang): Data Encryption and Hashing



The Go language (Golang) provides a powerful and elegant standard library for cryptographic operations. Unlike many other languages where third-party packages need to be installed, Go includes support for symmetric and asymmetric encryption, as well as modern hashing algorithms, right out of the box. In this article, we will thoroughly examine how to use cryptography in Go to protect data on the educational portal pythonlib.ru.



Main Cryptography Packages in Go



All cryptography in Go is concentrated in the crypto package and its subpackages. Here are the key ones:

  • crypto/aes — implementation of the Advanced Encryption Standard (AES).
  • crypto/cipher — interfaces for encryption modes (CBC, GCM, CTR).
  • crypto/rsa — RSA asymmetric encryption.
  • crypto/sha256, crypto/sha512 — hash functions of the SHA-2 family.
  • golang.org/x/crypto/bcrypt — adaptive password hashing (additional package).
  • crypto/rand — cryptographically secure random number generator.


Symmetric AES Encryption in Go



Symmetric encryption uses the same key for encryption and decryption. Let's look at an example with AES-256 in GCM (Galois/Counter Mode), which provides data authentication.



package main

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

func encryptAES(plaintext []byte, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err }

// Create GCM (Galois/Counter Mode) gcm, err := cipher.NewGCM(block) if err != nil { return nil, err }

// Generate a random nonce (number used once) nonce := make([]byte, gcm.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return nil, err }

// Seal prepends the nonce to the ciphertext ciphertext := gcm.Seal(nonce, nonce, plaintext, nil) return ciphertext, nil}

func decryptAES(ciphertext []byte, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err }

gcm, err := cipher.NewGCM(block) if err != nil { return nil, err }

nonceSize := gcm.NonceSize() if len(ciphertext) < nonceSize { return nil, fmt.Errorf("ciphertext too short") }

nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { return nil, err } return plaintext, nil}

func main() { key := []byte("examplekey123456") // 16 bytes for AES-128 plaintext := []byte("Secret data for PythonLib")

encrypted, _ := encryptAES(plaintext, key) fmt.Println("Encrypted (hex):", hex.EncodeToString(encrypted))

decrypted, _ := decryptAES(encrypted, key) fmt.Println("Decrypted:", string(decrypted))}


Note: the key must be 16, 24, or 32 bytes long for AES-128, AES-192, or AES-256 respectively. The nonce (IV) is generated randomly and stored together with the ciphertext.



Asymmetric RSA Encryption in Go



RSA uses a pair of keys: a public key for encryption and a private key for decryption. This is ideal for secure data exchange between a server and a client.



package main

import ( "crypto/rand" "crypto/rsa" "crypto/sha256" "fmt")

func generateKeyPair(bits int) (*rsa.PrivateKey, error) {

Recommendations