-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
308 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
Copyright 2017 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
/* | ||
This code is based on the article https://www.thepolyglotdeveloper.com/2018/02/encrypt-decrypt-data-golang-application-crypto-packages/ | ||
written by Nic Raboy. | ||
Gzip compression/decompression has ben added as there as there are issues with txt records longer than | ||
255 characters and encryption + base64 encoding adds some characters to the resulting text record. | ||
*/ | ||
|
||
package endpoint | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/rand" | ||
"encoding/base64" | ||
"fmt" | ||
"io" | ||
|
||
log "github.com/sirupsen/logrus" | ||
) | ||
|
||
// Decompress data | ||
func DecompressData(data []byte) (resData []byte, err error) { | ||
gz, err := gzip.NewReader(bytes.NewBuffer(data)) | ||
if err != nil { | ||
return data, err | ||
} | ||
defer gz.Close() | ||
var b bytes.Buffer | ||
if _, err = b.ReadFrom(gz); err != nil { | ||
return data, err | ||
} | ||
return b.Bytes(), nil | ||
} | ||
|
||
// Compress data | ||
func CompressData(data []byte) (compressedData []byte, err error) { | ||
var b bytes.Buffer | ||
gz, err := gzip.NewWriterLevel(&b, gzip.BestCompression) | ||
if err != nil { | ||
return data, nil | ||
} | ||
// defer gz.Close() | ||
if _, err = gz.Write(data); err != nil { | ||
return data, nil | ||
} | ||
|
||
if err = gz.Flush(); err != nil { | ||
return data, nil | ||
} | ||
|
||
if err = gz.Close(); err != nil { | ||
return data, nil | ||
} | ||
|
||
return b.Bytes(), nil | ||
} | ||
|
||
// Encrypt data using the supplied AES key | ||
func EncryptText(text string, aesKey []byte) (string, error) { | ||
block, _ := aes.NewCipher(aesKey) | ||
gcm, err := cipher.NewGCM(block) | ||
if err != nil { | ||
return text, err | ||
} | ||
nonce := make([]byte, gcm.NonceSize()) | ||
if _, err = io.ReadFull(rand.Reader, nonce); err != nil { | ||
return text, err | ||
} | ||
data := []byte(text) | ||
data, err = CompressData(data) | ||
if err != nil { | ||
log.Debugf("Failed to compress data based on the text %#v. Got error %#v.", text, err) | ||
} | ||
cipherdata := gcm.Seal(nonce, nonce, data, nil) | ||
return base64.StdEncoding.EncodeToString(cipherdata), nil | ||
} | ||
|
||
// Decrypt data using a supplied AES encryption key | ||
func DecryptText(text string, aesKey []byte) (string, error) { | ||
block, err := aes.NewCipher(aesKey) | ||
if err != nil { | ||
return text, err | ||
} | ||
gcm, err := cipher.NewGCM(block) | ||
if err != nil { | ||
return text, err | ||
} | ||
nonceSize := gcm.NonceSize() | ||
data, err := base64.StdEncoding.DecodeString(text) | ||
if err != nil { | ||
return text, err | ||
} | ||
if len(data) <= nonceSize { | ||
return text, fmt.Errorf("The encoded data from text %#v is shorter than %#v bytes and can't be decoded", text, nonceSize) | ||
} | ||
nonce, ciphertext := data[:nonceSize], data[nonceSize:] | ||
plaindata, err := gcm.Open(nil, nonce, ciphertext, nil) | ||
if err != nil { | ||
return text, err | ||
} | ||
plaindata, err = DecompressData(plaindata) | ||
if err != nil { | ||
log.Debugf("Failed to decompress data based on the base64 encoded text %#v. Got error %#v.", text, err) | ||
} | ||
return string(plaindata), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
Copyright 2017 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package endpoint | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEncrypt(t *testing.T) { | ||
// Verify that text encryption and decryption works | ||
aesKey := []byte("s%zF`.*'5`9.AhI2!B,.~hmbs^.*TL?;") | ||
plaintext := "Til pigerene havde han skemtsomme ord, han spøkte med byens børn, han svingede sydvesten og sprang ombord; så heiste han fokken, og hjem han for i solskin, den gamle ørn." | ||
encryptedtext, err := EncryptText(plaintext, aesKey) | ||
require.NoError(t, err) | ||
decryptedtext, err := DecryptText(encryptedtext, aesKey) | ||
require.NoError(t, err) | ||
if plaintext != decryptedtext { | ||
t.Errorf("Original plain text %#v differs from the resulting decrypted text %#v", plaintext, decryptedtext) | ||
} | ||
|
||
// Verify that decrypt returns an error and unmodified data if wrong AES encryption key is used | ||
decryptedtext, err = DecryptText(encryptedtext, []byte("s'J!jD`].LC?g&Oa11AgTub,j48ts/96")) | ||
require.Error(t, err) | ||
if decryptedtext != encryptedtext { | ||
t.Error("Data decryption failed, but decrypt still didn't return the original input") | ||
} | ||
|
||
// Verify that decrypt returns an error and unmodified data if unencrypted input is is supplied | ||
decryptedtext, err = DecryptText(plaintext, aesKey) | ||
require.Error(t, err) | ||
if plaintext != decryptedtext { | ||
t.Errorf("Data decryption failed, but decrypt still didn't return the original input. Original input %#v, returned data %#v", plaintext, decryptedtext) | ||
} | ||
|
||
// Verify that a known encrypted text is decrypted to what is expected | ||
encryptedtext = "TIBnEeYWYd+sffKZ6Wk3Js0pR58TbsFxhXUc+6jzgS4AXCb+NSuKjnlRqp6e5imh5b1hrxWmecrI/QNJzC6o/2U5FZfxY5CjSqhIbCV/gWWkgK1Qd1ohzCO4tzkF5fwGCxSW715NLDUImg6xE4D/hI2pY8wcATnvv4qUw6eR78kDzfn4cwO1IeS/HmFn+ASldPvY6Y3JHCSlbvWTekfRrknHJeLHIsPW5yZVPZCq29xGEe+A29Y=" | ||
decryptedtext, err = DecryptText(encryptedtext, aesKey) | ||
require.NoError(t, err) | ||
if decryptedtext != plaintext { | ||
t.Error("Decryption of text didn't result in expected plaintext result.") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.