Шифрование Golang AES ECB

Попытка эмулировать алгоритм в Go, который в основном представляет собой шифрование в режиме AES ECB.

Вот что у меня есть

func Decrypt(data []byte) []byte {
    cipher, err := aes.NewCipher([]byte(KEY))
    if err == nil {
        cipher.Decrypt(data, PKCS5Pad(data))
        return data
    }
    return nil
}

У меня также есть проверенный и работающий алгоритм PKCS5Padding, который сначала заполняет данные. Я не могу найти никакой информации о том, как переключить режим шифрования в пакете Go AES (его точно нет в документации) .

У меня есть этот код на другом языке, поэтому я знаю, что этот алгоритм работает не совсем правильно.

РЕДАКТИРОВАТЬ: вот метод, который я интерпретировал на странице проблемы

func AESECB(ciphertext []byte) []byte {
    cipher, _ := aes.NewCipher([]byte(KEY))
    fmt.Println("AESing the data")
    bs := 16
    if len(ciphertext)%bs != 0     {
        panic("Need a multiple of the blocksize")
    }

    plaintext := make([]byte, len(ciphertext))
    for len(plaintext) > 0 {
        cipher.Decrypt(plaintext, ciphertext)
        plaintext = plaintext[bs:]
        ciphertext = ciphertext[bs:]
    }
    return plaintext
}

На самом деле это не возвращает никаких данных, возможно, я что-то напортачил, когда изменил его с encripting на decripting


person Jameo    schedule 05.06.2014    source источник
comment
что говорит ошибка? у вас есть / можете ли вы привести пример детской площадки?   -  person fabrizioM    schedule 06.06.2014
comment
Вы заполняете открытый текст перед шифрованием и распаковываете его после. И вы делаете это только для последнего блока, а не где-нибудь между ними.   -  person Maarten Bodewes    schedule 06.06.2014
comment
@owls вместо реализации, которую я видел, фактически дополнял зашифрованные данные перед расшифровкой ... может ли это быть правильным? github.com/martinp/pysnap/blob/master/pysnap/ utils.py # L40   -  person Jameo    schedule 06.06.2014
comment
Вам конкретно нужно здесь шифрование в режиме ECB? Что вы пытаетесь зашифровать / есть ли необходимое взаимодействие с API?   -  person elithrar    schedule 06.06.2014
comment
@Jameo Нет, это не может быть правильно. Это будет означать, что вы добавляете полный блок заполнения (поскольку зашифрованный текст всегда в x раз больше размера блока). Таким образом, открытый текст будет состоять из всего , включая заполнение в конце и блок случайного мусора. Значит, он расшифрует, да, но результат будет некорректным.   -  person Maarten Bodewes    schedule 06.06.2014


Ответы (5)


Электронная кодовая книга (ECB) - это очень простой режим работы. Данные, подлежащие шифрованию, делятся на байтовые блоки одинакового размера. Для каждого блока применяется шифр, в данном случае AES, генерирующий зашифрованный блок.

Приведенный ниже фрагмент кода расшифровывает данные AES-128 в ECB (обратите внимание, что размер блока составляет 16 байт):

package main

import (
    "crypto/aes"
)

func DecryptAes128Ecb(data, key []byte) []byte {
    cipher, _ := aes.NewCipher([]byte(key))
    decrypted := make([]byte, len(data))
    size := 16

    for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
        cipher.Decrypt(decrypted[bs:be], data[bs:be])
    }

    return decrypted
}

Как упоминалось в @OneOfOne, ECB небезопасен и его очень легко обнаружить, поскольку повторяющиеся блоки всегда будут шифроваться одними и теми же зашифрованными блоками. Этот ответ Crypto SE дает очень хорошее объяснение почему.

person phss    schedule 14.01.2017
comment
Спасибо за это, было полезно. Стоит отметить, что это не ограничивается 128-битным шифрованием - оно также будет работать для 256-битного, передав 32-байтовый ключ вместо 16-байтового. - person Jarvis Johnson; 22.03.2019

Почему? Мы намеренно исключили ECB: он небезопасен, а при необходимости его легко реализовать.

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

person OneOfOne    schedule 05.06.2014
comment
хороший момент, также, если вы перейдете по ссылке, вы найдете простую реализацию режима ECB в Go - person Kluyg; 06.06.2014
comment
Но, конечно, вы бы не стали внедрять эту простую реализацию режима ECB ни в какое программное обеспечение (когда-либо) из-за его существенных недостатков, верно? :) - person elithrar; 06.06.2014
comment
@elithrar определенно не для нового программного обеспечения ... это требование для существующего API, с которым я пытаюсь взаимодействовать - person Jameo; 06.06.2014

