Goには標準パッケージにcipherがあり、それを用いると暗号化復号化を行うことができる
例えば暗号化、復号化は以下のように定義することで実行できます。
import ( "crypto/cipher" "crypto/des" ) func TripleDesEncrypt(data, key, iv []byte) ([]byte, error) { block, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } stream := cipher.NewCFBEncrypter(block, iv) encrypted := make([]byte, len(data)) stream.XORKeyStream(encrypted, data) return encrypted, nil } func TripleDesDecrypt(data, key, iv []byte) ([]byte, error) { block, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } stream := cipher.NewCFBDecrypter(block, iv) decrypted := make([]byte, len(data)) stream.XORKeyStream(decrypted, data) return decrypted, nil }
The Go Playground で動かせるようにしておきました。
ただユースケースとして、他言語で暗号化しGoで復号化させるという場合もよくあると思います。
Pythonで暗号化する際にpycryptoを使うと以下で簡単に暗号化できます。 暗号化後はbyte列になってしまうので、base64でエンコードしておきます。
from Crypto.Cipher import DES3 from Crypto import Random import base64 key = "123456789123456789123456" iv = "12345678" cipher_encrypt = DES3.new(key, DES3.MODE_CFB, iv) plaintext = "Hello World" encrypted_text = cipher_encrypt.encrypt(plaintext) b64_text = base64.b64encode(encrypted_text) print("encrypt:",encrypted_text.hex()," base64 encoded: ",b64_text)
ここで暗号化した文字列を先程のGoの実装に食わせると復号化されません。 これはPythonが8bit segmentを利用しているからなようで、Goはそこに対応していません。
そこで、Goで復号化するためには以下のようにDecryptのメソッドを変更する必要があります。
type cfb8 struct { b cipher.Block blockSize int in []byte out []byte decrypt bool } func (x *cfb8) XORKeyStream(dst, src []byte) { for i := range src { x.b.Encrypt(x.out, x.in) copy(x.in[:x.blockSize-1], x.in[1:]) if x.decrypt { x.in[x.blockSize-1] = src[i] } dst[i] = src[i] ^ x.out[0] if !x.decrypt { x.in[x.blockSize-1] = dst[i] } } } func newCFB8Decrypter(block cipher.Block, iv []byte) cipher.Stream { blockSize := block.BlockSize() if len(iv) != blockSize { // stack trace will indicate whether it was de or encryption panic("cipher.newCFB: IV length must equal block size") } x := &cfb8{ b: block, blockSize: blockSize, out: make([]byte, blockSize), in: make([]byte, blockSize), decrypt: true, } copy(x.in, iv) return x }
これで復号化ができます。 動くコードはこちらに置いておきます。
参考URL