github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/test/chaincodes/AuctionApp/image_proc_api.go (about) 1 /****************************************************************** 2 Copyright IT People Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 16 ******************************************************************/ 17 18 /////////////////////////////////////////////////////////////////////// 19 // Author : IT People - Mohan Venkataraman - image API 20 // Purpose: Explore the Hyperledger/fabric and understand 21 // how to write an chain code, application/chain code boundaries 22 // The code is not the best as it has just hammered out in a day or two 23 // Feedback and updates are appreciated 24 /////////////////////////////////////////////////////////////////////// 25 26 package main 27 28 import ( 29 "bufio" 30 "bytes" 31 "crypto/aes" 32 "crypto/cipher" 33 "crypto/rand" 34 "errors" 35 "fmt" 36 "image" 37 "image/gif" 38 "image/jpeg" 39 "image/png" 40 "io" 41 "net/http" 42 "os" 43 ) 44 45 /////////////////////////////////////////////////////////// 46 // Convert Image to []bytes and viceversa 47 // Detect Image Filetype 48 // Image Function to read an image and create a byte array 49 // Currently only PNG images are supported 50 /////////////////////////////////////////////////////////// 51 func ImageToByteArray(imageFile string) ([]byte, string) { 52 53 file, err := os.Open(imageFile) 54 55 if err != nil { 56 fmt.Println("imageToByteArray() : cannot OPEN image file ", err) 57 return nil, string("imageToByteArray() : cannot OPEN image file ") 58 } 59 60 defer file.Close() 61 62 fileInfo, _ := file.Stat() 63 var size int64 = fileInfo.Size() 64 bytes := make([]byte, size) 65 66 // read file into bytes 67 buff := bufio.NewReader(file) 68 _, err = buff.Read(bytes) 69 70 if err != nil { 71 fmt.Println("imageToByteArray() : cannot READ image file") 72 return nil, string("imageToByteArray() : cannot READ image file ") 73 } 74 75 filetype := http.DetectContentType(bytes) 76 fmt.Println("imageToByteArray() : ", filetype) 77 //filetype := GetImageType(bytes) 78 79 return bytes, filetype 80 } 81 82 ////////////////////////////////////////////////////// 83 // If Valid fileType, will have "image" as first word 84 ////////////////////////////////////////////////////// 85 func GetImageType(buff []byte) string { 86 filetype := http.DetectContentType(buff) 87 88 switch filetype { 89 case "image/jpeg", "image/jpg": 90 return filetype 91 92 case "image/gif": 93 return filetype 94 95 case "image/png": 96 return filetype 97 98 case "application/pdf": // not image, but application ! 99 filetype = "application/pdf" 100 default: 101 filetype = "Unknown" 102 } 103 return filetype 104 } 105 106 //////////////////////////////////////////////////////////// 107 // Converts a byteArray into an image and saves it 108 // into an appropriate file 109 // It is important to get the file type before saving the 110 // file by call the GetImageType 111 //////////////////////////////////////////////////////////// 112 func ByteArrayToImage(imgByte []byte, imageFile string) error { 113 114 // convert []byte to image for saving to file 115 img, _, _ := image.Decode(bytes.NewReader(imgByte)) 116 117 fmt.Println("ProcessQueryResult ByteArrayToImage : proceeding to create image ") 118 119 //save the imgByte to file 120 out, err := os.Create(imageFile) 121 122 if err != nil { 123 fmt.Println("ByteArrayToImage() : cannot CREATE image file ", err) 124 return errors.New("ByteArrayToImage() : cannot CREATE image file ") 125 } 126 fmt.Println("ProcessRequestType ByteArrayToImage : proceeding to Encode image ") 127 128 //err = png.Encode(out, img) 129 filetype := http.DetectContentType(imgByte) 130 131 switch filetype { 132 case "image/jpeg", "image/jpg": 133 var opt jpeg.Options 134 opt.Quality = 100 135 err = jpeg.Encode(out, img, &opt) 136 137 case "image/gif": 138 var opt gif.Options 139 opt.NumColors = 256 140 err = gif.Encode(out, img, &opt) 141 142 case "image/png": 143 err = png.Encode(out, img) 144 145 default: 146 err = errors.New("Only PMNG, JPG and GIF Supported ") 147 } 148 149 if err != nil { 150 fmt.Println("ByteArrayToImage() : cannot ENCODE image file ", err) 151 return errors.New("ByteArrayToImage() : cannot ENCODE image file ") 152 } 153 154 // everything ok 155 fmt.Println("Image file generated and saved to ", imageFile) 156 return nil 157 } 158 159 /////////////////////////////////////////////////////////////////////// 160 // Encryption and Decryption Section 161 // Images will be Encrypted and stored and the key will be part of the 162 // certificate that is provided to the Owner 163 /////////////////////////////////////////////////////////////////////// 164 165 const ( 166 AESKeyLength = 32 // AESKeyLength is the default AES key length 167 NonceSize = 24 // NonceSize is the default NonceSize 168 ) 169 170 /////////////////////////////////////////////////// 171 // GetRandomBytes returns len random looking bytes 172 /////////////////////////////////////////////////// 173 func GetRandomBytes(len int) ([]byte, error) { 174 key := make([]byte, len) 175 176 _, err := rand.Read(key) 177 if err != nil { 178 return nil, err 179 } 180 181 return key, nil 182 } 183 184 //////////////////////////////////////////////////////////// 185 // GenAESKey returns a random AES key of length AESKeyLength 186 // 3 Functions to support Encryption and Decryption 187 // GENAESKey() - Generates AES symmetric key 188 // Encrypt() Encrypts a [] byte 189 // Decrypt() Decryts a [] byte 190 //////////////////////////////////////////////////////////// 191 func GenAESKey() ([]byte, error) { 192 return GetRandomBytes(AESKeyLength) 193 } 194 195 func PKCS5Pad(src []byte) []byte { 196 padding := aes.BlockSize - len(src)%aes.BlockSize 197 pad := bytes.Repeat([]byte{byte(padding)}, padding) 198 return append(src, pad...) 199 } 200 201 func PKCS5Unpad(src []byte) []byte { 202 len := len(src) 203 unpad := int(src[len-1]) 204 return src[:(len - unpad)] 205 } 206 207 func Decrypt(key []byte, ciphertext []byte) []byte { 208 209 // Create the AES cipher 210 block, err := aes.NewCipher(key) 211 if err != nil { 212 panic(err) 213 } 214 215 // Before even testing the decryption, 216 // if the text is too small, then it is incorrect 217 if len(ciphertext) < aes.BlockSize { 218 panic("Text is too short") 219 } 220 221 // Get the 16 byte IV 222 iv := ciphertext[:aes.BlockSize] 223 224 // Remove the IV from the ciphertext 225 ciphertext = ciphertext[aes.BlockSize:] 226 227 // Return a decrypted stream 228 stream := cipher.NewCFBDecrypter(block, iv) 229 230 // Decrypt bytes from ciphertext 231 stream.XORKeyStream(ciphertext, ciphertext) 232 233 return ciphertext 234 } 235 236 func Encrypt(key []byte, ba []byte) []byte { 237 238 // Create the AES cipher 239 block, err := aes.NewCipher(key) 240 if err != nil { 241 panic(err) 242 } 243 244 // Empty array of 16 + ba length 245 // Include the IV at the beginning 246 ciphertext := make([]byte, aes.BlockSize+len(ba)) 247 248 // Slice of first 16 bytes 249 iv := ciphertext[:aes.BlockSize] 250 251 // Write 16 rand bytes to fill iv 252 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 253 panic(err) 254 } 255 256 // Return an encrypted stream 257 stream := cipher.NewCFBEncrypter(block, iv) 258 259 // Encrypt bytes from ba to ciphertext 260 stream.XORKeyStream(ciphertext[aes.BlockSize:], ba) 261 262 return ciphertext 263 }