Spec-Zone.ru › Go

Пакет шифрования

  • import "crypto/cipher"
  • Обзор
  • Индекс
  • Примеры

Обзор

Пакет cipher реализует стандартные режимы блочного шифрования, которые можно использовать вместе с реализациями блочных шифров низкого уровня. См. https://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html и Специальное издание NIST 800-38A.

Индекс

  • тип AEAD
  • функция NewGCM(cipher Block) (AEAD, ошибка)
  • функция NewGCMWithNonceSize(cipher Block, размер int) (AEAD, ошибка)
  • функция NewGCMWithRandomNonce(cipher Block) (AEAD, ошибка)
  • функция NewGCMWithTagSize(cipher Block, размер_тега int) (AEAD, ошибка)
  • тип Block
  • тип BlockMode
  • функция NewCBCDecrypter(b Block, iv []byte) BlockMode
  • функция NewCBCEncrypter(b Block, iv []byte) BlockMode
  • тип Stream
  • функция NewCFBDecrypter(block Block, iv []byte) Stream
  • функция NewCFBEncrypter(block Block, iv []byte) Stream
  • функция NewCTR(block Block, iv []byte) Stream
  • функция NewOFB(b Block, iv []byte) Stream
  • тип StreamReader
  • функция (r StreamReader) Read(dst []byte) (n int, ошибка error)
  • тип StreamWriter
  • функция (w StreamWriter) Close() ошибка
  • функция (w StreamWriter) Write(src []byte) (n int, ошибка error)

Примеры

NewCBCDecrypter
NewCBCEncrypter
NewCFBDecrypter
NewCFBEncrypter
NewCTR
NewGCM (Расшифрование)
NewGCM (Шифрование)
NewOFB
StreamReader
StreamWriter

Файлы пакета

cbc.go cfb.go cipher.go ctr.go gcm.go io.go ofb.go

тип AEAD 1.2

AEAD — это режим шифрования, предоставляющий аутентифицированное шифрование с сопутствующими данными. Для описания методологии см. https://en.wikipedia.org/wiki/Authenticated_encryption.

type AEAD interface {
    // NonceSize returns the size of the nonce that must be passed to Seal
    // and Open.
    NonceSize() int

    // Overhead returns the maximum difference between the lengths of a
    // plaintext and its ciphertext.
    Overhead() int

    // Seal encrypts and authenticates plaintext, authenticates the
    // additional data and appends the result to dst, returning the updated
    // slice. The nonce must be NonceSize() bytes long and unique for all
    // time, for a given key.
    //
    // To reuse plaintext's storage for the encrypted output, use plaintext[:0]
    // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
    // dst and additionalData may not overlap.
    Seal(dst, nonce, plaintext, additionalData []byte) []byte

    // Open decrypts and authenticates ciphertext, authenticates the
    // additional data and, if successful, appends the resulting plaintext
    // to dst, returning the updated slice. The nonce must be NonceSize()
    // bytes long and both it and the additional data must match the
    // value passed to Seal.
    //
    // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
    // as dst. Otherwise, the remaining capacity of dst must not overlap ciphertext.
    // dst and additionalData may not overlap.
    //
    // Even if the function fails, the contents of dst, up to its capacity,
    // may be overwritten.
    Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
}

функция NewGCM 1.2

func NewGCM(cipher Block) (AEAD, error)

NewGCM возвращает заданный 128-битный, блочный шифр, упакованный в режиме Galois Counter с стандартной длиной nonce.

В общем случае операция GHASH, выполняемая этой реализацией GCM, не является постоянной по времени. Исключением является случай, когда базовый Block был создан функцией aes.NewCipher на системах с аппаратной поддержкой AES. Подробности см. в документации пакета crypto/aes.

Пример (Расшифрование)

Код:

// Load your secret key from a safe place and reuse it across multiple
// Seal/Open calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
ciphertext, _ := hex.DecodeString("c3aaa29f002ca75870806e44086700f62ce4d43e902b3888e23ceff797a7a471")
nonce, _ := hex.DecodeString("64a9433eae7ccceee2fc0eda")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err.Error())
}

aesgcm, err := cipher.NewGCM(block)
if err != nil {
    panic(err.Error())
}

plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
    panic(err.Error())
}

fmt.Printf("%s\n", plaintext)

