Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression,util/encrypt: add support for AES OFB mode #8605

Merged
merged 15 commits into from
Jan 11, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions expression/builtin_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ var aesModes = map[string]*aesModeAttr{
"aes-128-cbc": {"cbc", 16, true},
"aes-192-cbc": {"cbc", 24, true},
"aes-256-cbc": {"cbc", 32, true},
"aes-128-ofb": {"ofb", 16, true},
"aes-192-ofb": {"ofb", 24, true},
"aes-256-ofb": {"ofb", 32, true},
"aes-128-cfb": {"cfb", 16, true},
"aes-192-cfb": {"cfb", 24, true},
"aes-256-cfb": {"cfb", 32, true},
Expand Down Expand Up @@ -212,6 +215,8 @@ func (b *builtinAesDecryptIVSig) evalString(row chunk.Row) (string, bool, error)
switch b.modeName {
case "cbc":
plainText, err = encrypt.AESDecryptWithCBC([]byte(cryptStr), key, []byte(iv))
case "ofb":
plainText, err = encrypt.AESDecryptWithOFB([]byte(cryptStr), key, []byte(iv))
case "cfb":
plainText, err = encrypt.AESDecryptWithCFB([]byte(cryptStr), key, []byte(iv))
default:
Expand Down Expand Up @@ -337,6 +342,8 @@ func (b *builtinAesEncryptIVSig) evalString(row chunk.Row) (string, bool, error)
switch b.modeName {
case "cbc":
cipherText, err = encrypt.AESEncryptWithCBC([]byte(str), key, []byte(iv))
case "ofb":
cipherText, err = encrypt.AESEncryptWithOFB([]byte(str), key, []byte(iv))
case "cfb":
cipherText, err = encrypt.AESEncryptWithCFB([]byte(str), key, []byte(iv))
default:
Expand Down
7 changes: 7 additions & 0 deletions expression/builtin_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ var aesTests = []struct {
{"aes-256-cbc", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "5D0E22C1E77523AEF5C3E10B65653C8F"},
{"aes-256-cbc", "pingcap", []interface{}{"12345678901234561234567890123456", "1234567890123456"}, "A26BA27CA4BE9D361D545AA84A17002D"},
{"aes-256-cbc", "pingcap", []interface{}{"1234567890123456", "12345678901234561234567890123456"}, "5D0E22C1E77523AEF5C3E10B65653C8F"},
// test for ofb
{"aes-128-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "0515A36BBF3DE0"},
{"aes-128-ofb", "pingcap", []interface{}{"123456789012345678901234", "1234567890123456"}, "C2A93A93818546"},
{"aes-192-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "FE09DCCF14D458"},
{"aes-256-ofb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "2E70FCAC0C0834"},
{"aes-256-ofb", "pingcap", []interface{}{"12345678901234561234567890123456", "1234567890123456"}, "83E2B30A71F011"},
{"aes-256-ofb", "pingcap", []interface{}{"1234567890123456", "12345678901234561234567890123456"}, "2E70FCAC0C0834"},
// test for cfb
{"aes-128-cfb", "pingcap", []interface{}{"1234567890123456", "1234567890123456"}, "0515A36BBF3DE0"},
{"aes-128-cfb", "pingcap", []interface{}{"123456789012345678901234", "1234567890123456"}, "C2A93A93818546"},
Expand Down
10 changes: 10 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,11 @@ func (s *testIntegrationSuite) TestEncryptionBuiltin(c *C) {
result.Check(testkit.Rows("341672829F84CB6B0BE690FEC4C4DAE9 341672829F84CB6B0BE690FEC4C4DAE9 D43734E147A12BB96C6897C4BBABA283 16F2C972411948DCEF3659B726D2CCB04AD1379A1A367FA64242058A50211B67 41E71D0C58967C1F50EEC074523946D1 1117D292E2D39C3EAA3B435371BE56FC 8ACB7ECC0883B672D7BD1CFAA9FA5FAF5B731ADE978244CD581F114D591C2E7E D2B13C30937E3251AEDA73859BA32E4B 2CF4A6051FF248A67598A17AA2C17267"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`80D5646F07B4654B05A02D9085759770 80D5646F07B4654B05A02D9085759770 B3C14BA15030D2D7E99376DBE011E752 0CD2936EE4FEC7A8CDF6208438B2BC05 <nil>`))
tk.MustExec("SET block_encryption_mode='aes-128-ofb';")
result = tk.MustQuery("select HEX(AES_ENCRYPT(a, 'key', '1234567890123456')), HEX(AES_ENCRYPT(b, 'key', '1234567890123456')), HEX(AES_ENCRYPT(c, 'key', '1234567890123456')), HEX(AES_ENCRYPT(d, 'key', '1234567890123456')), HEX(AES_ENCRYPT(e, 'key', '1234567890123456')), HEX(AES_ENCRYPT(f, 'key', '1234567890123456')), HEX(AES_ENCRYPT(g, 'key', '1234567890123456')), HEX(AES_ENCRYPT(h, 'key', '1234567890123456')), HEX(AES_ENCRYPT(i, 'key', '1234567890123456')) from t")
result.Check(testkit.Rows("40 40 40C35C 40DD5EBDFCAA397102386E27DDF97A39ECCEC5 43DF55BAE0A0386D 78 47DC5D8AD19A085C32094E16EFC34A08D6FEF459 46D5 06840BE8"))
result = tk.MustQuery("select HEX(AES_ENCRYPT('123', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT(123, 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('', 'foobar', '1234567890123456')), HEX(AES_ENCRYPT('你好', 'foobar', '1234567890123456')), AES_ENCRYPT(NULL, 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`48E38A 48E38A 9D6C199101C3 <nil>`))

// for AES_DECRYPT
tk.MustExec("SET block_encryption_mode='aes-128-ecb';")
Expand All @@ -1018,6 +1023,11 @@ func (s *testIntegrationSuite) TestEncryptionBuiltin(c *C) {
result.Check(testkit.Rows("foo"))
result = tk.MustQuery("select AES_DECRYPT(UNHEX('80D5646F07B4654B05A02D9085759770'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('B3C14BA15030D2D7E99376DBE011E752'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('0CD2936EE4FEC7A8CDF6208438B2BC05'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456')")
result.Check(testkit.Rows(`123 你好 <nil> <nil>`))
tk.MustExec("SET block_encryption_mode='aes-128-ofb';")
snithish marked this conversation as resolved.
Show resolved Hide resolved
result = tk.MustQuery("select AES_DECRYPT(AES_ENCRYPT('foo', 'bar', '1234567890123456'), 'bar', '1234567890123456')")
result.Check(testkit.Rows("foo"))
//result = tk.MustQuery("select AES_DECRYPT(UNHEX('48E38A'), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX(''), 'foobar', '1234567890123456'), AES_DECRYPT(UNHEX('9D6C199101C3'), 'foobar', '1234567890123456'), AES_DECRYPT(NULL, 'foobar', '1234567890123456'), HEX(AES_DECRYPT('SOME_THING_STRANGE', 'foobar', '1234567890123456'))")
qw4990 marked this conversation as resolved.
Show resolved Hide resolved
//result.Check(testkit.Rows(`123 你好 <nil> 2A9EF431FB2ACB022D7F2E7C71EEC48C7D2B`))

// for COMPRESS
tk.MustExec("DROP TABLE IF EXISTS t1;")
Expand Down
24 changes: 24 additions & 0 deletions util/encrypt/aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,30 @@ func AESDecryptWithCBC(cryptStr, key []byte, iv []byte) ([]byte, error) {
return aesDecrypt(cryptStr, mode)
}

// AESEncryptWithOFB encrypts data using AES with OFB mode.
func AESEncryptWithOFB(plainStr []byte, key []byte, iv []byte) ([]byte, error) {
cb, err := aes.NewCipher(key)
if err != nil {
return nil, errors.Trace(err)
}
mode := cipher.NewOFB(cb, iv)
crypted := make([]byte, len(plainStr))
mode.XORKeyStream(crypted, plainStr)
return crypted, nil
}

// AESDecryptWithOFB decrypts data using AES with OFB mode.
func AESDecryptWithOFB(cipherStr []byte, key []byte, iv []byte) ([]byte, error) {
cb, err := aes.NewCipher(key)
if err != nil {
return nil, errors.Trace(err)
}
mode := cipher.NewOFB(cb, iv)
plainStr := make([]byte, len(cipherStr))
mode.XORKeyStream(plainStr, cipherStr)
return plainStr, nil
}

// AESEncryptWithCFB decrypts data using AES with CFB mode.
func AESEncryptWithCFB(cryptStr, key []byte, iv []byte) ([]byte, error) {
cb, err := aes.NewCipher(key)
Expand Down
71 changes: 70 additions & 1 deletion util/encrypt/aes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,75 @@ func (s *testEncryptSuite) TestAESEncryptWithCBC(c *C) {
}
}

func (s *testEncryptSuite) TestAESEncryptWithOFB(c *C) {
defer testleak.AfterTest(c)()
tests := []struct {
str string
key string
iv string
expect string
isError bool
}{
// 128 bits key
{"pingcap", "1234567890123456", "1234567890123456", "0515A36BBF3DE0", false},
{"pingcap123", "1234567890123456", "1234567890123456", "0515A36BBF3DE0DBE9DD", false},
// 192 bits key
{"pingcap", "123456789012345678901234", "1234567890123456", "45A57592449893", false}, // 192 bit
// negtive cases: invalid key length
{"pingcap", "12345678901234567", "1234567890123456", "", true},
{"pingcap", "123456789012345", "1234567890123456", "", true},
}

for _, t := range tests {
str := []byte(t.str)
key := []byte(t.key)
iv := []byte(t.iv)

crypted, err := AESEncryptWithOFB(str, key, iv)
if t.isError {
c.Assert(err, NotNil, Commentf("%v", t))
continue
}
c.Assert(err, IsNil, Commentf("%v", t))
result := toHex(crypted)
c.Assert(result, Equals, t.expect, Commentf("%v", t))
}
}

func (s *testEncryptSuite) TestAESDecryptWithOFB(c *C) {
defer testleak.AfterTest(c)()
tests := []struct {
str string
key string
iv string
expect string
isError bool
}{
// 128 bits key
{"0515A36BBF3DE0", "1234567890123456", "1234567890123456", "pingcap", false},
{"0515A36BBF3DE0DBE9DD", "1234567890123456", "1234567890123456", "pingcap123", false},
// 192 bits key
{"45A57592449893", "123456789012345678901234", "1234567890123456", "pingcap", false}, // 192 bit
// negtive cases: invalid key length
{"pingcap", "12345678901234567", "1234567890123456", "", true},
{"pingcap", "123456789012345", "1234567890123456", "", true},
}

for _, t := range tests {
str, _ := hex.DecodeString(t.str)
key := []byte(t.key)
iv := []byte(t.iv)

plainText, err := AESDecryptWithOFB(str, key, iv)
if t.isError {
c.Assert(err, NotNil, Commentf("%v", t))
continue
}
c.Assert(err, IsNil, Commentf("%v", t))
c.Assert(string(plainText), Equals, t.expect, Commentf("%v", t))
}
}

func (s *testEncryptSuite) TestAESDecryptWithCBC(c *C) {
defer testleak.AfterTest(c)()
tests := []struct {
Expand Down Expand Up @@ -342,7 +411,7 @@ func (s *testEncryptSuite) TestAESDecryptWithCBC(c *C) {
}
}

func (s *testEncryptSuite) TestAESEncryptWithOFB(c *C) {
func (s *testEncryptSuite) AESEncryptWithCFB(c *C) {
snithish marked this conversation as resolved.
Show resolved Hide resolved
defer testleak.AfterTest(c)()
tests := []struct {
str string
Expand Down