Golang AES ECB加密

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

Golang AES ECB Encryption

问题

尝试在Go中模拟一种基本上是AES ECB模式加密的算法。

以下是我目前的代码:

  1. func Decrypt(data []byte) []byte {
  2. cipher, err := aes.NewCipher([]byte(KEY))
  3. if err == nil {
  4. cipher.Decrypt(data, PKCS5Pad(data))
  5. return data
  6. }
  7. return nil
  8. }

我还有一个经过测试和工作正常的PKCS5Padding算法,它首先对数据进行填充。我找不到关于如何在Go的AES包中切换加密模式的任何信息(在文档中肯定没有)。

我在另一种语言中有这段代码,这就是我知道这个算法不完全正确的原因。

编辑:以下是我从问题页面解释的方法:

  1. func AESECB(ciphertext []byte) []byte {
  2. cipher, _ := aes.NewCipher([]byte(KEY))
  3. fmt.Println("AESing the data")
  4. bs := 16
  5. if len(ciphertext)%bs != 0 {
  6. panic("Need a multiple of the blocksize")
  7. }
  8. plaintext := make([]byte, len(ciphertext))
  9. for len(plaintext) > 0 {
  10. cipher.Decrypt(plaintext, ciphertext)
  11. plaintext = plaintext[bs:]
  12. ciphertext = ciphertext[bs:]
  13. }
  14. return plaintext
  15. }

实际上,这并没有返回任何数据,也许在从加密改为解密时我搞错了什么。

英文:

Trying to emulate an algorithm in Go that is basically AES ECB Mode encryption.

Here's what I have so far

  1. func Decrypt(data []byte) []byte {
  2. cipher, err := aes.NewCipher([]byte(KEY))
  3. if err == nil {
  4. cipher.Decrypt(data, PKCS5Pad(data))
  5. return data
  6. }
  7. return nil
  8. }

I also have a PKCS5Padding algorithm, which is tested and working, which pads the data first. I cant find any information on how to switch the encryption mode in the Go AES package (it's definitely not in the docs).

I have this code in another language, which is how I know this algorithm isn't working quite correctly.

EDIT: Here is the method as I have interpreted from on the issue page

  1. func AESECB(ciphertext []byte) []byte {
  2. cipher, _ := aes.NewCipher([]byte(KEY))
  3. fmt.Println("AESing the data")
  4. bs := 16
  5. if len(ciphertext)%bs != 0 {
  6. panic("Need a multiple of the blocksize")
  7. }
  8. plaintext := make([]byte, len(ciphertext))
  9. for len(plaintext) > 0 {
  10. cipher.Decrypt(plaintext, ciphertext)
  11. plaintext = plaintext[bs:]
  12. ciphertext = ciphertext[bs:]
  13. }
  14. return plaintext
  15. }

This is actually not returning any data, maybe I screwed something up when changing it from encripting to decripting

答案1

得分: 10

电子密码本(ECB)是一种非常直接的操作模式。要加密的数据被分成具有相同大小的字节块。对于每个块,应用一个密码算法,例如AES,生成加密的块。

下面的代码片段解密了ECB中的AES-128数据(请注意,块大小为16字节):

  1. package main
  2. import (
  3. "crypto/aes"
  4. )
  5. func DecryptAes128Ecb(data, key []byte) []byte {
  6. cipher, _ := aes.NewCipher([]byte(key))
  7. decrypted := make([]byte, len(data))
  8. size := 16
  9. for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
  10. cipher.Decrypt(decrypted[bs:be], data[bs:be])
  11. }
  12. return decrypted
  13. }

正如@OneOfOne所提到的,ECB是不安全的,并且非常容易检测,因为重复的块将始终加密为相同的加密块。这个Crypto SE答案给出了一个非常好的解释。

英文:

Electronic codebook ("ECB") is a very straightforward mode of operation. The data to be encrypted is divided into byte blocks, all having the same size. For each block, a cipher is applied, in this case AES, generating the encrypted block.

