Asymmetric cryptography, also known as public-key cryptography, is a cryptographic system where the key used to encrypt data is different from the key used to decrypt it. This allows for secure communication between parties even without a shared secret key. In this article, we will explore how to implement asymmetric cryptography using the Go programming language.
Generating Key Pairs
The first step in implementing asymmetric cryptography is to generate a key pair. The key pair consists of a public key and a private key. The public key can be freely shared with anyone, whereas the private key must be kept secret.
Go's standard library provides the crypto/rand
and crypto/rsa
packages for generating cryptographically secure random numbers and generating RSA key pairs, respectively. Here's an example of how to generate a 2048-bit RSA key pair:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
func main() {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
publicKey := &privateKey.PublicKey
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
})
err = os.WriteFile("private.pem", privateKeyPEM, 0644)
if err != nil {
panic(err)
}
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
panic(err)
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: publicKeyBytes,
})
err = os.WriteFile("public.pem", publicKeyPEM, 0644)
if err != nil {
panic(err)
}
}
In this example, we use the rsa.GenerateKey
function to generate a 2048-bit RSA key pair. We then use the x509.MarshalPKCS1PrivateKey
and x509.MarshalPKIXPublicKey
functions to marshal the private and public keys into their respective PEM-encoded formats. Finally, we write the PEM-encoded keys to disk.
Encrypting and Decrypting Data
With a key pair generated, we can now encrypt and decrypt data using the public and private keys, respectively. To encrypt data with the public key, we can use the crypto/x509
package's EncryptPKCS1v15
function:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
)
func main() {
publicKeyPEM, err := ioutil.ReadFile("public.pem")
if err != nil {
panic(err)
}
publicKeyBlock, _ := pem.Decode(publicKeyPEM)
publicKey, err := x509.ParsePKIXPublicKey(publicKeyBlock.Bytes)
if err != nil {
panic(err)
}
plaintext := []byte("hello, world!")
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey.(*rsa.PublicKey), plaintext)
if err != nil {
panic(err)
}
fmt.Printf("Encrypted: %x\n", ciphertext)
}
In this example, we first read in the PEM-encoded public key from the public.pem
file. We then decode the PEM block and parse the public key using the x509.ParsePKIXPublicKey
function. Finally, we use the rsa.EncryptPKCS1v15
function to encrypt the plaintext message using the public key.
To decrypt data with the private key, we can use the crypto/rsa
package's DecryptPKCS1v15
function:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
)
func main() {
privateKeyPEM, err := ioutil.ReadFile("private.pem")
if err != nil {
panic(err)
}
privateKeyBlock, _ := pem.Decode(privateKeyPEM)
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if err != nil {
panic(err)
}
ciphertext := []byte{0x88, 0xaa, 0x63, 0x24, 0x2d, 0x48, 0xfd, 0xb1, 0x63, 0x71, 0x33, 0x17, 0x2a, 0x01, 0xce, 0x15, 0x1b, 0x25, 0xac, 0xcd, 0x35, 0xc1, 0x7c, 0x2a, 0x48, 0x58, 0x79, 0xae, 0x73, 0xf3, 0x5e, 0xc9, 0x89, 0xa7, 0x8a, 0x92, 0xa4, 0x3f, 0x3d, 0xb3, 0x43, 0x1d, 0x01, 0x74, 0xee, 0xd1, 0x1e, 0x95, 0x2b, 0x4f, 0x42, 0x46, 0x0b}
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, ciphertext)
if err != nil {
panic(err)
}
fmt.Printf("Decrypted: %s\n", plaintext)
}
In this example, we first read in the PEM-encoded private key from the private.pem
file. We then decode the PEM block and parse the private key using the x509.ParsePKCS1PrivateKey
function. Finally, we use the rsa.DecryptPKCS1v15
function to decrypt the ciphertext message using the private key.
Conclusion
In this article, we have explored how to implement asymmetric cryptography using the Go programming language. We have shown how to generate an RSA key pair, encrypt and decrypt data using the public and private keys, respectively. With this knowledge, you can now implement secure communication between parties even without a shared secret key.
Top comments (0)