LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 币圈百科 > 保护数据库信息如何用Go语言+对称密钥做数据加密?

保护数据库信息如何用Go语言+对称密钥做数据加密?

2020-01-31 区块链大本营 来源:区块链网络

个人识别信息(PII)是客户告知服务提供商(电子商务、金融服务等)的个人信息。作为服务提供者,他们有责任妥善保管信息。针对PII的攻击可能来自外部,也可能来自服务商内部。

为了抵御针对PII的攻击,将存储在数据库中的PII加密,这样组织内的员工就无法读取信息,外部攻击者在设法窃取数据库时也无法读取信息。

如何解决这一问题呢?本文就将为大家介绍用 Go语言为数据加密的策略。

一、数据写入

1、读取输入信息(明文)

2、将明文加密为密文

3、将密文写入到数据库中

二、数据读取

1、从数据库中读取密文

2、将密文解密为明文

3、发送明文

三、加密算法

对称密钥非常适合该任务的应用场景,其具有以下特点:

1、加密过程发生在一个缔约方(准确地说是同一服务)。因此无需与另一方交换密钥,双方使用同一密钥。

2、与非对称加密相比,对称加密速度更快,其带来的额外速度在数据交互服务总是受欢迎的。

3、每个数据字段中的文本可能很大。对称加密在加密大数据时具有更好的性能。

加密示例

kingsman ==> sLR9ctALjY0rtAi8IvosScCtBE21gyMOBl3xHzi52Hbo+H3O

四、示例

我们将以金融服务提供商的注册模块为例,展示如何对数据进行简单的加密保存和解密读取。

1、新用户创建函数

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}

上面的函数是用Go语言将数据写入数据库的最小函数。

这里将示例中的信息范围限制在4个属性:id,姓名,nationalID,createtimeunix。之后会用这个函数来集成加密函数。

2、数据读取函数

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}

上述代码定义了用户对象的结构体,以及一个从数据库中读取数据的函数。函数是读取数据并将其解析为对象而无需任何数据处理的最小代码。如果提供了数据库中正确的表,该函数将正常工作。我们将在之后用这个函数来解密数据库中的数据。

3、数据加密函数

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}

上面的函数(encrypt)是用于加密纯文本的函数。AES是一种对称加密算法,大部分现代计算机语言(Go,NodeJS,PYTHON,PHP)都含有AES算法的支持库。上面代码的主要含义是:

(1)使用NewCipher函数来创建明文(passphrase)的密码(加密器),该函数接受可阅读形式的明文作为输入。

(2)使用密封函数(Seal)来加密纯文本,Seal函数的输出是字节格式的密文,是不可阅读的形式,需要将密文编码为base64格式,以便存储在数据库中。

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

4、数据解密函数

我们需要创建一个解密函数来对存储在数据库中的数据进行解密,由于是对称密钥,因此解密使用的密钥和加密相同。函数如下:

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}

上面的函数(decrypt)主要功能是将密文和密钥重新处理为明文。该函数主要由两部分构成:

(1)第一部分是使用Go语言中的AES和cipher库准备密码。该过程需要使用加密过程中使用的密钥。

(2)第二部分主要进行解密。数据库中的数据是base64格式的字符串类型。在运行Open函数之前,我们需要将其格式转换为字节类型。Open函数的输出是字节类型的,因此我们需要将它格式化为string类型,这样就得到了可阅读的明文。

5、单元测试

在我们将加密和解密函数集成到CRUD DB函数之前,我们必须通过单元测试来验证解密函数的输出是否与明文相同:

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)????????????}????????????//????????})????}}

首先通过加密函数(encrypt)来对明文(“kingsman”)进行加密。然后将加密函数输出的密文再输入到解密函数中,预期的输出是等于明文的字符串类型值。最后,我们将输出结果与纯文本进行对比验证:

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?=?kingsmanPASSok??????github.com/purnaresa/secureme/db-encryption?????0.005s

6、函数集成

当我们确信加密和解密函数都能正常工作时,就该将他们集成到CRUD DB函数了。基本上数据在保存到数据库之前都需要进行加密。

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}

在上面的代码中,我们为nationalID进行加密,为了简化这个例子,我们忽略了错误输出。对于解密,我们必须在从数据库读取数据后立即运行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}

总结

上述代码中提供的是对单个值进行加密的示例,同样的方法也可以用于多个值的加密。只要密钥得到很好的保护(不泄露),AES机制就可以安全使用。上述方案被认为是数据库信息安全的最低要求,因为它只实现了两个基本要素(算法和密钥)。

此外,我们可以使用更多的方法来确保数据安全,比如salt,这样即使密钥被盗,攻击者也不能利用密钥来解密密文。

完整代码:

https://github.com/purnaresa/secureme/blob/master/db-encryption/main.go

原文链接:

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

【END】

—-

编译者/作者:区块链大本营

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...