» Quick Introduction to Go » 2. Intermediate » 2.1 Crypto

Crypto

The crypto package provides a collection of cryptographic primitives and algorithms.

Hash Functions

The crypto package provides a generic hash package that defines the hash.Hash interface. Sub-packages, such as crypto/sha256 and crypto/sha512, implement specific hash functions.

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
)

func calculateSHA256(input string) string {
	hasher := sha256.New()
	hasher.Write([]byte(input))
	hash := hasher.Sum(nil)
	return hex.EncodeToString(hash)
}

func main() {
	data := "Hello, Crypto!"
	hash := calculateSHA256(data)
	fmt.Printf("Input: %s\nSHA-256 Hash: %s\n", data, hash)
    // => Input: Hello, Crypto!
    // SHA-256 Hash: de0640f1dc17ca1b01fb9eba3019ed07c12e2af4ae990ecb36aa669898a9fd40
}

Symmetric Encryption

The cipher package includes interfaces and implementations for block cipher modes (e.g., AES, DES).

package main

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

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

	nonce := make([]byte, 12)
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		return "", err
	}

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

	ciphertext := aesgcm.Seal(nil, nonce, []byte(plaintext), nil)
	return hex.EncodeToString(ciphertext), nil
}

func main() {
	key := "0123456789abcdef0123456789abcdef" // 32 bytes for AES-256
	plaintext := "Hello, AES-GCM!"

	ciphertext, err := encryptAESGCM(key, plaintext)
	if err != nil {
		fmt.Println("Encryption error:", err)
		return
	}

	fmt.Printf("Plaintext: %s\nCiphertext: %s\n", plaintext, ciphertext)
    // => Plaintext: Hello, AES-GCM!
    // => Ciphertext: 9ce45e9cdc452a3e70169bbacf6a926c012462ca0efb5e3945a2a85c539ba3
}

Asymmetric Encryption

The rsa package supports RSA encryption and decryption. The ecdsa package supports the Elliptic Curve Digital Signature Algorithm.

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
)

func encryptRSA(publicKey *rsa.PublicKey, plaintext string) (string, error) {
	ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(plaintext))
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

func main() {
	// In practice, load the public key from a file or another source.
	publicKeyPEM := `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2aWbY8+0wQbOMxvDLgs
+3Cb9SMoyA/2v9MqZrwh4jG28x20aHz/Wng+6vYpFsmw6KrN6k7PZuBn8j/tgyzR
PQFQyXct0p56UM5o6j2gsa1EGZQMHFGiZ0bgqzsc4LCM0Jhz6Dc/0q1q62gjVGUF
oZxq1/2Rrg5n4z5mDPnWozDmupzrMtD9UgA2yV2+u6z2fnUGDT3FJoEZSYwcl4Co
9j8aVj0hl/jhVKuYJ13lh9EDVHdwqojyDWX5U5P+LrDlAlSvs88kH3tlr5S/0sRk
WtRc5d2g+VC/rI3ufkr/YMl9QcNQupXNqA3hq8fVezwwUcd6H62wUsyLOyrUkWmE
BQIDAQAB
-----END PUBLIC KEY-----
`

	block, _ := pem.Decode([]byte(publicKeyPEM))
	if block == nil {
		fmt.Println("Error decoding public key")
		return
	}

	publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		fmt.Println("Error parsing public key:", err)
		return
	}

	plaintext := "Hello, RSA!"
	ciphertext, err := encryptRSA(publicKey.(*rsa.PublicKey), plaintext)
	if err != nil {
		fmt.Println("Encryption error:", err)
		return
	}

	fmt.Printf("Plaintext: %s\nCiphertext: %s\n", plaintext, ciphertext)
    // => Plaintext: Hello, RSA!
    // => Ciphertext: X4UG+f0jXTyC+iOy6SPlHeML90her5HOyOz00Yh1XMcYU07B3U6oraEvLySQzQuBAWm8PTkVjZvHaJ1Z9EKRko3kovpIUNGqv6OEwqzc+FMJBHwAfyG7Z9oyKJeNaACaWyCL7bhI4q1TrbrwwzRcUigkX5IHZq3Pz3Zb4dhTv7d50nBKrK4/3Fjxofp5wuyOQrDeYdggV5rkXAJJ+XeYihkbSDjc9xR7ul1b7cxPz9hcfgdvWe+UV5kvuf5TWFpaTxEKMjXxknkYK9T/dgs8w6y29llu/195nSjyumDEovi+AGS32e7id8YmC4JiE4rTvmIWSiLu7QvyAEne4fn4dw==
}

Random Number Generation

The rand package provides a source of cryptographically secure random numbers.

package main

import (
	"crypto/rand"
	"fmt"
	"math/big"
)

func generateRandomString(length int) (string, error) {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	charsetLength := big.NewInt(int64(len(charset)))
	result := make([]byte, length)

	for i := range result {
		randomIndex, err := rand.Int(rand.Reader, charsetLength)
		if err != nil {
			return "", err
		}
		result[i] = charset[randomIndex.Int64()]
	}

	return string(result), nil
}

func main() {
	randomString, err := generateRandomString(16)
	if err != nil {
		fmt.Println("Error generating random string:", err)
		return
	}

	fmt.Println("Random String:", randomString)
    // => Random String: aPL0YL2RuLoqvF9J
}

Code Challenges

Implement a secure password hashing utility in Go that uses SHA-256.

Loading...
> code result goes here
Prev
Next