Вывод:

exampleplaintext

Пример (Шифрование)

Код:

// Load your secret key from a safe place and reuse it across multiple
// Seal/Open calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
// When decoded the key should be 16 bytes (AES-128) or 32 (AES-256).
key, _ := hex.DecodeString("6368616e676520746869732070617373776f726420746f206120736563726574")
plaintext := []byte("exampleplaintext")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err.Error())
}

// Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
nonce := make([]byte, 12)
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
    panic(err.Error())
}

aesgcm, err := cipher.NewGCM(block)
if err != nil {
    panic(err.Error())
}

ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
fmt.Printf("%x\n", ciphertext)

функция NewGCMWithNonceSize 1.5

func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error)

NewGCMWithNonceSize возвращает заданный 128-битный, блочный шифр, упакованный в режиме Galois Counter Mode, который принимает nonce заданной длины. Длина не должна быть равна нулю.

Используйте эту функцию только если вам нужна совместимость с существующей криптосистемой, которая использует нестандартные длины nonce. Все остальные пользователи должны использовать NewGCM, который быстрее и более устойчив к злоупотреблениям.

функция NewGCMWithRandomNonce 1.24

func NewGCMWithRandomNonce(cipher Block) (AEAD, error)

NewGCMWithRandomNonce возвращает заданный шифр, упакованный в Galois Counter Mode, со случайными nonce. Шифр должен быть создан с помощью aes.NewCipher.

Он генерирует случайный 96-битный nonce, который добавляется в заголовок шифрованного текста функцией Seal, и извлекается из зашифрованного текста функцией Open. Размер nonce AEAD равен нулю, в то время как Overhead составляет 28 байт (комбинация размера nonce и размера тега).

Заданный ключ НЕ ДОЛЖЕН использоваться для шифрования более 2^32 сообщений, чтобы ограничить риск столкновения случайных nonce до незначительных уровней.

функция NewGCMWithTagSize 1.11

func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error)

NewGCMWithTagSize возвращает заданный 128-битный, блочный шифр, упакованный в режиме Galois Counter Mode, который генерирует теги заданной длины.

Разрешены размеры тегов от 12 до 16 байт.

Используйте эту функцию только если вам нужна совместимость с существующей криптосистемой, которая использует нестандартные длины тегов. Все остальные пользователи должны использовать NewGCM, который более устойчив к злоупотреблениям.

тип Block

Block представляет реализацию блочного шифра с использованием заданного ключа. Он предоставляет возможность шифрования или дешифрования отдельных блоков. Реализации режима расширяют эту возможность до потоков блоков.

type Block interface {
    // BlockSize returns the cipher's block size.
    BlockSize() int

    // Encrypt encrypts the first block in src into dst.
    // Dst and src must overlap entirely or not at all.
    Encrypt(dst, src []byte)

    // Decrypt decrypts the first block in src into dst.
    // Dst and src must overlap entirely or not at all.
    Decrypt(dst, src []byte)
}

тип BlockMode

BlockMode представляет собой блочный шифр, работающий в блочном режиме (CBC, ECB и т. д.).

type BlockMode interface {
    // BlockSize returns the mode's block size.
    BlockSize() int

    // CryptBlocks encrypts or decrypts a number of blocks. The length of
    // src must be a multiple of the block size. Dst and src must overlap
    // entirely or not at all.
    //
    // If len(dst) < len(src), CryptBlocks should panic. It is acceptable
    // to pass a dst bigger than src, and in that case, CryptBlocks will
    // only update dst[:len(src)] and will not touch the rest of dst.
    //
    // Multiple calls to CryptBlocks behave as if the concatenation of
    // the src buffers was passed in a single run. That is, BlockMode
    // maintains state and does not reset at each CryptBlocks call.
    CryptBlocks(dst, src []byte)
}

функция NewCBCDecrypter

func NewCBCDecrypter(b Block, iv []byte) BlockMode

NewCBCDecrypter возвращает BlockMode, который расшифровывает в режиме шифра с цепочкой блоков, используя заданный Block. Длина iv должна быть такой же, как размер блока Block, и должна совпадать с iv, используемым для шифрования данных.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
ciphertext, _ := hex.DecodeString("73c86d43a9d700a253a96c85b0f6b03ac9792e0e757f869cca306bd3cba1c62b")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize {
    panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]

