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

Add support for passing non-printable character as key #2851

Merged
merged 1 commit into from Aug 29, 2019

Conversation

sinhaashish
Copy link
Contributor

This feature enables the users to pass non-printable character as encrytion-key by encoding it.
Example :
If the encryption keys contains a non printable character like tab :
--encrypt-key "play/test/=32byteslongsecretke mustbegiven1".
The user need to encode using base64 and pass the encoded string as the key.
--encrypt-key "play/test=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="

Tested case:

case 1.  Copy encrypted file from s3 to play using  nonprintable character in key ( "s3/encryptedfile/=32byteslongsecreabcdefg	givenn21,play/encrypt=32byteslongsecretke	mustbegiven1") .
 The key contains tab character

a)  ./mc mb s3/encryptedfile
b)  ./mc cp  --encrypt-key "s3/encryptedfile/=MzJieXRlc2xvbmdzZWNyZWFiY2RlZmcJZ2l2ZW5uMjE=" ~/Downloads/test.csv s3/encryptedfile/test.csv
c) ./mc mb  play/encrypt
d) ./mc cp --recursive --encrypt-key "s3/encryptedfile/=MzJieXRlc2xvbmdzZWNyZWFiY2RlZmcJZ2l2ZW5uMjE=,play/encrypt/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  s3/encryptedfile/   play/encrypt/
e) ./mc head  --encrypt-key "play/encrypt/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/encrypt/test.csv
f) ./mc cat  --encrypt-key "play/encrypt/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/encrypt/test.csv


Case 2.  Copy encrypted file from s3 to play using  32 byte string  as key and key for play is encoded as it contains a non printable character  ( "s3/documents/=32byteslongsecretkeymustbegiven1,play/normalstr/=32byteslongsecretke	mustbegiven1") .
a) ./mc mb s3/normalstr
b)  ./mc cp  --encrypt-key "s3/normalstr/=32byteslongsecretkeymustbegiven1" ~/Downloads/test.csv s3/normalstr/test.csv
c) ./mc mb  play/normalstr
d) ./mc cp --recursive --encrypt-key "s3/normalstr/=32byteslongsecretkeymustbegiven1,play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  s3/normalstr/   play/normalstr/
e) ./mc head  --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/normalstr/test.csv
f) ./mc cat  --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/normalstr/test.csv
g) ./mc stat  --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/normalstr/test.csv
h) ./mc rm  --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/normalstr/test.csv
i) cat ~/Downloads/10000.csv | mc pipe  --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE=" play/normalstr/10000.csv
j) ./mc mirror --overwrite --insecure   --encrypt-key "play/normalstr/=MzJieXRlc2xvbmdzZWNyZXRrZQltdXN0YmVnaXZlbjE="  play/normalstr/ myminio/sinha/

Closes #2678

@codecov-io
Copy link

codecov-io commented Aug 7, 2019

Codecov Report

Merging #2851 into master will increase coverage by 0.14%.
The diff coverage is 69.69%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2851      +/-   ##
==========================================
+ Coverage     9.9%   10.04%   +0.14%     
==========================================
  Files         140      140              
  Lines       13522    13555      +33     
==========================================
+ Hits         1339     1362      +23     
- Misses      12016    12026      +10     
  Partials      167      167
