28
Encrypting Data In MySQL With Go Baron Schwartz, VividCortex Percona Live 2015

Encrypting Data in MySQL with Go

Embed Size (px)

Citation preview

Encrypting Data In MySQL With Go

Baron Schwartz, VividCortexPercona Live 2015

Intro & Logistics

• Contact me at @xaprb or [email protected]

• Ask questions anytime

• Slides will be posted

VividCortex is database performance monitoring for MySQL, PostgreSQL, Redis, ++

Agenda

1. Encryption in MySQL2. One specific implementation

Data Encryption

• It’s possible to encrypt at any desired layer in the stack

• You can encrypt “close to the user” or “far from the user”

• It’s also possible to skip layers, e.g. encrypt the block device, encrypt the transport, and leave cleartext everywhere else

Block Device

Filesystem

Database

Service

Application

From A Layer Down

• In general, in many cases when you encrypt at some layer, it’s relatively straightforward to ensure it remains encrypted at lower layers.

• Ideally for the user’s security, you want encryption as far up the stack as possible.

• Ideally for the app’s functionality, you want encryption as far down the stack as possible.

Block Device

Filesystem

Database

Service

Application

Convenience Versus Security

• Anywhere data needs to be understood and manipulated, it must be available in cleartext.

• Users need the data to be decrypted for them in the application, obviously.

• What about other places?

Block Device

Filesystem

Database

Service

Application

Encryption In The App or User Interface

• Example: LastPass.

• Consequence: services can’t do useful things.

• This is impractical for most purposes.

• Consider e.g. using Dropbox to embed slides in a blog post.

Block Device

Filesystem

Database

Service

Application

Encryption In The Service

• Data is available in plaintext in the service, so the service can do useful things.

• Anything that can access the service can access the unencrypted data.

Block Device

Filesystem

Database

Service

Application

Encryption In The Database

• This is rather nuanced. Data can be encrypted in many ways in the database.

• The easiest way to think about this: as a database client, do I need to bring my own key to unlock my data, or is the key resident in the database?

Block Device

Filesystem

Database

Service

Application

Bring My Key, Or Authenticate To Key Storage?

Hello World

Hello World

Send My Key, Or Keep It Private?

• This is equivalent in some ways to encrypting at a higher or lower level in the stack.

• However, the “send my key” strategy has an important consequence: the key is present across more than one layer in the stack.

• If you send a key to a lower level, you lose control over it. (For example it can be viewed in SHOW PROCESSLIST or logged to disk in plaintext.)

Encryption in the Filesystem or Block Device

• This is often a way of implementing “at-rest” encryption.

Block Device

Filesystem

Database

Service

Application

Encrypt at-rest or in-transit?

• PCI specifies two kinds of encryption, “at-rest” and “data in motion.”

• Sometimes companies just ensure they meet these requirements to protect themselves from consequences.

• The reality is, even if data is encrypted both ways, there are easy ways to “checkbox comply” without significantly making access to the data safer and reducing attack surface.

• I believe it is much more important to think about who can get access and how, and address the greatest threats to the end user (not just the vendor).

MySQL Encryption Functions

• MySQL offers a few encryption functions in SQL.

• Many of them are deprecated.

• AES is supported, and is the only one you should use.

• Any encryption using SQL functions is “send-my-key.”

• See https://dev.mysql.com/doc/refman/5.6/en/encryption-functions.html

Key Management

• Key management is an important element of an encryption strategy.

• How are keys secured?

• How are they made available when/where needed? Are they on-disk? Are they in-memory only? Who or what gives them to a user, app, or service that needs them?

• How are they rotated and expired?

• Further reading:

• PKI

• http://aws.amazon.com/kms/

Part 2: Encrypting with Go and MySQL

Encryption with Go

• Go’s database/sql package supports interfaces that enable easy in-service encryption.

• The encryption is transparent to the programmer.

• It is not a “send-my-key” strategy. The key is not leaked outside the Go process.

• See “Using Built-In Interfaces” in “The Ultimate Guide To Building Database-Driven Apps with Go”

Block Device

Filesystem

Database

Service

Application

To Implement

• You need to implement a type that satisfies two of Go’s stdlib interfaces.

• driver.Valuer influences how values are transformed as they are sent to the database.

• sql.Scanner influences how values are transformed upon retrieval.

Simple Code Example - Lowercasetype LowercaseString string

// Implements driver.Valuer. func (ls LowercaseString) Value() (driver.Value, error) { return driver.Value(strings.ToLower(string(ls))), nil }

// Implements sql.Scanner. Simplistic -- only handles string and []byte func (ls *LowercaseString) Scan(src interface{}) error { var source string switch src.(type) { case string: source = src.(string) case []byte: source = string(src.([]byte)) default: return errors.New("Incompatible type for LowercaseString") } *ls = LowercaseString(strings.ToLower(source)) return nil }

Example, Cont’d: Inserting Values

// Insert a row that's not lowercased, and one that is. var normalString string = "I AM UPPERCASED NORMAL STRING" var lcString LowercaseString = "I AM UPPERCASED MAGIC STRING"

_, err = db.Exec("INSERT INTO test.hello VALUES(?), (?)", normalString, lcString) if err != nil { log.Fatal(err) }

• Result: The database will contain"I AM UPPERCASED NORMAL STRING" and"i am uppercased magic string"

Example, Cont’d: Selecting Values rows, err := db.Query("SELECT * FROM test.hello") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var s1 LowercaseString err = rows.Scan(&s1) if err != nil { log.Print(err) } log.Print(s1) }

• Result: the app will log"i am uppercased normal string"and"i am uppercased magic string"

Example Source Code

• Please see Go+Database ebook for full source code and downloadable link, plus in-depth explanation: vividcortex.com/resources/building-database-driven-apps-with-go/

Extending the Example To Encryption• Use the standard crypto/aes library in Go’s stdlib

• Managing “secret” is an exercise for the reader!

• See https://vividcortex.com/blog/2014/11/11/encrypting-data-in-mysql-with-go/

block, err := aes.NewCipher(secret) if err != nil { return nil, err } ciphertext := make([]byte, aes.BlockSize+len(buf)) if _, err := io.ReadFull(rand.Reader, ciphertext[:aes.BlockSize]); err != nil { return nil, err } stream := cipher.NewCFBEncrypter(block, ciphertext[:aes.BlockSize]) stream.XORKeyStream(ciphertext[aes.BlockSize:], buf)

Extending To Additional Services (e.g. VividCortex’s Architecture, Vastly Over-Simplified)

Agents

Public API

Internal Service

Encryption BoundaryKMS

Questions

• Slides will be posted• I’m [email protected]• Thankyouverymuch

More Resources

Credits

• Lock https://www.flickr.com/photos/photosightfaces/8152791780/

• Agenda https://www.flickr.com/photos/puntodevista/639615047/

• Lock icon http://icons.iconarchive.com/icons/artua/mac/512/Lock-icon.png

• User icon simpleicons.com

• Key icon iconarchive.com

• Safe icon softicons.com