The code snippet below decrypts AES-128 data in ECB (note that the block size is 16 bytes):

  1. package main
  2. import (
  3. &quot;crypto/aes&quot;
  4. )
  5. func DecryptAes128Ecb(data, key []byte) []byte {
  6. cipher, _ := aes.NewCipher([]byte(key))
  7. decrypted := make([]byte, len(data))
  8. size := 16
  9. for bs, be := 0, size; bs &lt; len(data); bs, be = bs+size, be+size {
  10. cipher.Decrypt(decrypted[bs:be], data[bs:be])
  11. }
  12. return decrypted
  13. }

As mentioned by @OneOfOne, ECB is insecure and very easy to detect, as repeated blocks will always encrypt to the same encrypted blocks. This Crypto SE answer gives a very good explanation why.

答案2

得分: 7

为什么?我们有意将ECB排除在外:它是不安全的,而且如果需要的话,实现起来非常简单。

https://github.com/golang/go/issues/5597

英文:

> Why? We left ECB out intentionally: it's insecure, and if needed it's
trivial to implement.

https://github.com/golang/go/issues/5597

答案3

得分: 4

我使用了你的代码,所以我觉得有必要向你展示我是如何修复它的。

我正在使用Go语言完成这个问题的密码朋克挑战

我将为你解释错误,因为代码大部分是正确的。

  1. for len(plaintext) > 0 {
  2. cipher.Decrypt(plaintext, ciphertext)
  3. plaintext = plaintext[bs:]
  4. ciphertext = ciphertext[bs:]
  5. }

这个循环确实解密了数据,但没有将其放在任何地方。它只是简单地将这两个数组向前移动,没有产生任何输出。

  1. i := 0
  2. plaintext := make([]byte, len(ciphertext))
  3. finalplaintext := make([]byte, len(ciphertext))
  4. for len(ciphertext) > 0 {
  5. cipher.Decrypt(plaintext, ciphertext)
  6. ciphertext = ciphertext[bs:]
  7. decryptedBlock := plaintext[:bs]
  8. for index, element := range decryptedBlock {
  9. finalplaintext[(i*bs)+index] = element
  10. }
  11. i++
  12. plaintext = plaintext[bs:]
  13. }
  14. return finalplaintext[:len(finalplaintext)-5]

这个改进的部分将解密后的数据存储在一个名为finalplaintext的新的[]byte切片中。如果你返回它,你就可以得到数据。

以这种方式进行操作很重要,因为Decrypt函数一次只能处理一个块大小的数据。

我返回一个切片,因为我怀疑它可能是填充的。我对密码学和Go语言都不太熟悉,所以欢迎任何人纠正/修改这个代码。

英文:

I used your code so I feel the need to show you how I fixed it.

I am doing the cryptopals challenges for this problem in Go.

I'll walk you through the mistake since the code is mostly correct.

  1. for len(plaintext) &gt; 0 {
  2. cipher.Decrypt(plaintext, ciphertext)
  3. plaintext = plaintext[bs:]
  4. ciphertext = ciphertext[bs:]
  5. }

The loop does decrypt the data but does not put it anywhere. It simply shifts the two arrays along producing no output.

  1. i := 0
  2. plaintext := make([]byte, len(ciphertext))
  3. finalplaintext := make([]byte, len(ciphertext))
  4. for len(ciphertext) &gt; 0 {
  5. cipher.Decrypt(plaintext, ciphertext)
  6. ciphertext = ciphertext[bs:]
  7. decryptedBlock := plaintext[:bs]
  8. for index, element := range decryptedBlock {
  9. finalplaintext[(i*bs)+index] = element
  10. }
  11. i++
  12. plaintext = plaintext[bs:]
  13. }
  14. return finalplaintext[:len(finalplaintext)-5]

What this new improvement does is store the decrypted data into a new []byte called finalplaintext. If you return that you get the data.

It's important to do it this way since the Decrypt function only works one block size at a time.

I return a slice because I suspect it's padded. I am new to cryptography and Go so anyone feel free to correct/revise this.

答案4

得分: 1

