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

M4n*_*4sh 6 encryption aes go encryption-symmetric

最后,我在StackOverflow上发布了我的第一个问题.我现在使用这个网站多年了,我总能找到所有问题的答案:)

我正在实现一个基于官方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)
    }

    // 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.
}
Run Code Online (Sandbox Code Playgroud)

以下引用是什么意思?关于我应该注意什么才能提供安全的加密和解密?

请注意,此示例过于简单,因为它省略了对加密数据的任何身份验证.如果你实际上以这种方式使用StreamReader,攻击者可以在输出中翻转任意位.

谢谢!

Cal*_*leb 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
Run Code Online (Sandbox Code Playgroud)

如果您正在处理小消息,这个 API 可能会更容易使用。