Created
June 8, 2023 11:34
-
-
Save cod3smith/145b780c68ea0f1b24d551b2d1adeed1 to your computer and use it in GitHub Desktop.
Revisions
-
cod3smith created this gist
Jun 8, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,238 @@ package main import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/pem" "fmt" "io/ioutil" "os" ) func generateRSAKeyPair() (*rsa.PrivateKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err } return privateKey, nil } func savePrivateKeyToPEM(privateKey *rsa.PrivateKey, filename string) error { keyBytes := x509.MarshalPKCS1PrivateKey(privateKey) pemBlock := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: keyBytes, } file, err := os.Create(filename) if err != nil { return err } defer file.Close() err = pem.Encode(file, pemBlock) if err != nil { return err } return nil } func loadPrivateKeyFromPEM(filename string) (*rsa.PrivateKey, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() pemData, err := ioutil.ReadAll(file) if err != nil { return nil, err } block, _ := pem.Decode(pemData) if block == nil { return nil, fmt.Errorf("failed to decode PEM block") } privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, err } return privateKey, nil } func savePublicKeyToPEM(publicKey *rsa.PublicKey, filename string) error { keyBytes, err := x509.MarshalPKIXPublicKey(publicKey) if err != nil { return err } pemBlock := &pem.Block{ Type: "PUBLIC KEY", Bytes: keyBytes, } file, err := os.Create(filename) if err != nil { return err } defer file.Close() err = pem.Encode(file, pemBlock) if err != nil { return err } return nil } func loadPublicKeyFromPEM(filename string) (*rsa.PublicKey, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() pemData, err := ioutil.ReadAll(file) if err != nil { return nil, err } block, _ := pem.Decode(pemData) if block == nil { return nil, fmt.Errorf("failed to decode PEM block") } publicKey, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } return publicKey.(*rsa.PublicKey), nil } func encryptSymmetricKey(publicKey *rsa.PublicKey, symmetricKey []byte) ([]byte, error) { encryptedKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, symmetricKey, nil) if err != nil { return nil, err } return encryptedKey, nil } func decryptSymmetricKey(privateKey *rsa.PrivateKey, encryptedKey []byte) ([]byte, error) { decryptedKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, encryptedKey, nil) if err != nil { return nil, err } return decryptedKey, nil } func encrypt(plaintext []byte, symmetricKey []byte) ([]byte, error) { block, err := aes.NewCipher(symmetricKey) if err != nil { return nil, err } paddedPlaintext := padPKCS7(plaintext, block.BlockSize()) ciphertext := make([]byte, len(paddedPlaintext)) mode := cipher.NewCBCEncrypter(block, symmetricKey[:block.BlockSize()]) mode.CryptBlocks(ciphertext, paddedPlaintext) return ciphertext, nil } func decrypt(ciphertext []byte, symmetricKey []byte) ([]byte, error) { block, err := aes.NewCipher(symmetricKey) if err != nil { return nil, err } plaintext := make([]byte, len(ciphertext)) mode := cipher.NewCBCDecrypter(block, symmetricKey[:block.BlockSize()]) mode.CryptBlocks(plaintext, ciphertext) unpaddedPlaintext := unpadPKCS7(plaintext) return unpaddedPlaintext, nil } func padPKCS7(data []byte, blockSize int) []byte { padding := blockSize - (len(data) % blockSize) pad := byte(padding) for i := 0; i < padding; i++ { data = append(data, pad) } return data } func unpadPKCS7(data []byte) []byte { padding := int(data[len(data)-1]) return data[:len(data)-padding] } func main() { // Generate RSA key pair privateKey, err := generateRSAKeyPair() if err != nil { fmt.Println("Key generation error:", err) return } // Save private key to PEM file err = savePrivateKeyToPEM(privateKey, "private.pem") if err != nil { fmt.Println("Private key saving error:", err) return } // Load private key from PEM file privateKey, err = loadPrivateKeyFromPEM("private.pem") if err != nil { fmt.Println("Private key loading error:", err) return } // Get the public key from the private key publicKey := privateKey.Public().(*rsa.PublicKey) // Save public key to PEM file err = savePublicKeyToPEM(publicKey, "public.pem") if err != nil { fmt.Println("Public key saving error:", err) return } // Load public key from PEM file publicKey, err = loadPublicKeyFromPEM("public.pem") if err != nil { fmt.Println("Public key loading error:", err) return } // Generate random symmetric key symmetricKey := make([]byte, 32) _, err = rand.Read(symmetricKey) if err != nil { fmt.Println("Symmetric key generation error:", err) return } // Encrypt the symmetric key using the public key encryptedKey, err := encryptSymmetricKey(publicKey, symmetricKey) if err != nil { fmt.Println("Key encryption error:", err) return } // Encrypt the plaintext using the symmetric key plaintext := []byte("Hello, world!") ciphertext, err := encrypt(plaintext, symmetricKey) if err != nil { fmt.Println("Encryption error:", err) return } fmt.Println("encrypted key: ", string(ciphertext)) // Decrypt the symmetric key using the private key decryptedKey, err := decryptSymmetricKey(privateKey, encryptedKey) if err != nil { fmt.Println("Key decryption error:", err) return } // Decrypt the ciphertext using the symmetric key decryptedPlaintext, err := decrypt(ciphertext, decryptedKey) if err != nil { fmt.Println("Decryption error:", err) return } fmt.Println("Decrypted plaintext:", string(decryptedPlaintext)) }