Golang AES StreamReader加密 – 示例省略了对加密数据的任何身份验证。

huangapple go评论83阅读模式
英文:

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

问题

终于我在StackOverflow上发布了我的第一个问题。我现在已经使用这个网站好几年了,我总是能找到对我所有问题的很好的答案 Golang AES StreamReader加密 – 示例省略了对加密数据的任何身份验证。

我正在实现一个基于官方的Golang密码示例的文件加密后台守护进程:

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)
    }

    // 如果每个密文的密钥都是唯一的,那么使用零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}
    // 在复制的同时进行解密,将输入文件复制到输出文件。
    if _, err := io.Copy(outFile, reader); err != nil {
        panic(err)
    }

    // 请注意,这个示例很简单,它省略了对加密数据的任何认证。如果你实际上以这种方式使用StreamReader,攻击者可以在输出中翻转任意位。
}

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)
    }

    // 如果每个密文的密钥都是唯一的,那么使用零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}
    // 在复制的同时进行加密,将输入文件复制到输出文件。
    if _, err := io.Copy(writer, inFile); err != nil {
        panic(err)
    }

    // 请注意,这个示例很简单,它省略了对加密数据的任何认证。如果你实际上以这种方式使用StreamReader,攻击者可以在解密结果中翻转任意位。
}

以下引用的意思是什么?在提供安全的加密和解密时,我应该注意什么?

请注意,这个示例很简单,它省略了对加密数据的任何认证。如果你实际上以这种方式使用StreamReader,攻击者可以在输出中翻转任意位。

谢谢!

英文:

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 Golang AES StreamReader加密 – 示例省略了对加密数据的任何身份验证。

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!

答案1

得分: 4

从维基百科上可以找到以下解释:

电子密码本模式(ECB)、密码分组链接模式(CBC)、输出反馈模式(OFB)、密码反馈模式(CFB)、计数器模式(CTR)和XTS模式提供了机密性,但它们不能防止意外修改或恶意篡改。

在这里可以找到一个很好的解释:https://security.stackexchange.com/a/33576。

Go语言支持其他支持完整性和认证检查的模式。正如rossum所说,你可以使用GCMCCM。你可以在godoc.org上找到很多示例。例如,HashiCorp的memberlist库

另一个值得注意的库是golang.org/x/crypto/nacl中的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

如果你处理的是小消息,这个API可能会更容易使用。

英文:

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.

huangapple
  • 本文由 发表于 2015年5月9日 17:52:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/30138477.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定