Impacted Files Coverage Δ
cmd/cat-main.go 18.39% <ø> (ø) ⬆️
cmd/mirror-main.go 0% <ø> (ø) ⬆️
cmd/stat-main.go 0% <ø> (ø) ⬆️
cmd/head-main.go 0% <ø> (ø) ⬆️
cmd/cp-main.go 3.4% <0%> (-0.05%) ⬇️
cmd/common-methods.go 9.12% <79.31%> (+9.12%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update af7d551...46ae6fe. Read the comment docs.

cmd/stat-main.go Show resolved Hide resolved
cmd/mirror-main.go Outdated Show resolved Hide resolved
cmd/head-main.go Outdated
@@ -68,6 +68,10 @@ EXAMPLES:

2. Display only first line from server encrypted object on Amazon S3.
$ {{.HelpName}} -n 1 --encrypt-key 's3/csv-data=32byteslongsecretkeymustbegiven1' s3/csv-data/population.csv

3. Display only first line from server encrypted object on Amazon S3. In case the encryption key contains non-printable characcter like tab, pass the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/characcter/character

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

cmd/cat-main.go Outdated
@@ -69,6 +69,10 @@ EXAMPLES:

4. Save an encrypted object from Amazon S3 cloud storage to a local file.
$ {{.HelpName}} --encrypt-key 's3/mysql-backups=32byteslongsecretkeymustbegiven1' s3/mysql-backups/backups-201810.gz > /mnt/data/recent.gz

5. Display the content of encrypted object. In case the encryption key contains non-printable characcter like tab, pass the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/characcter/character

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

cmd/cp-main.go Outdated

if sseKeys != "" {
sseKeys, err = getDecodedKey(sseKeys)
fatalIf(err, "Unable to decrypt encryption keys.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Unable to decrypt encryption keys." is incorrect as you are just trying to decode the base64 encoded key.
"Unable to parse encryption key" is better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

secretValue := encryptString[1]
decodedString, e := base64.StdEncoding.DecodeString(secretValue)
if e != nil {
return "", probe.NewError(errors.New("key should be 32 bytes long or if the key is encoded; then decoded value must be of 32 bytes long"))
Copy link
Contributor

@poornas poornas Aug 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return "", probe.NewError(errors.New("key should be 32 bytes long or if the key is encoded; then decoded value must be of 32 bytes long"))
return "", probe.NewError(errors.New("key should be 32 bytes long or if the key is base64 encoded; then decoded value must be 32 bytes long"))
```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

}

if len(decodedString) != 32 {
keyString = keyString + sse
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't you be returning an error here because plain text key is not 32 bytes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is taken care in parseEncryptionKeys .

err error
status bool
}{
//success scenerio the key contains non printable (tab) character as key
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/scenerio/scenario across this test case

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be fixed in more than one place. Please fix them everywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

encryptString := strings.SplitN(sse, "=", 2)
pre := encryptString[0]
secretValue := encryptString[1]
decodedString, e := base64.StdEncoding.DecodeString(secretValue)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to have this part in a function. Other than that, the first part should be to check if the length of secretValue is 32, then it is plain text and use it as is. Only otherwise do you proceed to decode and if the decode fails, you return error. Else check if the decoded length is 32, then use that, else return error

Now, what will happen is that even if you encode a string of length 10 and pass it in command line, this code is going to use it as plain text as the decoded string length will be 10 and this code will assume that it is a plain text secret key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a function func parseKey(sseKeys string) (sse string, err *probe.Error) to achieve this functionality.

Copy link
Collaborator

@kannappanr kannappanr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the code based on the comments made in this PR

return sseKeys, nil
}
decodedString, e := base64.StdEncoding.DecodeString(secretValue)
if e != nil || len(decodedString) != 32 || len(secretValue) != 32 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if e != nil || len(decodedString) != 32 || len(secretValue) != 32 {
if e != nil || len(decodedString) != 32 {

@sinhaashish sinhaashish force-pushed the non-printable-char branch 2 times, most recently from 30e2bb4 to 65eb30f Compare August 14, 2019 11:43
}
decodedString, e := base64.StdEncoding.DecodeString(secretValue)
if e != nil || len(decodedString) != 32 {
return "", probe.NewError(errors.New("key should be 32 bytes long or if the key is base64 encoded; then decoded value must be 32 bytes long"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return "", probe.NewError(errors.New("key should be 32 bytes long or if the key is base64 encoded; then decoded value must be 32 bytes long"))
return "", probe.NewError(errors.New("Encryption key should be 32 bytes plain text key or 64 bytes base64 encoded key"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

// {"play/documents/=32byteslongsecretkeymustbegiven1,s3/documents/=MzJieXRlc2xvbmdzZWNyZWFiY2RlZmcJZ2l2ZW5uMjE=", "play/documents/=32byteslongsecretkeymustbegiven1,s3/documents/=32byteslongsecreabcdefg givenn21", nil, true},
// // decoded key less than 32 char and conatin non printable (tab) character
// {"s3/documents/=MzJieXRlc2xvbmdzZWNyZWFiY2RlZmcJZ2l2ZW5uMjE", "", errors.New("key should be 32 bytes long or if the key is base64 encoded; then decoded value must be 32 bytes long"), false},
// // normal key less than 32 character
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like these tests need to be uncommented

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@sinhaashish
Copy link
Contributor Author

@poornas @kannappanr PTAL

@@ -28,11 +28,11 @@ func TestParseMetaData(t *testing.T) {
err error
status bool
}{
// success scenerio using ; as delimitter
// success scenario using ; as delimitter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please fix typo delimitter -> delimiter wherever they occur

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for pointing it out. Done with the change.

poornas
poornas previously approved these changes Aug 28, 2019
Copy link
Contributor

@poornas poornas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

kannappanr
kannappanr previously approved these changes Aug 29, 2019
Copy link
Collaborator

@kannappanr kannappanr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested. LGTM

@harshavardhana harshavardhana merged commit 1582b1c into minio:master Aug 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] mc accepts only printable characters as encryption keys on the command line
5 participants