数据库数据使用md5加密_使用go中编写的数据加密保护数据库中的信息

数据库数据使用md5加密

Background

背景

Personally-identifying information (PII) is personal information that customers tell the service provider (e-commerce, financial service, etc…). As a service provider, it’s their responsibility to safekeeping the information. The attack vector can be from outside or inside the organization.

个人识别信息(PII)是客户告诉服务提供商的个人信息(电子商务,金融服务等)。 作为服务提供商,他们有责任保护信息。 攻击媒介可以来自组织外部或内部。

Objective

目的

Encrypt PII stored in the Database so information cannot be read by an employee within the organization, and the external attacker cannot read the information when they manage to steal the Database.

对存储在数据库中的PII进行加密,以使组织内的员工无法读取信息,并且外部攻击者在设法窃取数据库时也无法读取信息。

Strategy

战略

Data Writing

数据写入

  1. Read input (plaintext)

    读取输入(纯文本)
  2. Encrypt plaintext to ciphertext

    将纯文本加密为密文
  3. Write ciphertext to DB

    将密文写入数据库

Data Reading

资料读取

  1. Read ciphertext from DB

    从数据库读取密文
  2. Decrypt ciphertext to plaintext

    将密文解密为纯文本
  3. Send plaintext

    发送纯文本

Example

kingsman ==> sLR9ctALjY0rtAi8IvosScCtBE21gyMOBl3xHzi52Hbo+H3O

金斯曼==> sLR9ctALjY0rtAi8IvosScCtBE21gyMOBl3xHzi52Hbo + H3O

Encryption Algorithm

加密演算法

Symmetric-key is an appropriate algorithm in this scenario because:

在这种情况下,对称密钥是一种合适的算法,因为:

  1. Encryption process happens in one party (the same service to be precise). So no need to concerning key exchange with another party.

    加密过程发生在一方(确切地说是同一服务)中。 因此,无需考虑与另一方进行密钥交换。
  2. Symmetric encryption is faster compare to asymmetric encryption. Extra speed in data interaction service is always welcomed.

    与非对称加密相比,对称加密更快。 始终欢迎在数据交互服务中提高速度。
  3. Content size in each field of data can be huge. Symmetric encryption has a better capability for encrypting big sized data.

    每个数据字段中的内容量可能很大。 对称加密具有更好的加密大型数据的能力。

Sample Case

样品盒

Financial Service Provider: Registration Module

金融服务提供商:注册模块

Create New User Function

创建新的用户功能

func createData(id, name, nationalID, createTimeUnix string) (err error) {
_, err = DB.Exec(`
INSERT INTO
user (id, name, national_id, create_time_unix)
VALUES
("?", "?", "?", "?")
`, id, name, nationalID, createTimeUnix)
return
}

The function above is the minimum function to write data into the Database in Go.

上面的功能是在Go中将数据写入数据库的最小功能。

To limit the scope in the example case, every request contains 4 info:

为了限制示例中的范围,每个请求都包含4个信息:

  • id

    ID
  • name

    名称
  • nationalID (in USA this known as SSN, in Indonesia known by KTP)

    nationalID(在美国,这被称为SSN,在印度尼西亚,被KTP称为)
  • createTimeUnix

    createTimeUnix

We will come back to this function to integrate encryption function.

我们将回到此功能以集成加密功能。

Read User Data Function

读取用户数据功能

type User struct {
ID string
Name string
NationalID string
CreateTimeUnix string
}func readData(id string) (user User, err error) {
row := DB.QueryRow(`
SELECT
id, name, national_id, create_time_unix
FROM
user
WHERE
id = "?"`, id)
err = row.Scan(
&user.ID,
&user.Name,
&user.NationalID,
&user.CreateTimeUnix)
return
}

The code above explains two things, struct of User and function to read data from the Database. The function is the minimum code to read data and parse into an object without any data handling. The function will work fine given the provided with the correct table in the Database. We will come back to this function again to decrypt data from the Database.

上面的代码解释了两件事,用户结构和从数据库读取数据的功能。 该函数是无需任何数据处理即可读取数据并解析为对象的最少代码。 鉴于数据库中提供了正确的表,该功能将正常运行。 我们将再次回到此功能以解密数据库中的数据。

