(Go) Encrypting / decrypting string results in lost characters

Issue

I am attempting to encrypt sensitive data before storing it. First, I generate a key to be used for the encryption process:

import (
    "crypto/aes"
    CR "crypto/rand"
    "encoding/hex"
    "errors"
    "log"
    "os"
)

// []byte key used to encrypt tokens before saving to local file system
var key = make([]byte, 32)

func createKey(key *[]byte) {
    _, err = CR.Read(*key)
    if err != nil {
        log.Println("Error creating key from crypto/rand package:", err)
    }
}

Next I create functions that encrypt and decrypt a string respectively:

func encryptToken(t token) string {
    original := t.ID // ID is string member of token

    cipher, err := aes.NewCipher(key)
    if err != nil {
        log.Println("Error creating cipher during encrypt:", err)
    }

    out := make([]byte, len(original))
    cipher.Encrypt(out, []byte(original))

    return hex.EncodeToString(out) // this will be written to a csv file 

    // appears in file as: cec35df876e1b77diefg9023366c5f2f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
}

func decryptToken(s string) string {
    ciphertext, err := hex.DecodeString(s) // s is read from csv file
    if err != nil {
        log.Println("Error decoding string from hex:", err)
    }

    cipher, err := aes.NewCipher(key)
    if err != nil {
        log.Println("Error creating cipher during decrypt:", err)
    }

    original := make([]byte, len(ciphertext))
    cipher.Decrypt(original, ciphertext)

    originalAsString := string(original[:])

    return originalAsString  // returns: 6f928e728f485403

    // original token was: 6f928e728f485403e254049f684ea5ec853adcfa9553cdfc956fr45671447c57
}

Considering that encryptToken() returns a hex string with so many zeros, I am certain this is where my problem is. I’ve experimented adjusting the length of key, but using a value other than 32 in var key = make([]byte, 32) will result in a panic involving invalid memory address or nil pointer dereference. Why is this?

Solution

The shortest answer is probably: As @GradyPlayer suggested, you’re using your cipher the wrong way. You have to hand it over to an encrypter instead which applies it to all the bytes. The pattern looks like that:

ciphertext = make([]byte, len(plaintext))
cbc := cipher.NewCBCEncrypter(cipher, iv)
cbc.CryptBlocks(ciphertext, plaintext)

That said, here you would still have to put the initialization vector in front of the ciphertext (that’s a usual place to put it at least, and the decrypter might expect it to be located here), and you still have to think about padding (if you’re using CBC as I did).

So while it’s not directly addressing the question, I think it would help you do get more code for a better understanding. Here is a gist I’ve just created. Disclaimer: I mostly assembled code fragments from other places. So I merely put the pieces together you can see here, and gained some understanding on the road.

Answered By – NotX

Answer Checked By – Jay B. (GoLangFix Admin)

Leave a Reply

Your email address will not be published.