github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/network/tunnel/mucp/crypto.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); 2 // you may not use this file except in compliance with the License. 3 // You may obtain a copy of the License at 4 // 5 // https://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, 9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 // See the License for the specific language governing permissions and 11 // limitations under the License. 12 // 13 // Original source: github.com/micro/go-micro/v3/network/tunnel/mucp/crypto.go 14 15 package mucp 16 17 import ( 18 "crypto/aes" 19 "crypto/cipher" 20 "crypto/rand" 21 "crypto/sha256" 22 23 "github.com/tickoalcantara12/micro/v3/service/network/tunnel" 24 "github.com/oxtoacart/bpool" 25 ) 26 27 var ( 28 // the local buffer pool 29 // gcmStandardNonceSize from crypto/cipher/gcm.go is 12 bytes 30 // 100 - is max size of pool 31 noncePool = bpool.NewBytePool(100, 12) 32 ) 33 34 // hash hahes the data into 32 bytes key and returns it 35 // hash uses sha256 underneath to hash the supplied key 36 func hash(key []byte) []byte { 37 sum := sha256.Sum256(key) 38 return sum[:] 39 } 40 41 // Encrypt encrypts data and returns the encrypted data 42 func Encrypt(gcm cipher.AEAD, data []byte) ([]byte, error) { 43 var err error 44 45 // get new byte array the size of the nonce from pool 46 // NOTE: we might use smaller nonce size in the future 47 nonce := noncePool.Get() 48 if _, err = rand.Read(nonce); err != nil { 49 return nil, err 50 } 51 defer noncePool.Put(nonce) 52 53 // NOTE: we prepend the nonce to the payload 54 // we need to do this as we need the same nonce 55 // to decrypt the payload when receiving it 56 return gcm.Seal(nonce, nonce, data, nil), nil 57 } 58 59 // Decrypt decrypts the payload and returns the decrypted data 60 func newCipher(key []byte) (cipher.AEAD, error) { 61 var err error 62 63 // generate a new AES cipher using our 32 byte key for decrypting the message 64 c, err := aes.NewCipher(hash(key)) 65 if err != nil { 66 return nil, err 67 } 68 69 // gcm or Galois/Counter Mode, is a mode of operation 70 // for symmetric key cryptographic block ciphers 71 // - https://en.wikipedia.org/wiki/Galois/Counter_Mode 72 gcm, err := cipher.NewGCM(c) 73 if err != nil { 74 return nil, err 75 } 76 77 return gcm, nil 78 } 79 80 func Decrypt(gcm cipher.AEAD, data []byte) ([]byte, error) { 81 var err error 82 83 nonceSize := gcm.NonceSize() 84 85 if len(data) < nonceSize { 86 return nil, tunnel.ErrDecryptingData 87 } 88 89 // NOTE: we need to parse out nonce from the payload 90 // we prepend the nonce to every encrypted payload 91 nonce, ciphertext := data[:nonceSize], data[nonceSize:] 92 ciphertext, err = gcm.Open(ciphertext[:0], nonce, ciphertext, nil) 93 if err != nil { 94 return nil, err 95 } 96 97 return ciphertext, nil 98 }