Я использовал ваш код, поэтому считаю необходимым показать вам, как я его исправил.

Я выполняю задачи шифрования для этой проблемы в Go.

Я объясню вам ошибку, поскольку код в основном правильный.

for len(plaintext) > 0 {
    cipher.Decrypt(plaintext, ciphertext)
    plaintext = plaintext[bs:]
    ciphertext = ciphertext[bs:]
}

Цикл расшифровывает данные, но никуда их не помещает. Он просто сдвигает два массива без вывода.

i := 0
plaintext := make([]byte, len(ciphertext))
finalplaintext := make([]byte, len(ciphertext))
for len(ciphertext) > 0 {
    cipher.Decrypt(plaintext, ciphertext)
    ciphertext = ciphertext[bs:]
    decryptedBlock := plaintext[:bs]
    for index, element := range decryptedBlock {
        finalplaintext[(i*bs)+index] = element
    }
    i++
    plaintext = plaintext[bs:]
} 
return finalplaintext[:len(finalplaintext)-5]

Это новое улучшение сохраняет расшифрованные данные в новом [] байте, называемом finalplaintext. Если вы вернетесь, вы получите данные.

Это важно сделать таким образом, поскольку функция дешифрования работает только с одним размером блока за раз.

Я возвращаю кусок, потому что подозреваю, что он набит. Я новичок в криптографии и Go, поэтому любой может исправить / пересмотреть это.

person Dan Garcia    schedule 15.05.2016

В идеале вы хотите реализовать интерфейс crypto / cipher # BlockMode. Поскольку официального не существует, я использовал crypto / cipher # NewCBCEncrypter в качестве отправной точки:

package ecb
import "crypto/cipher"

type ecbEncrypter struct { cipher.Block }

func newECBEncrypter(b cipher.Block) cipher.BlockMode {
   return ecbEncrypter{b}
}

func (x ecbEncrypter) BlockSize() int {
   return x.Block.BlockSize()
}

func (x ecbEncrypter) CryptBlocks(dst, src []byte) {
   size := x.BlockSize()
   if len(src) % size != 0 {
      panic("crypto/cipher: input not full blocks")
   }
   if len(dst) < len(src) {
      panic("crypto/cipher: output smaller than input")
   }
   for len(src) > 0 {
      x.Encrypt(dst, src)
      src, dst = src[size:], dst[size:]
   }
}
person Steven Penny    schedule 07.03.2021

Меня смутило несколько вещей.

Сначала мне нужна была версия вышеупомянутого алгоритма aes-256, но, очевидно, aes.Blocksize (который равен 16) не изменится, когда заданный ключ имеет длину 32. Так что достаточно дать ключ длиной 32, чтобы сделать алгоритм aes-256

Во-вторых, расшифрованное значение по-прежнему содержит заполнение, а значение заполнения изменяется в зависимости от длины зашифрованной строки. Например. когда есть 5 символов заполнения, сам символ заполнения будет 5.

Вот моя функция, которая возвращает строку:

func DecryptAes256Ecb(hexString string, key string) string {
  data, _ := hex.DecodeString(hexString)

  cipher, _ := aes.NewCipher([]byte(key))

  decrypted := make([]byte, len(data))
  size := 16

  for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
    cipher.Decrypt(decrypted[bs:be], data[bs:be])
  }

  // remove the padding. The last character in the byte array is the number of padding chars
  paddingSize := int(decrypted[len(decrypted)-1])
  return string(decrypted[0 : len(decrypted)-paddingSize])
}
person kriepy    schedule 01.11.2017
comment
1. AES имеет один размер блока из 16 байтов, он не связан с размером ключа. AES имеет три размера ключа: 128, 192 и 256 бит. 2. Здесь показано заполнение PKCS # 7, заполнение необходимо, если данные, подлежащие шифрованию, не всегда кратны размеру блока. 3. Большинство реализаций AES (реализации aes Go этого не делают) обрабатывают входные данные длиной более одного блока и автоматически обрабатывают вызовы блоков и заполнение. 4. Вместо этого см. крипто / шифр, который обрабатывает блокировку и заполнение. - person zaph; 01.11.2017