Public key encryption

Public key encryption and decryption requires two keys: one to encrypt and a second one to decrypt. The encryption key is usually made public in some way so that anyone can encrypt messages to you. The decryption key must stay private, otherwise everyone would be able to decrypt those messages! Public key systems are asymmetric, with different keys for different uses.

There are many public key encryption systems supported by Go. A typical one is the RSA scheme.

A program generating RSA private and public keys is

  1. /* GenRSAKeys
  2. */
  3. package main
  4. import (
  5. "crypto/rand"
  6. "crypto/rsa"
  7. "crypto/x509"
  8. "encoding/gob"
  9. "encoding/pem"
  10. "fmt"
  11. "os"
  12. )
  13. func main() {
  14. reader := rand.Reader
  15. bitSize := 512
  16. key, err := rsa.GenerateKey(reader, bitSize)
  17. checkError(err)
  18. fmt.Println("Private key primes", key.Primes[0].String(), key.Primes[1].String())
  19. fmt.Println("Private key exponent", key.D.String())
  20. publicKey := key.PublicKey
  21. fmt.Println("Public key modulus", publicKey.N.String())
  22. fmt.Println("Public key exponent", publicKey.E)
  23. saveGobKey("private.key", key)
  24. saveGobKey("public.key", publicKey)
  25. savePEMKey("private.pem", key)
  26. }
  27. func saveGobKey(fileName string, key interface{}) {
  28. outFile, err := os.Create(fileName)
  29. checkError(err)
  30. encoder := gob.NewEncoder(outFile)
  31. err = encoder.Encode(key)
  32. checkError(err)
  33. outFile.Close()
  34. }
  35. func savePEMKey(fileName string, key *rsa.PrivateKey) {
  36. outFile, err := os.Create(fileName)
  37. checkError(err)
  38. var privateKey = &pem.Block{Type: "RSA PRIVATE KEY",
  39. Bytes: x509.MarshalPKCS1PrivateKey(key)}
  40. pem.Encode(outFile, privateKey)
  41. outFile.Close()
  42. }
  43. func checkError(err error) {
  44. if err != nil {
  45. fmt.Println("Fatal error ", err.Error())
  46. os.Exit(1)
  47. }
  48. }

The program also saves the certificates using gob serialisation. They can be read back by this program:

  1. /* LoadRSAKeys
  2. */
  3. package main
  4. import (
  5. "crypto/rsa"
  6. "encoding/gob"
  7. "fmt"
  8. "os"
  9. )
  10. func main() {
  11. var key rsa.PrivateKey
  12. loadKey("private.key", &key)
  13. fmt.Println("Private key primes", key.Primes[0].String(), key.Primes[1].String())
  14. fmt.Println("Private key exponent", key.D.String())
  15. var publicKey rsa.PublicKey
  16. loadKey("public.key", &publicKey)
  17. fmt.Println("Public key modulus", publicKey.N.String())
  18. fmt.Println("Public key exponent", publicKey.E)
  19. }
  20. func loadKey(fileName string, key interface{}) {
  21. inFile, err := os.Open(fileName)
  22. checkError(err)
  23. decoder := gob.NewDecoder(inFile)
  24. err = decoder.Decode(key)
  25. checkError(err)
  26. inFile.Close()
  27. }
  28. func checkError(err error) {
  29. if err != nil {
  30. fmt.Println("Fatal error ", err.Error())
  31. os.Exit(1)
  32. }
  33. }