summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/minio/minio-go/pkg/encrypt
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-05-17 16:51:25 -0400
committerGitHub <noreply@github.com>2017-05-17 16:51:25 -0400
commitd103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26 (patch)
treedbde13123c6add150448f7b75753ac022d862475 /vendor/github.com/minio/minio-go/pkg/encrypt
parentcd23b8139a9463b67e3096744321f6f4eb0ca40a (diff)
downloadchat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.tar.gz
chat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.tar.bz2
chat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.zip
Upgrading server dependancies (#6431)
Diffstat (limited to 'vendor/github.com/minio/minio-go/pkg/encrypt')
-rw-r--r--vendor/github.com/minio/minio-go/pkg/encrypt/cbc.go284
-rw-r--r--vendor/github.com/minio/minio-go/pkg/encrypt/interface.go50
-rw-r--r--vendor/github.com/minio/minio-go/pkg/encrypt/keys.go165
3 files changed, 499 insertions, 0 deletions
diff --git a/vendor/github.com/minio/minio-go/pkg/encrypt/cbc.go b/vendor/github.com/minio/minio-go/pkg/encrypt/cbc.go
new file mode 100644
index 000000000..7670e68f4
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/encrypt/cbc.go
@@ -0,0 +1,284 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2017 Minio, Inc.
+ *
+ * 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 encrypt
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/base64"
+ "errors"
+ "io"
+)
+
+// Crypt mode - encryption or decryption
+type cryptMode int
+
+const (
+ encryptMode cryptMode = iota
+ decryptMode
+)
+
+// CBCSecureMaterials encrypts/decrypts data using AES CBC algorithm
+type CBCSecureMaterials struct {
+
+ // Data stream to encrypt/decrypt
+ stream io.Reader
+
+ // Last internal error
+ err error
+
+ // End of file reached
+ eof bool
+
+ // Holds initial data
+ srcBuf *bytes.Buffer
+
+ // Holds transformed data (encrypted or decrypted)
+ dstBuf *bytes.Buffer
+
+ // Encryption algorithm
+ encryptionKey Key
+
+ // Key to encrypts/decrypts data
+ contentKey []byte
+
+ // Encrypted form of contentKey
+ cryptedKey []byte
+
+ // Initialization vector
+ iv []byte
+
+ // matDesc - currently unused
+ matDesc []byte
+
+ // Indicate if we are going to encrypt or decrypt
+ cryptMode cryptMode
+
+ // Helper that encrypts/decrypts data
+ blockMode cipher.BlockMode
+}
+
+// NewCBCSecureMaterials builds new CBC crypter module with
+// the specified encryption key (symmetric or asymmetric)
+func NewCBCSecureMaterials(key Key) (*CBCSecureMaterials, error) {
+ if key == nil {
+ return nil, errors.New("Unable to recognize empty encryption properties")
+ }
+ return &CBCSecureMaterials{
+ srcBuf: bytes.NewBuffer([]byte{}),
+ dstBuf: bytes.NewBuffer([]byte{}),
+ encryptionKey: key,
+ matDesc: []byte("{}"),
+ }, nil
+
+}
+
+// SetupEncryptMode - tells CBC that we are going to encrypt data
+func (s *CBCSecureMaterials) SetupEncryptMode(stream io.Reader) error {
+ // Set mode to encrypt
+ s.cryptMode = encryptMode
+
+ // Set underlying reader
+ s.stream = stream
+
+ s.eof = false
+ s.srcBuf.Reset()
+ s.dstBuf.Reset()
+
+ var err error
+
+ // Generate random content key
+ s.contentKey = make([]byte, aes.BlockSize*2)
+ if _, err := rand.Read(s.contentKey); err != nil {
+ return err
+ }
+ // Encrypt content key
+ s.cryptedKey, err = s.encryptionKey.Encrypt(s.contentKey)
+ if err != nil {
+ return err
+ }
+ // Generate random IV
+ s.iv = make([]byte, aes.BlockSize)
+ if _, err = rand.Read(s.iv); err != nil {
+ return err
+ }
+ // New cipher
+ encryptContentBlock, err := aes.NewCipher(s.contentKey)
+ if err != nil {
+ return err
+ }
+
+ s.blockMode = cipher.NewCBCEncrypter(encryptContentBlock, s.iv)
+
+ return nil
+}
+
+// SetupDecryptMode - tells CBC that we are going to decrypt data
+func (s *CBCSecureMaterials) SetupDecryptMode(stream io.Reader, iv string, key string) error {
+ // Set mode to decrypt
+ s.cryptMode = decryptMode
+
+ // Set underlying reader
+ s.stream = stream
+
+ // Reset
+ s.eof = false
+ s.srcBuf.Reset()
+ s.dstBuf.Reset()
+
+ var err error
+
+ // Get IV
+ s.iv, err = base64.StdEncoding.DecodeString(iv)
+ if err != nil {
+ return err
+ }
+
+ // Get encrypted content key
+ s.cryptedKey, err = base64.StdEncoding.DecodeString(key)
+ if err != nil {
+ return err
+ }
+
+ // Decrypt content key
+ s.contentKey, err = s.encryptionKey.Decrypt(s.cryptedKey)
+ if err != nil {
+ return err
+ }
+
+ // New cipher
+ decryptContentBlock, err := aes.NewCipher(s.contentKey)
+ if err != nil {
+ return err
+ }
+
+ s.blockMode = cipher.NewCBCDecrypter(decryptContentBlock, s.iv)
+ return nil
+}
+
+// GetIV - return randomly generated IV (per S3 object), base64 encoded.
+func (s *CBCSecureMaterials) GetIV() string {
+ return base64.StdEncoding.EncodeToString(s.iv)
+}
+
+// GetKey - return content encrypting key (cek) in encrypted form, base64 encoded.
+func (s *CBCSecureMaterials) GetKey() string {
+ return base64.StdEncoding.EncodeToString(s.cryptedKey)
+}
+
+// GetDesc - user provided encryption material description in JSON (UTF8) format.
+func (s *CBCSecureMaterials) GetDesc() string {
+ return string(s.matDesc)
+}
+
+// Fill buf with encrypted/decrypted data
+func (s *CBCSecureMaterials) Read(buf []byte) (n int, err error) {
+ // Always fill buf from bufChunk at the end of this function
+ defer func() {
+ if s.err != nil {
+ n, err = 0, s.err
+ } else {
+ n, err = s.dstBuf.Read(buf)
+ }
+ }()
+
+ // Return
+ if s.eof {
+ return
+ }
+
+ // Fill dest buffer if its length is less than buf
+ for !s.eof && s.dstBuf.Len() < len(buf) {
+
+ srcPart := make([]byte, aes.BlockSize)
+ dstPart := make([]byte, aes.BlockSize)
+
+ // Fill src buffer
+ for s.srcBuf.Len() < aes.BlockSize*2 {
+ _, err = io.CopyN(s.srcBuf, s.stream, aes.BlockSize)
+ if err != nil {
+ break
+ }
+ }
+
+ // Quit immediately for errors other than io.EOF
+ if err != nil && err != io.EOF {
+ s.err = err
+ return
+ }
+
+ // Mark current encrypting/decrypting as finished
+ s.eof = (err == io.EOF)
+
+ if s.eof && s.cryptMode == encryptMode {
+ if srcPart, err = pkcs5Pad(s.srcBuf.Bytes(), aes.BlockSize); err != nil {
+ s.err = err
+ return
+ }
+ } else {
+ _, _ = s.srcBuf.Read(srcPart)
+ }
+
+ // Crypt srcPart content
+ for len(srcPart) > 0 {
+
+ // Crypt current part
+ s.blockMode.CryptBlocks(dstPart, srcPart[:aes.BlockSize])
+
+ // Unpad when this is the last part and we are decrypting
+ if s.eof && s.cryptMode == decryptMode {
+ dstPart, err = pkcs5Unpad(dstPart, aes.BlockSize)
+ if err != nil {
+ s.err = err
+ return
+ }
+ }
+
+ // Send crypted data to dstBuf
+ if _, wErr := s.dstBuf.Write(dstPart); wErr != nil {
+ s.err = wErr
+ return
+ }
+ // Move to the next part
+ srcPart = srcPart[aes.BlockSize:]
+ }
+ }
+ return
+}
+
+// Unpad a set of bytes following PKCS5 algorithm
+func pkcs5Unpad(buf []byte, blockSize int) ([]byte, error) {
+ len := len(buf)
+ if len == 0 {
+ return nil, errors.New("buffer is empty")
+ }
+ pad := int(buf[len-1])
+ if pad > len || pad > blockSize {
+ return nil, errors.New("invalid padding size")
+ }
+ return buf[:len-pad], nil
+}
+
+// Pad a set of bytes following PKCS5 algorithm
+func pkcs5Pad(buf []byte, blockSize int) ([]byte, error) {
+ len := len(buf)
+ pad := blockSize - (len % blockSize)
+ padText := bytes.Repeat([]byte{byte(pad)}, pad)
+ return append(buf, padText...), nil
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/encrypt/interface.go b/vendor/github.com/minio/minio-go/pkg/encrypt/interface.go
new file mode 100644
index 000000000..2fd75033f
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/encrypt/interface.go
@@ -0,0 +1,50 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2017 Minio, Inc.
+ *
+ * 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 encrypt implements a generic interface to encrypt any stream of data.
+// currently this package implements two types of encryption
+// - Symmetric encryption using AES.
+// - Asymmetric encrytion using RSA.
+package encrypt
+
+import "io"
+
+// Materials - provides generic interface to encrypt any stream of data.
+type Materials interface {
+
+ // Returns encrypted/decrypted data, io.Reader compatible.
+ Read(b []byte) (int, error)
+
+ // Get randomly generated IV, base64 encoded.
+ GetIV() (iv string)
+
+ // Get content encrypting key (cek) in encrypted form, base64 encoded.
+ GetKey() (key string)
+
+ // Get user provided encryption material description in
+ // JSON (UTF8) format. This is not used, kept for future.
+ GetDesc() (desc string)
+
+ // Setup encrypt mode, further calls of Read() function
+ // will return the encrypted form of data streamed
+ // by the passed reader
+ SetupEncryptMode(stream io.Reader) error
+
+ // Setup decrypted mode, further calls of Read() function
+ // will return the decrypted form of data streamed
+ // by the passed reader
+ SetupDecryptMode(stream io.Reader, iv string, key string) error
+}
diff --git a/vendor/github.com/minio/minio-go/pkg/encrypt/keys.go b/vendor/github.com/minio/minio-go/pkg/encrypt/keys.go
new file mode 100644
index 000000000..8814845e3
--- /dev/null
+++ b/vendor/github.com/minio/minio-go/pkg/encrypt/keys.go
@@ -0,0 +1,165 @@
+/*
+ * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2017 Minio, Inc.
+ *
+ * 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 encrypt
+
+import (
+ "crypto/aes"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "errors"
+)
+
+// Key - generic interface to encrypt/decrypt a key.
+// We use it to encrypt/decrypt content key which is the key
+// that encrypt/decrypt object data.
+type Key interface {
+ // Encrypt data using to the set encryption key
+ Encrypt([]byte) ([]byte, error)
+ // Decrypt data using to the set encryption key
+ Decrypt([]byte) ([]byte, error)
+}
+
+// SymmetricKey - encrypts data with a symmetric master key
+type SymmetricKey struct {
+ masterKey []byte
+}
+
+// Encrypt passed bytes
+func (s *SymmetricKey) Encrypt(plain []byte) ([]byte, error) {
+ // Initialize an AES encryptor using a master key
+ keyBlock, err := aes.NewCipher(s.masterKey)
+ if err != nil {
+ return []byte{}, err
+ }
+
+ // Pad the key before encryption
+ plain, _ = pkcs5Pad(plain, aes.BlockSize)
+
+ encKey := []byte{}
+ encPart := make([]byte, aes.BlockSize)
+
+ // Encrypt the passed key by block
+ for {
+ if len(plain) < aes.BlockSize {
+ break
+ }
+ // Encrypt the passed key
+ keyBlock.Encrypt(encPart, plain[:aes.BlockSize])
+ // Add the encrypted block to the total encrypted key
+ encKey = append(encKey, encPart...)
+ // Pass to the next plain block
+ plain = plain[aes.BlockSize:]
+ }
+ return encKey, nil
+}
+
+// Decrypt passed bytes
+func (s *SymmetricKey) Decrypt(cipher []byte) ([]byte, error) {
+ // Initialize AES decrypter
+ keyBlock, err := aes.NewCipher(s.masterKey)
+ if err != nil {
+ return nil, err
+ }
+
+ var plain []byte
+ plainPart := make([]byte, aes.BlockSize)
+
+ // Decrypt the encrypted data block by block
+ for {
+ if len(cipher) < aes.BlockSize {
+ break
+ }
+ keyBlock.Decrypt(plainPart, cipher[:aes.BlockSize])
+ // Add the decrypted block to the total result
+ plain = append(plain, plainPart...)
+ // Pass to the next cipher block
+ cipher = cipher[aes.BlockSize:]
+ }
+
+ // Unpad the resulted plain data
+ plain, err = pkcs5Unpad(plain, aes.BlockSize)
+ if err != nil {
+ return nil, err
+ }
+
+ return plain, nil
+}
+
+// NewSymmetricKey generates a new encrypt/decrypt crypto using
+// an AES master key password
+func NewSymmetricKey(b []byte) *SymmetricKey {
+ return &SymmetricKey{masterKey: b}
+}
+
+// AsymmetricKey - struct which encrypts/decrypts data
+// using RSA public/private certificates
+type AsymmetricKey struct {
+ publicKey *rsa.PublicKey
+ privateKey *rsa.PrivateKey
+}
+
+// Encrypt data using public key
+func (a *AsymmetricKey) Encrypt(plain []byte) ([]byte, error) {
+ cipher, err := rsa.EncryptPKCS1v15(rand.Reader, a.publicKey, plain)
+ if err != nil {
+ return nil, err
+ }
+ return cipher, nil
+}
+
+// Decrypt data using public key
+func (a *AsymmetricKey) Decrypt(cipher []byte) ([]byte, error) {
+ cipher, err := rsa.DecryptPKCS1v15(rand.Reader, a.privateKey, cipher)
+ if err != nil {
+ return nil, err
+ }
+ return cipher, nil
+}
+
+// NewAsymmetricKey - generates a crypto module able to encrypt/decrypt
+// data using a pair for private and public key
+func NewAsymmetricKey(privData []byte, pubData []byte) (*AsymmetricKey, error) {
+ // Parse private key from passed data
+ priv, err := x509.ParsePKCS8PrivateKey(privData)
+ if err != nil {
+ return nil, err
+ }
+ privKey, ok := priv.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("not a valid private key")
+ }
+
+ // Parse public key from passed data
+ pub, err := x509.ParsePKIXPublicKey(pubData)
+ if err != nil {
+ return nil, err
+ }
+
+ pubKey, ok := pub.(*rsa.PublicKey)
+ if !ok {
+ return nil, errors.New("not a valid public key")
+ }
+
+ // Associate the private key with the passed public key
+ privKey.PublicKey = *pubKey
+
+ return &AsymmetricKey{
+ publicKey: pubKey,
+ privateKey: privKey,
+ }, nil
+}