Mengenal Asymmetric Encryption: Keamanan Data Tingkat Tinggi dengan Golang
Tags: go, programming, tutorial, learning
Published: 2024-07-02 01:17:55


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2c6tdxpib3sz1rt1ok16.png)


### Apa Itu Asymmetric Encryption?

Asymmetric encryption adalah metode enkripsi yang menggunakan dua kunci berbeda: public key (kunci publik) dan private key (kunci privat). Berbeda dengan metode [Symmetric Encryption](https://yogameleniawan.com/learning-media/implementasi-metode-standard-symmetric-encryption-signature-pada-golang-2m5m) kalau asymmetric encryption itu kunci publik digunakan untuk mengenkripsi data, sementara kunci privat digunakan untuk mendekripsi data. Karena karakteristik ini, asymmetric encryption sangat berguna dalam berbagai situasi yang membutuhkan keamanan tinggi dan otentikasi. Berikut beberapa contoh penggunaan dan penjelasan detail kapan menggunakan asymmetric encryption:

1. Mengamankan Transaksi Online
Dalam transaksi online, seperti pembelian di e-commerce atau perbankan online, asymmetric encryption digunakan untuk memastikan bahwa informasi sensitif, seperti nomor kartu kredit atau informasi pribadi, dikirim dengan aman dari pengguna ke server.
Prosesnya yaitu pengguna mengenkripsi informasi sensitif menggunakan public key yang disediakan oleh server. Hanya server yang memiliki private key yang dapat mendekripsi informasi tersebut, sehingga menjaga data tetap aman selama pengiriman.

2. Sistem Otentikasi dan Login
Asymmetric encryption digunakan dalam protokol otentikasi untuk memastikan identitas pengguna. Contohnya adalah penggunaan sertifikat digital dan SSL/TLS dalam HTTPS.
Prosesnya ketika pengguna mencoba login, server mengirimkan sebuah challenge yang dienkripsi dengan public key pengguna. Pengguna kemudian mendekripsi challenge ini dengan private key mereka dan mengirimkan kembali ke server, membuktikan identitas mereka.

### Apa keuntungan dan kekurangan pakai Asymmetric Encryption?

#### Keuntungan Menggunakan Asymmetric Encryption

- Keamanan Tinggi: Dengan menggunakan dua kunci berbeda, risiko bocornya kunci enkripsi berkurang.
- Otentikasi: Dapat digunakan untuk memastikan identitas pengirim dan penerima data.
- Distribusi Kunci yang Aman: Public key dapat didistribusikan secara bebas tanpa mengurangi keamanan.

#### Kekurangan Menggunakan Asymmetric Encryption

- Kecepatan: Asymmetric encryption lebih lambat dibandingkan symmetric encryption karena proses enkripsi dan dekripsinya lebih kompleks.
- Ukuran Kunci: Kunci yang digunakan dalam asymmetric encryption biasanya lebih panjang, sehingga membutuhkan lebih banyak ruang penyimpanan dan bandwidth.

---

### Contoh Penggunaan Asymmetric Encryption di Golang
Sekarang kita lihat gimana cara pakai asymmetric encryption dan digital signature di Golang.

#### Generate RSA Key di Golang

```go
package main

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

func generateKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return nil, nil, err
	}
	return privateKey, &privateKey.PublicKey, nil
}

func savePEMKey(fileName string, key *rsa.PrivateKey) error {
	outFile, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer outFile.Close()

	privateKeyPEM := pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(key),
	}
	return pem.Encode(outFile, &privateKeyPEM)
}

func savePublicPEMKey(fileName string, pubkey *rsa.PublicKey) error {
	asn1Bytes, err := x509.MarshalPKIXPublicKey(pubkey)
	if err != nil {
		return err
	}

	publicKeyPEM := pem.Block{
		Type:  "RSA PUBLIC KEY",
		Bytes: asn1Bytes,
	}
	outFile, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer outFile.Close()
	return pem.Encode(outFile, &publicKeyPEM)
}

func main() {
	privateKey, publicKey, err := generateKeyPair(2048)
	if err != nil {
		fmt.Println("Error generating keys:", err)
		return
	}

	err = savePEMKey("private_key.pem", privateKey)
	if err != nil {
		fmt.Println("Error saving private key:", err)
		return
	}

	err = savePublicPEMKey("public_key.pem", publicKey)
	if err != nil {
		fmt.Println("Error saving public key:", err)
		return
	}

	fmt.Println("Keys generated and saved successfully!")
}

```

#### Enkripsi dan Dekripsi dengan RSA di Golang

```go
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
)

func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
	privKeyFile, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer privKeyFile.Close()

	pemFileInfo, _ := privKeyFile.Stat()
	var size = pemFileInfo.Size()
	pemBytes := make([]byte, size)

	buffer := bufio.NewReader(privKeyFile)
	_, err = buffer.Read(pemBytes)
	if err != nil {
		return nil, err
	}

	data, _ := pem.Decode(pemBytes)
	privateKeyImported, err := x509.ParsePKCS1PrivateKey(data.Bytes)
	if err != nil {
		return nil, err
	}

	return privateKeyImported, nil
}

func loadPublicKey(path string) (*rsa.PublicKey, error) {
	pubKeyFile, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer pubKeyFile.Close()

	pemFileInfo, _ := pubKeyFile.Stat()
	var size = pemFileInfo.Size()
	pemBytes := make([]byte, size)

	buffer := bufio.NewReader(pubKeyFile)
	_, err = buffer.Read(pemBytes)
	if err != nil {
		return nil, err
	}

	data, _ := pem.Decode(pemBytes)
	publicKeyImported, err := x509.ParsePKIXPublicKey(data.Bytes)
	if err != nil {
		return nil, err
	}

	pubKey, ok := publicKeyImported.(*rsa.PublicKey)
	if !ok {
		return nil, fmt.Errorf("error parsing public key")
	}

	return pubKey, nil
}

func encryptMessage(pub *rsa.PublicKey, msg []byte) ([]byte, error) {
	ciphertext, err := rsa.EncryptOAEP(
		sha256.New(),
		rand.Reader,
		pub,
		msg,
		nil)
	if err != nil {
		return nil, err
	}
	return ciphertext, nil
}

func decryptMessage(priv *rsa.PrivateKey, ciphertext []byte) ([]byte, error) {
	plaintext, err := rsa.DecryptOAEP(
		sha256.New(),
		rand.Reader,
		priv,
		ciphertext,
		nil)
	if err != nil {
		return nil, err
	}
	return plaintext, nil
}

func main() {
	privateKey, err := loadPrivateKey("private_key.pem")
	if err != nil {
		fmt.Println("Error loading private key:", err)
		return
	}

	publicKey, err := loadPublicKey("public_key.pem")
	if err != nil {
		fmt.Println("Error loading public key:", err)
		return
	}

	message := []byte("Hello, world!")
	ciphertext, err := encryptMessage(publicKey, message)
	if err != nil {
		fmt.Println("Error encrypting message:", err)
		return
	}
	fmt.Printf("Encrypted message: %x\n", ciphertext)

	plaintext, err := decryptMessage(privateKey, ciphertext)
	if err != nil {
		fmt.Println("Error decrypting message:", err)
		return
	}
	fmt.Printf("Decrypted message: %s\n", plaintext)
}

```

#### Tanda Tangan Digital (Signature) di Golang

```go
package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
)

func signMessage(priv *rsa.PrivateKey, msg []byte) ([]byte, error) {
	hash := sha256.New()
	hash.Write(msg)
	hashed := hash.Sum(nil)

	signature, err := rsa.SignPSS(
		rand.Reader,
		priv,
		crypto.SHA256,
		hashed,
		nil,
	)
	if err != nil {
		return nil, err
	}

	return signature, nil
}

func verifyMessage(pub *rsa.PublicKey, msg, sig []byte) error {
	hash := sha256.New()
	hash.Write(msg)
	hashed := hash.Sum(nil)

	err := rsa.VerifyPSS(
		pub,
		crypto.SHA256,
		hashed,
		sig,
		nil,
	)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	privateKey, err := loadPrivateKey("private_key.pem")
	if err != nil {
		fmt.Println("Error loading private key:", err)
		return
	}

	publicKey, err := loadPublicKey("public_key.pem")
	if err != nil {
		fmt.Println("Error loading public key:", err)
		return
	}

	message := []byte("This is a signed message.")
	signature, err := signMessage(privateKey, message)
	if err != nil {
		fmt.Println("Error signing message:", err)
		return
	}
	fmt.Printf("Signature: %x\n", signature)

	err = verifyMessage(publicKey, message, signature)
	if err != nil {
		fmt.Println("Error verifying message:", err)
		return
	}
	fmt.Println("Message verified successfully!")
}
```

### Kesimpulan
Dengan menggunakan asymmetric encryption, teman-teman bisa mengenkripsi data dengan public key dan mendekripsinya dengan private key. Selain itu, teman-teman juga bisa menandatangani pesan dengan private key dan memverifikasinya dengan public key. Metode ini memberikan tingkat keamanan yang tinggi dan memastikan integritas serta keaslian data yang dikirim atau diterima. Jadi, pastikan teman-teman menggunakan metode ini untuk keperluan yang membutuhkan keamanan tinggi!