理想情况下,你希望实现crypto/cipher#BlockMode接口。由于官方没有提供这样的接口,我使用crypto/cipher#NewCBCEncrypter作为起点:

  1. package ecb
  2. import "crypto/cipher"
  3. type ecbEncrypter struct { cipher.Block }
  4. func newECBEncrypter(b cipher.Block) cipher.BlockMode {
  5. return ecbEncrypter{b}
  6. }
  7. func (x ecbEncrypter) BlockSize() int {
  8. return x.Block.BlockSize()
  9. }
  10. func (x ecbEncrypter) CryptBlocks(dst, src []byte) {
  11. size := x.BlockSize()
  12. if len(src) % size != 0 {
  13. panic("crypto/cipher: input not full blocks")
  14. }
  15. if len(dst) < len(src) {
  16. panic("crypto/cipher: output smaller than input")
  17. }
  18. for len(src) > 0 {
  19. x.Encrypt(dst, src)
  20. src, dst = src[size:], dst[size:]
  21. }
  22. }
英文:

Ideally you want to implement the crypto/cipher#BlockMode interface. Since an official one doesn't exist, I used crypto/cipher#NewCBCEncrypter as a starting point:

  1. package ecb
  2. import &quot;crypto/cipher&quot;
  3. type ecbEncrypter struct { cipher.Block }
  4. func newECBEncrypter(b cipher.Block) cipher.BlockMode {
  5. return ecbEncrypter{b}
  6. }
  7. func (x ecbEncrypter) BlockSize() int {
  8. return x.Block.BlockSize()
  9. }
  10. func (x ecbEncrypter) CryptBlocks(dst, src []byte) {
  11. size := x.BlockSize()
  12. if len(src) % size != 0 {
  13. panic(&quot;crypto/cipher: input not full blocks&quot;)
  14. }
  15. if len(dst) &lt; len(src) {
  16. panic(&quot;crypto/cipher: output smaller than input&quot;)
  17. }
  18. for len(src) &gt; 0 {
  19. x.Encrypt(dst, src)
  20. src, dst = src[size:], dst[size:]
  21. }
  22. }

答案5

得分: -2

我被一些事情搞糊涂了。

首先,我需要一个上述算法的AES-256版本,但显然当给定的密钥长度为32时,aes.Blocksize(即16)不会改变。因此,只需提供长度为32的密钥即可使算法成为AES-256。

其次,解密后的值仍然包含填充,填充值取决于加密字符串的长度。例如,当有5个填充字符时,填充字符本身将是5。

这是我的一个返回字符串的函数:

  1. func DecryptAes256Ecb(hexString string, key string) string {
  2. data, _ := hex.DecodeString(hexString)
  3. cipher, _ := aes.NewCipher([]byte(key))
  4. decrypted := make([]byte, len(data))
  5. size := 16
  6. for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
  7. cipher.Decrypt(decrypted[bs:be], data[bs:be])
  8. }
  9. // 移除填充。字节数组中的最后一个字符是填充字符的数量
  10. paddingSize := int(decrypted[len(decrypted)-1])
  11. return string(decrypted[0 : len(decrypted)-paddingSize])
  12. }

希望对你有帮助!

英文:

I was confused by a couple of things.

First i needed a aes-256 version of the above algorithm, but apparently the aes.Blocksize (which is 16) won't change when the given key has length 32. So it is enough to give a key of length 32 to make the algorithm aes-256

Second, the decrypted value still contains padding and the padding value changes depending on the length of the encrypted string. E.g. when there are 5 padding characters the padding character itself will be 5.

Here is my function which returns a string:

  1. func DecryptAes256Ecb(hexString string, key string) string {
  2. data, _ := hex.DecodeString(hexString)
  3. cipher, _ := aes.NewCipher([]byte(key))
  4. decrypted := make([]byte, len(data))
  5. size := 16
  6. for bs, be := 0, size; bs &lt; len(data); bs, be = bs+size, be+size {
  7. cipher.Decrypt(decrypted[bs:be], data[bs:be])
  8. }
  9. // remove the padding. The last character in the byte array is the number of padding chars
  10. paddingSize := int(decrypted[len(decrypted)-1])
  11. return string(decrypted[0 : len(decrypted)-paddingSize])
  12. }

huangapple
  • 本文由 发表于 2014年6月6日 07:48:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/24072026.html
匿名

发表评论

匿名网友

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

确定