使用CTR模式进行解密

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

Decrypt using the CTR mode

问题

我正在尝试理解使用CTR模式的加密工作原理,所以我创建了这些函数来进行测试:

import (
    "crypto/cipher"
    "crypto/rand"
)

// generateIV 生成适用于加密的初始化向量(IV)。
//
// http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
func generateIV(bytes int) []byte {
    b := make([]byte, bytes)
    rand.Read(b)
    return b
}

func encrypt(block cipher.Block, value []byte) []byte {
    iv := generateIV(block.BlockSize())
    encrypted := make([]byte, len(value) + block.BlockSize())
    encrypted = append(encrypted, iv...)
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(encrypted, value)
    return encrypted
}

func decrypt(block cipher.Block, encrypted []byte) []byte {
    iv := encrypted[:block.BlockSize()]
    ciphertext := encrypted[block.BlockSize():]
    stream := cipher.NewCTR(block, iv)
    plain := make([]byte, len(ciphertext))
    // XORKeyStream 也用于解密吗?
    stream.XORKeyStream(plain, ciphertext)
    return plain
}

加密似乎工作正常,但是我不确定,因为我不理解解密的输出。我应该使用stream.XORKeyStream来解密吗?测试看起来像这样:

import (
    "crypto/aes"
    "fmt"
    "testing"
)

func TestEncryptCTR(t *testing.T) {
    block, err := aes.NewCipher([]byte("1234567890123456"))
    if err != nil {
        panic(err)
    }

    value := "foobarbaz"
    encrypted := encrypt(block, []byte(value))
    decrypted := decrypt(block, encrypted)
    fmt.Printf("--- %s ---", string(decrypted))
}

但是我明显没有得到“foobarbaz”。你能发现我做错了什么吗?

英文:

I'm trying to understand how encryption using the CTR mode works, so I created these functions to test it:

import (
    "crypto/cipher"
    "crypto/rand"
)

// generateIV generates an initialization vector (IV) suitable for encryption.
//
// http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
func generateIV(bytes int) []byte {
    b := make([]byte, bytes)
    rand.Read(b)
    return b
}

func encrypt(block cipher.Block, value []byte) []byte {
    iv := generateIV(block.BlockSize())
    encrypted := make([]byte, len(value) + block.BlockSize())
    encrypted = append(encrypted, iv...)
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(encrypted, value)
    return encrypted
}

func decrypt(block cipher.Block, encrypted []byte) []byte {
    iv := encrypted[:block.BlockSize()]
    ciphertext := encrypted[block.BlockSize():]
    stream := cipher.NewCTR(block, iv)
    plain := make([]byte, len(ciphertext))
    // XORKeyStream is used to decrypt too?
    stream.XORKeyStream(plain, ciphertext)
    return plain
}

Encryption seems to work fine, but well I don't know really because I don't understand the output of decryption. Should I use stream.XORKeyStream to decrypt too? The test looks like this:

import (
    "crypto/aes"
    "fmt"
    "testing"
)

func TestEncryptCTR(t *testing.T) {
    block, err := aes.NewCipher([]byte("1234567890123456"))
    if err != nil {
        panic(err)
    }

    value := "foobarbaz"
    encrypted := encrypt(block, []byte(value))
    decrypted := decrypt(block, encrypted)
    fmt.Printf("--- %s ---", string(decrypted))
}

But I'm definitely not getting "foobarbaz" back. Can you spot what I'm doing wrong?

答案1

得分: 2

问题是我在测试基础知识之前尝试做太多事情。我想在生成的密文之前添加IV,但当我这样做时,一切都被破坏了。这个简单版本没有添加IV,可以正常工作:

import (
    "crypto/cipher"
    "crypto/rand"
)

// generateIV 生成适用于加密的初始化向量(IV)。
//
// http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
func generateIV(bytes int) []byte {
    b := make([]byte, bytes)
    rand.Read(b)
    return b
}

func encrypt(block cipher.Block, value []byte, iv []byte) []byte {
    stream := cipher.NewCTR(block, iv)
    ciphertext := make([]byte, len(value))
    stream.XORKeyStream(ciphertext, value)
    return ciphertext
}