Data Encryption Function

数据加密功能

func encrypt(plaintext, passphrase string) (chipertext string, err error) {
block, _ := aes.NewCipher([]byte(passphrase))
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return
}ciphertextByte := gcm.Seal(
nonce,
nonce,
[]byte(plaintext),
nil)
chipertext = base64.StdEncoding.EncodeToString(ciphertextByte)return
}

The function above (encrypt) is a function to encrypt plain text. AES algorithm is used as a symmetrical key algorithm. Most of the modern language (Go, Node JS, Python, PHP) already have a library for AES. In essence, what’s written in code above are;

上面的函数( encrypt )是对纯文本进行加密的函数。 AES算法用作对称密钥算法。 大多数现代语言(Go,Node JS,Python,PHP)已经具有用于AES的库。 本质上,上面的代码写的是:

  1. Create AES Cipher (encryptor) using NewCipher function. Creating an AES Cipher required a passphrase. The passphrase is the human-readable format of the key.

    使用NewCipher函数创建AES密码(加密器)。 创建AES密码需要密码。 密码短语是密钥的人类可读格式。

  2. Ciphering plain text using Seal function. The output of Seal function is ciphertext in byte-formated which not a human-readable format. It is required to encode the ciphertext into base64 so it can be stored in the Database.

    使用Seal功能对纯文本进行加密。 Seal函数的输出是字节格式的密文,而不是人类可读的格式。 需要将密文编码为base64以便可以将其存储在数据库中。

We will use encrypt function to encrypt nationalID. The process will happen at createData function.

我们将使用encrypt功能对nationalID进行加密。 该过程将在createData函数处发生。

Data Decryption Function

数据解密功能

We need to create function to decrypt data stored in the Database. Decryption using the same key used during encryption.

我们需要创建函数来解密存储在数据库中的数据。 使用加密期间使用的相同密钥进行解密。

func decrypt(cipherText, key string) (plainText string, err error) {
// prepare cipher
keyByte := []byte(key)
block, err := aes.NewCipher(keyByte)
if err != nil {
return
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}
nonceSize := gcm.NonceSize()
process ciphertext
ciphertextByte, _ := base64.StdEncoding.DecodeString(cipherText)
nonce, ciphertextByteClean := ciphertextByte[:nonceSize], ciphertextByte[nonceSize:]
plaintextByte, err := gcm.Open(
nil,
nonce,
ciphertextByteClean,
nil)
if err != nil {
log.Println(err)
return
}
plainText = string(plaintextByte)
//
return
}

The function above (decrypt) is processing ciphertext and key into plaintext. There are 2 parts in the decrypt function.

上面的功能( decrypt )是将密文和密钥处理成明文。 decrypt功能分为两部分。

  1. The first part is preparing the cipher using AES and cipher library from Go. It required a key used during encryption.

    第一部分是使用AES和Go中的cipher库准备密码。 它需要加密期间使用的密钥。

  2. The second part is processing decryption. Data from the Database is string-type in base64 format. We need to format it into byte-type before running Open function. The output of Open is byte type so we need to format it into string-type to make it human-readable.

    第二部分是处理解密。 来自数据库的数据是base64格式的字符串类型。 在运行Open函数之前,我们需要将其格式化为字节类型。 Open的输出为字节类型,因此我们需要将其格式化为字符串类型以使其易于阅读。

Unit Test

单元测试

Before we integrate encrypt and decrypt function into CRUD DB function. we must create the unit test to verify the output of decrypt function is the same as plaintext.

在将encryptdecrypt功能集成到CRUD DB功能之前。 我们必须创建单元测试以验证decrypt函数的输出与纯文本相同。

func Test_encrypt(t *testing.T) {
type args struct {
plaintext string
key string
}
tests := []struct {
name string
args args
}{
{
name: "happy test",
args: args{
plaintext: "kingsman",
key: "04076d64bdb6fcf31706eea85ec98431"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// encrypt the plaintext
ciphertext, err := encrypt(tt.args.plaintext, tt.args.key)
if err != nil {
t.Errorf("encrypt() error = %v", err)
return
}
t.Logf("ciphertext = %s", ciphertext)
decrypt the ciphertext from previous encrypt function
plaintext, err := decrypt(ciphertext, tt.args.key)
if err != nil {
t.Errorf("encrypt() error = %v", err)
return
}
t.Logf("plaintext = %s", plaintext)
compare the initial plaintext with output of previous decrypt function
if plaintext != tt.args.plaintext {
t.Errorf("plaintext = %v, want %v", plaintext, tt.args.plaintext)
}
//
})
}
}

