Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang AES StreamReader encryption - Example omits any authentication of the encrypted data

Finally I am posting my first question on StackOverflow. I'm using this site for years now and I always found great answers to all my questions :)

I am implementing a file encryption background daemon which is based on the official Golang cipher example:

func ExampleStreamReader() {
    key := []byte("example key 1234")

    inFile, err := os.Open("encrypted-file")
    if err != nil {
        panic(err)
    }
    defer inFile.Close()

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    // If the key is unique for each ciphertext, then it's ok to use a zero
    // IV.
    var iv [aes.BlockSize]byte
    stream := cipher.NewOFB(block, iv[:])

    outFile, err := os.OpenFile("decrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        panic(err)
    }
    defer outFile.Close()

    reader := &cipher.StreamReader{S: stream, R: inFile}
    // Copy the input file to the output file, decrypting as we go.
    if _, err := io.Copy(outFile, reader); err != nil {
        panic(err)
    }

    // Note that this example is simplistic in that it omits any
    // authentication of the encrypted data. If you were actually to use
    // StreamReader in this manner, an attacker could flip arbitrary bits in
    // the output.
}

func ExampleStreamWriter() {
    key := []byte("example key 1234")

    inFile, err := os.Open("plaintext-file")
    if err != nil {
        panic(err)
    }
    defer inFile.Close()

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    // If the key is unique for each ciphertext, then it's ok to use a zero
    // IV.
    var iv [aes.BlockSize]byte
    stream := cipher.NewOFB(block, iv[:])

    outFile, err := os.OpenFile("encrypted-file", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        panic(err)
    }
    defer outFile.Close()

    writer := &cipher.StreamWriter{S: stream, W: outFile}
    // Copy the input file to the output file, encrypting as we go.
    if _, err := io.Copy(writer, inFile); err != nil {
        panic(err)
    }

    // Note that this example is simplistic in that it omits any
    // authentication of the encrypted data. If you were actually to use
    // StreamReader in this manner, an attacker could flip arbitrary bits in
    // the decrypted result.
}

What is meant with the following quote. About what should I take care to provide a secure encryption and decryption?

Note that this example is simplistic in that it omits any authentication of the encrypted data. If you were actually to use StreamReader in this manner, an attacker could flip arbitrary bits in the output.

Thanks!

like image 974
M4ng0Squ4sh Avatar asked May 09 '15 09:05

M4ng0Squ4sh


1 Answers

From wikipedia:

The block cipher modes ECB, CBC, OFB, CFB, CTR, and XTS provide confidentiality, but they do not protect against accidental modification or malicious tampering.

A good explanation can be found here: https://security.stackexchange.com/a/33576.

Go has support for other modes which do support integrity and authentication checks. As rossum said you can use GCM or CCM. You can find lots of examples on godoc.org. For example HashiCorp's memberlist library.

Another library worth checking out is the NaCL port in golang.org/x/crypto/nacl:

func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool)
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte

If you're working with small messages this API will probably be a lot easier to use.

like image 118
Caleb Avatar answered Oct 15 '22 05:10

Caleb