func decrypt(block cipher.Block, ciphertext []byte, iv []byte) []byte {
    stream := cipher.NewCTR(block, iv)
    plain := make([]byte, len(ciphertext))
    // XORKeyStream 也用于解密!
    stream.XORKeyStream(plain, ciphertext)
    return plain
}

相应的测试如下:

import (
    "crypto/aes"
    "fmt"
    "testing"
)

func TestEncryptCTR(t *testing.T) {
    block, err := aes.NewCipher([]byte("1234567890123456"))
    if err != nil {
        panic(err)
    }

    iv := generateIV(block.BlockSize())
    value := "foobarbaz"
    encrypted := encrypt2(block, []byte(value), iv)
    decrypted := decrypt2(block, encrypted, iv)
    fmt.Printf("--- %s ---", string(decrypted))
}

我得到了"--- foobarbaz ---",如预期。

现在回到让前置IV工作的问题上。 使用CTR模式进行解密

编辑 这就是它,带有自动生成和前置IV的版本:

func encrypt(block cipher.Block, value []byte) []byte {
    // 生成适用于加密的初始化向量(IV)。
    // http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
    iv := make([]byte, block.BlockSize())
    rand.Read(iv)
    // 加密。
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(value, value)
    // 返回iv + 密文。
    return append(iv, value...)
}

func decrypt(block cipher.Block, value []byte) []byte {
    if len(value) > block.BlockSize() {
        // 提取iv。
        iv := value[:block.BlockSize()]
        // 提取密文。
        value = value[block.BlockSize():]
        // 解密。
        stream := cipher.NewCTR(block, iv)
        stream.XORKeyStream(value, value)
        return value
    }
    return nil
}
英文:

The problem was me trying to do too much before testing the basics. I wanted to prepend the IV to the generated ciphertext, but somewhat I broke everything when I did that. This simple version, with no prepended IV, works:

import (
    "crypto/cipher"
    "crypto/rand"
)

// generateIV generates an initialization vector (IV) suitable for encryption.
//
// http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
func generateIV(bytes int) []byte {
    b := make([]byte, bytes)
    rand.Read(b)
    return b
}

func encrypt(block cipher.Block, value []byte, iv []byte) []byte {
    stream := cipher.NewCTR(block, iv)
    ciphertext := make([]byte, len(value))
    stream.XORKeyStream(ciphertext, value)
    return ciphertext
}

func decrypt(block cipher.Block, ciphertext []byte, iv []byte) []byte {
    stream := cipher.NewCTR(block, iv)
    plain := make([]byte, len(ciphertext))
    // XORKeyStream is used to decrypt too!
    stream.XORKeyStream(plain, ciphertext)
    return plain
}

And the corresponding test:

import (
    "crypto/aes"
    "fmt"
    "testing"
)

func TestEncryptCTR(t *testing.T) {
    block, err := aes.NewCipher([]byte("1234567890123456"))
    if err != nil {
        panic(err)
    }

    iv := generateIV(block.BlockSize())
    value := "foobarbaz"
    encrypted := encrypt2(block, []byte(value), iv)
    decrypted := decrypt2(block, encrypted, iv)
    fmt.Printf("--- %s ---", string(decrypted))
}

I get "--- foobarbaz ---", as expected.

Now back to make the prepending IV work. 使用CTR模式进行解密

Edit And this is it, with auto-generated and prepended IV:

func encrypt(block cipher.Block, value []byte) []byte {
    // Generate an initialization vector (IV) suitable for encryption.
    // http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29
    iv := make([]byte, block.BlockSize())
    rand.Read(iv)
    // Encrypt it.
    stream := cipher.NewCTR(block, iv)
    stream.XORKeyStream(value, value)
    // Return iv + ciphertext.
    return append(iv, value...)
}

func decrypt(block cipher.Block, value []byte) []byte {
    if len(value) > block.BlockSize() {
        // Extract iv.
        iv := value[:block.BlockSize()]
        // Extract ciphertext.
        value = value[block.BlockSize():]
        // Decrypt it.
        stream := cipher.NewCTR(block, iv)
        stream.XORKeyStream(value, value)
        return value
    }
    return nil
}

huangapple
  • 本文由 发表于 2011年9月1日 05:53:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/7263928.html
匿名

发表评论

匿名网友

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

确定