We are running encrypt function to encrypt plaintext (“kingsman”). The output is ciphertext which we will pass into decrypt function. The expected output is the string-type value equal to the plaintext. Lastly, we compare the output with plaintext as verification. The test result is the following;

我们正在运行encrypt功能来加密纯文本(“ kingsman”)。 输出为密文,我们将其传递给decrypt函数。 预期的输出是等于明文的字符串类型值。 最后,我们将输出与纯文本进行比较以进行验证。 测试结果如下:

db-encryption go test -v -timeout 30s
=== RUN Test_encrypt
=== RUN Test_encrypt/happy_test
--- PASS: Test_encrypt (0.00s)
--- PASS: Test_encrypt/happy_test (0.00s)
main_test.go:78: ciphertext = sLR9ctALjY0rtAi8IvosScCtBE21gyMOBl3xHzi52Hbo+H3O
main_test.go:87: plaintext = kingsman
PASS
ok github.com/purnaresa/secureme/db-encryption 0.005s

Integration

积分

It is time to integrate to CRUD DB Function once we are confident that both encrypt and decrypt function working as expected. Basically we must encrypt the data right before we insert it into the Database.

一旦我们确信encryptdecrypt功能均能按预期工作,就可以将其集成到CRUD DB Function了。 基本上,我们必须在将数据插入数据库之前对数据进行加密。

func createData(id, name, nationalID, createTimeUnix string) (err error) {
// encryption
nationalID, _ = encrypt(nationalID, masterKey)
//_, err = DB.Exec(`
INSERT INTO
user (id, name, national_id, create_time_unix)
VALUES
("?", "?", "?", "?")
`, id, name, nationalID, createTimeUnix)return
}

In the above code, we are running encryption for nationalID. To simplify the example we are ignoring the error output.

在上面的代码中,我们正在为nationalID.运行加密nationalID. 为了简化示例,我们忽略了错误输出。

And for decryption, we must run decrypt function right after we read data from the Database.

对于解密,我们必须在从数据库读取数据后立即运行decrypt功能。

func readData(id string) (user User, err error) {
row := DB.QueryRow(`
SELECT
id, name, national_id, create_time_unix
FROM
user
WHERE
id = "?"`, id)err = row.Scan(
&user.ID,
&user.Name,
&user.NationalID,
&user.CreateTimeUnix)// decryption
user.NationalID, _ = decrypt(user.NationalID, masterKey)
//
return
}

Summary

摘要

The sample provided in this project is the encryption of a single value. But it can be used to encrypt several values. AES mechanism is safe to use as long as the key is well guarded. This project is considered as a minimum requirement for Securing Information in Database because there are only two factors implemented (algorithm and key).

该项目中提供的示例是单个值的加密。 但是它可以用于加密多个值。 只要密钥受到良好的保护,AES机制就可以安全使用。 由于仅实现了两个因素(算法和密钥),因此该项目被认为是保护数据库中信息的最低要求。

Full code can be downloaded from Github: https://github.com/purnaresa/secureme/blob/master/db-encryption/main.go

完整的代码可以从Github下载: https : //github.com/purnaresa/secureme/blob/master/db-encryption/main.go

We can improve more security factors such as salt so even if the key is stolen, an attacker couldn’t utilize the key to decrypt the ciphertext.What else do you think we can add to the next post?

我们可以改善salt等安全性因素,因此即使密钥被盗,攻击者也无法利用该密钥解密密文。您认为我们还能在下一篇文章中添加什么?

If you found this article helpful for you, don’t forget to follow my account.Xoxo

如果您发现本文对您有所帮助,请不要忘记关注我的帐户。

翻译自: https://medium.com/swlh/securing-information-in-database-using-data-encryption-written-in-go-4b2754214050

数据库数据使用md5加密

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值