// CBC mode always works in whole blocks.
if len(ciphertext)%aes.BlockSize != 0 {
    panic("ciphertext is not a multiple of the block size")
}

mode := cipher.NewCBCDecrypter(block, iv)

// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(ciphertext, ciphertext)

// If the original plaintext lengths are not a multiple of the block
// size, padding would have to be added when encrypting, which would be
// removed at this point. For an example, see
// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. However, it's
// critical to note that ciphertexts must be authenticated (i.e. by
// using crypto/hmac) before being decrypted in order to avoid creating
// a padding oracle.

fmt.Printf("%s\n", ciphertext)

Вывод:

exampleplaintext

функция NewCBCEncrypter

func NewCBCEncrypter(b Block, iv []byte) BlockMode

NewCBCEncrypter возвращает BlockMode, который шифрует в режиме шифра с цепочкой блоков, используя заданный Block. Длина iv должна быть такой же, как размер блока Block.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
plaintext := []byte("exampleplaintext")

// CBC mode works on blocks so plaintexts may need to be padded to the
// next whole block. For an example of such padding, see
// https://tools.ietf.org/html/rfc5246#section-6.2.3.2. Here we'll
// assume that the plaintext is already of the correct length.
if len(plaintext)%aes.BlockSize != 0 {
    panic("plaintext is not a multiple of the block size")
}

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    panic(err)
}

mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)

// It's important to remember that ciphertexts must be authenticated
// (i.e. by using crypto/hmac) as well as being encrypted in order to
// be secure.

fmt.Printf("%x\n", ciphertext)

тип Stream

Stream представляет собой потоковый шифр.

type Stream interface {
    // XORKeyStream XORs each byte in the given slice with a byte from the
    // cipher's key stream. Dst and src must overlap entirely or not at all.
    //
    // If len(dst) < len(src), XORKeyStream should panic. It is acceptable
    // to pass a dst bigger than src, and in that case, XORKeyStream will
    // only update dst[:len(src)] and will not touch the rest of dst.
    //
    // Multiple calls to XORKeyStream behave as if the concatenation of
    // the src buffers was passed in a single run. That is, Stream
    // maintains state and does not reset at each XORKeyStream call.
    XORKeyStream(dst, src []byte)
}

функция NewCFBDecrypter

func NewCFBDecrypter(block Block, iv []byte) Stream

NewCFBDecrypter возвращает Stream, который расшифровывает с режимом обратной связи шифра, используя заданный Block. iv должен иметь такой же размер, как размер блока Block.

Устарело: Режим CFB не является аутентифицированным, что, как правило, позволяет активным атакам манипулировать и восстанавливать открытый текст. Рекомендуется использовать режимы AEAD вместо этого. Стандартная реализация CFB в библиотеке также не оптимизирована и не валидирована как часть модуля FIPS 140-3. Если требуется неаутентифицированный режим Stream, используйте NewCTR вместо этого.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
ciphertext, _ := hex.DecodeString("7dd015f06bec7f1b8f6559dad89f4131da62261786845100056b353194ad")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
if len(ciphertext) < aes.BlockSize {
    panic("ciphertext too short")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]

stream := cipher.NewCFBDecrypter(block, iv)

// XORKeyStream can work in-place if the two arguments are the same.
stream.XORKeyStream(ciphertext, ciphertext)
fmt.Printf("%s", ciphertext)

Вывод:

some plaintext

функция NewCFBEncrypter

func NewCFBEncrypter(block Block, iv []byte) Stream

NewCFBEncrypter возвращает Stream, который шифрует с режимом обратной связи шифра, используя заданный Block. iv должен иметь такой же размер, как размер блока Block.

Устарело: Режим CFB не является аутентифицированным, что, как правило, позволяет активным атакам манипулировать и восстанавливать открытый текст. Рекомендуется использовать режимы AEAD вместо этого. Стандартная реализация CFB в библиотеке также не оптимизирована и не валидирована как часть модуля FIPS 140-3. Если требуется неаутентифицированный режим Stream, используйте NewCTR вместо этого.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
plaintext := []byte("some plaintext")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    panic(err)
}

stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

// It's important to remember that ciphertexts must be authenticated
// (i.e. by using crypto/hmac) as well as being encrypted in order to
// be secure.
fmt.Printf("%x\n", ciphertext)

