So as I went over how to do a simple hashing program I figured next I would utilize some more of they crypto libraries provided. In this case I used AES to write a simple encryption and decryption program. How this works is rather simple. We pass in two arguments. The first is the plaintext message you want to encrypt and the second is the key used to encrypt the file. A warning here is do not have a default key that is horribly insecure and users will many times use the default. We will now take the encryption key and initialization vector (iv) to encrypt the message. Another warning is here though the iv is not as important as the key make sure you use one and that it’s not something really simple like in the example. The iv you use for encryption must match also between the encryption and the decryption. For this example I use the CFB block mode. This allows for us to have plaintext of any length which makes this example more simple. After we encrypt the message I then decrypt it and print it out just to show you can. After that we encode the ciphertext (the encrypted text) in base64 so that you can copy and paste it into a decrypter. This way you don’t need to use a file to store the data in this example. Plus it shows you base64 which is fun tool for storing binary data in a human readable format.
package main import ( "fmt" "os" "crypto/aes" "crypto/cipher" "encoding/base64" ) var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f} func main() { // Load the plaintext message you want to encrypt. plaintext := []byte("hello, world") if len(os.Args) > 1 { plaintext = []byte(os.Args[1]) } // Setup a key that will encrypt the other text. key_text := "32o4908go293hohg98fh40gh" if len(os.Args) > 2 { key_text = os.Args[2] } // We chose our cipher type here in this case // we are using AES. c, err := aes.NewCipher([]byte(key_text)) if err != nil { fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err) os.Exit(-1) } // We use the CFBEncrypter in order to encrypt // the whole stream of plaintext using the // cipher setup with c and a iv. cfb := cipher.NewCFBEncrypter(c, commonIV) ciphertext := make([]byte, len(plaintext)) cfb.XORKeyStream(ciphertext, plaintext) fmt.Printf("%s=>%x\n", plaintext, ciphertext) // We decrypt it here just for the purpose of // showing the fact that it is decryptable. cfbdec := cipher.NewCFBDecrypter(c, commonIV) plaintextCopy := make([]byte, len(plaintext)) cfbdec.XORKeyStream(plaintextCopy, ciphertext) fmt.Printf("%x=>%s\n",ciphertext, plaintextCopy) // We must now convert the ciphertext to base64 // this will allow for the encrypted data to be // visible to copy and paste into the decrypter. base64Text := make ([]byte, base64.StdEncoding.EncodedLen(len(ciphertext))) base64.StdEncoding.Encode(base64Text, []byte(ciphertext)) fmt.Printf("base64: %s\n", base64Text) }
Next we have the decryption program. This program is setup pretty much the same as the encryption one except it takes in the base64 ciphertext and the key. The first thing we then have to do is decode the ciphertext form base64 into the normal binary format that we can decrypt. You will notice here that the iv matches the same as in the encryption program.
package main import ( "fmt" "os" "crypto/aes" "crypto/cipher" "encoding/base64" ) var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f} var ciphertext []byte func main() { // Load the base64 ciphertext from the arguement. if len(os.Args) > 1 { // Decode the ciphertext to put it in a usable binary format. dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(os.Args[1]))) base64.StdEncoding.Decode(dbuf, []byte(os.Args[1])) ciphertext = []byte(dbuf) } else { fmt.Printf("Error: At least one argument required!") os.Exit(-1) } // Load the key from the second argument. key_text := "32o4908go293hohg98fh40gh" if len(os.Args) > 2 { key_text = os.Args[2] } // We chose our cipher type here in this case // we are using AES. c, err := aes.NewCipher([]byte(key_text)); if err != nil { fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err) os.Exit(-1) } // We use the CFBDecrypter in order to decrypt // the whole stream of ciphertext using the // cipher setup with c and a iv. cfb := cipher.NewCFBDecrypter(c, commonIV) plaintext := make([]byte, len(ciphertext)) cfb.XORKeyStream(plaintext, ciphertext) // We then print out the resulting text. fmt.Printf("%x=>%s\n",ciphertext, plaintext) }
Well I hope this gives people a good example of how to do encryption with go. I felt the need to write this because I could not find a article anywhere on this topic. Most of the examples I used to come up with this were from the cfb_test.go testing code that comes in the source code. These test files have some good examples for using the code if your not afraid of poking around the code base. I also hope this might help people understand some more of the basics of encryption which can come in handy with any application you develop. One last word of warning though this code is in no way ready to be used with actual data and keep it safe. If you want to do that you should probably read up some more on encryption as using encryption without understanding the proper uses of it is not much better then not using it at all.