LoginSignup
6
5

More than 3 years have passed since last update.

GoでCipher Feedback暗号化と復号化

Last updated at Posted at 2019-07-22

CFB is

fig34.gif
footnote1

601px-CFB_encryption.svg.png
601px-CFB_decryption.svg.png

footnote2

標準Packageのみでやりたい

ライブラリならこう

package crypto

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/base64"
    "errors"
    "io"
)

func encodeBase64(b []byte) string {
    return base64.StdEncoding.EncodeToString(b)
}

func decodeBase64(s string) []byte {
    data, err := base64.StdEncoding.DecodeString(s)
    if err != nil {
        panic(err)
    }
    return data
}

func Encrypt(key, text []byte) (string, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }
    b := base64.StdEncoding.EncodeToString(text)
    cipt := make([]byte, aes.BlockSize+len(b))
    iv := cipt[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return "", err
    }
    cfb := cipher.NewCFBEncrypter(block, iv)
    cfb.XORKeyStream(cipt[aes.BlockSize:], []byte(b))
    return encodeBase64(cipt), nil
}

func Decrypt(key []byte, t string) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    text := decodeBase64(t)
    if len(text) < aes.BlockSize {
        return nil, errors.New("too short")
    }
    iv := text[:aes.BlockSize]
    text = text[aes.BlockSize:]
    cfb := cipher.NewCFBDecrypter(block, iv)
    cfb.XORKeyStream(text, text)
    data, err := base64.StdEncoding.DecodeString(string(text))
    if err != nil {
        return nil, err
    }
    return data, nil
}

ライブラリを使うにはこう

encrypt

// keyは復号化用キーでもある。
enc, err := crypto.Encrypt([]byte(key), []byte(str))
    if err != nil {
        log.Fatalf("%+v", err)
    }
fmt.Println(enc)

decrypt

dec, err := crypto.Decrypt([]byte(key), enc)
    if err != nil {
        log.Fatalf("%+v", err)
    }
fmt.Println(string(dec))

CFBモードを任意のxの整数倍の欠落に対しても同期を維持することが可能な自己同期型のストリーム暗号として利用するためには、ブロックサイズと初期化ベクトルのサイズでシフトレジスタを初期化する必要がある。これはブロック暗号によって暗号化され、暗号化結果の上位xビットは平文のxビットとのXORを取られ、これがxビットの暗号文となる。これらxビットの出力はシフトレジスタにシフトされ、次のxビットの平文の処理に用いられる。復号も同様であり、初期化ベクトルから始まり、復号、復号結果の上位xビットと暗号文のxビットのXORによりxビットの平文となり、これが次のxビットの暗号文の処理に用いられる。このような処理はCFB-8あるいはCFB-1として知られている(シフト量の大きさによる)

ブロック暗号を暗号化処理にのみ用いることと、ブロックサイズの整数倍にメッセージのパディングを行う必要がないことがメリットですね

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5