функция NewCTR

func NewCTR(block Block, iv []byte) Stream

NewCTR возвращает Stream, который шифрует/расшифровывает, используя заданный Block в режиме счетчика. Длина iv должна быть такой же, как размер блока Block.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
plaintext := []byte("some plaintext")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    panic(err)
}

stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

// It's important to remember that ciphertexts must be authenticated
// (i.e. by using crypto/hmac) as well as being encrypted in order to
// be secure.

// CTR mode is the same for both encryption and decryption, so we can
// also decrypt that ciphertext with NewCTR.

plaintext2 := make([]byte, len(plaintext))
stream = cipher.NewCTR(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])

fmt.Printf("%s\n", plaintext2)

Вывод:

some plaintext

функция NewOFB

func NewOFB(b Block, iv []byte) Stream

NewOFB возвращает Stream, который шифрует или расшифровывает, используя блочный шифр b в режиме обратной связи выхода. Длина инициализирующего вектора iv должна быть равна размеру блока b.

Устарело: Режим OFB не является аутентифицированным, что, как правило, позволяет активным атакам манипулировать и восстанавливать открытый текст. Рекомендуется использовать режимы AEAD вместо этого. Стандартная реализация OFB в библиотеке также не оптимизирована и не валидирована как часть модуля FIPS 140-3. Если требуется неаутентифицированный режим Stream, используйте NewCTR вместо этого.

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")
plaintext := []byte("some plaintext")

block, err := aes.NewCipher(key)
if err != nil {
    panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    panic(err)
}

stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

// It's important to remember that ciphertexts must be authenticated
// (i.e. by using crypto/hmac) as well as being encrypted in order to
// be secure.

// OFB mode is the same for both encryption and decryption, so we can
// also decrypt that ciphertext with NewOFB.

plaintext2 := make([]byte, len(plaintext))
stream = cipher.NewOFB(block, iv)
stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])

fmt.Printf("%s\n", plaintext2)

Вывод:

some plaintext

тип StreamReader

StreamReader обертывает Stream в io.Reader. Он вызывает XORKeyStream для обработки каждого фрагмента данных, который проходит через него.

type StreamReader struct {
    S Stream
    R io.Reader
}

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")

encrypted, _ := hex.DecodeString("cf0495cc6f75dafc23948538e79904a9")
bReader := bytes.NewReader(encrypted)

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[:])

reader := &cipher.StreamReader{S: stream, R: bReader}
// Copy the input to the output stream, decrypting as we go.
if _, err := io.Copy(os.Stdout, 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.

Вывод:

some secret text

функция (StreamReader) Read

func (r StreamReader) Read(dst []byte) (n int, err error)

тип StreamWriter

StreamWriter обертывает Stream в io.Writer. Он вызывает XORKeyStream для обработки каждого фрагмента данных, который проходит через него. Если какой-либо вызов StreamWriter.Write возвращает короткий результат, то StreamWriter не синхронизирован и его нужно отбросить. У StreamWriter нет внутренней буферизации; StreamWriter.Close не нужно вызывать для сброса данных записи.

type StreamWriter struct {
    S   Stream
    W   io.Writer
    Err error // unused
}

Пример

Код:

// Load your secret key from a safe place and reuse it across multiple
// NewCipher calls. (Obviously don't use this example key for anything
// real.) If you want to convert a passphrase to a key, use a suitable
// package like bcrypt or scrypt.
key, _ := hex.DecodeString("6368616e676520746869732070617373")

bReader := bytes.NewReader([]byte("some secret text"))

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[:])

var out bytes.Buffer

writer := &cipher.StreamWriter{S: stream, W: &out}
// Copy the input to the output buffer, encrypting as we go.
if _, err := io.Copy(writer, bReader); 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.

fmt.Printf("%x\n", out.Bytes())

Вывод:

cf0495cc6f75dafc23948538e79904a9

функция (StreamWriter) Close

func (w StreamWriter) Close() error

Закрывает лежащий в основе Writer и возвращает его значение Close, если Writer также является io.Closer. В противном случае возвращает nil.

func (StreamWriter) Write

func (w StreamWriter) Write(src []byte) (n int, err error)

© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/crypto/cipher/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API