Category Archives: Go

Go Post #2: AES Encryption

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.

Advertisement

Go Post #1: Simple Hashing

Ok so most people start learning a new language with hello world but that is just too simple to show off a new language. So instead of hello world I am going to post the first program I tried to write in go (of course after hello world). It was just a very simple hashing program which you pass in a string when you run the program and then you get back the string and what the hashed version of that string looks like.

package main

import(
    "fmt"
    "flag" // command line option parser
    "crypto/sha256"
    "hash"
)

var plaintext string

func main() {
    flag.Parse() // Scans the arg list and sets up flags
    if flag.NArg() > 0 {
        plaintext = flag.Arg(0)
    }

    h := sha256.New()  // h is a hash.Hash
    h.Write([]byte(plaintext))

    fmt.Printf("%s: %x\n", plaintext, h.Sum())
}

So lets looks at what exactly is going on in the example code. First you will notice import this is used just like in pretty much every other language and tells the compiler what libraries you want to include. Now if you don’t want sha256 hash you can change the import line that calls for crypto/sha256 with a different hashing algorithm. I was very happy at the selection of hashing algroithms you can chose from (md4, md5, sha1, sha256, sha384, sha512, md5sha1, ripemd160) basically to change the hash you use just change the import and later change the has you create.

Next in the code you see a variable definition it shows just a simple declaration of a string. It’s a bit different then most lanuagues but nothing to strange. After that you get to the real meat. The main function. Unlike your traditional C program I used the flag library in go which allos you to parse a list of flags (not shown here) as well is iterate through parameters. The if statement merely checks how many arguments were passes and if there is more then one it grabs the first one and sets it to the plaintext.

The last section is where the main work happens. I used go’s handy feature where you can define a variable when you first create it to create h which is the hash. The declaration happens with the := assignment. This is also the line that you chose your hashing algorithm. It should match whatever one you chose to import. In the next line I write the content of the plaintext into the hashing algorithm and you see how simple it is to cast a string into the byte array.

To finish it all off the last statement sums the hash and prints it out to the console. It’s that simple. Now at this point there are a few notes I would like to make. First, notice the lack of semicolons.  Yes, this language does have them but the only spot they are needed is in for loops and if you want multiple statements per line. Second, notice the bracing format. While I truly dislike the one true brace style its forced by the language and I have accepted it since Go provides so many neat features.

Well there you go that’s how you do a simple hash in Go and some of the language basics. Now since someone will complain if I don’t here is a more simple version of the hashing program using hello world.

package main

import (
“fmt”
“os”
“crypto/sha256″
)

func main() {
plaintext := “hello, world”
if len(os.Args) > 1 {
plaintext = os.Args[1]
}
h := sha256.New() // h is a hash.Hash
h.Write([]byte(plaintext))
fmt.Printf(“%s\n%x\n”, plaintext, h.Sum())
}

UPDATE: Added code from comments to replace hello world. (May come back and rework this article)