Skip to content

Instantly share code, notes, and snippets.

@olekukonko
Forked from icub3d/example_wrapio.go
Created February 4, 2014 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olekukonko/8799183 to your computer and use it in GitHub Desktop.
Save olekukonko/8799183 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"github.com/icub3d/wrapio"
"io"
"io/ioutil"
"log"
"strings"
)
func main() {
// These are the messages we'll encrypt and decrypt.
messages := []string{
"this is the first message.",
"I wonder about this encryption thing. Is it safe?",
"01234567890123456789012345678901",
"012345678901234567890123456789012",
"0123456789012345678901234567890",
"See what I did there?",
}
// Make a key.
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
log.Fatalln("failed to generate key:", err)
}
for _, message := range messages {
// We are going to use the AES cipher.
fmt.Println("original text:", message)
b, err := aes.NewCipher(key)
if err != nil {
log.Fatalln("failed to make aes cipher:", err)
}
// CBC needs an initialization vector.
iv := make([]byte, b.BlockSize())
if _, err := rand.Read(iv); err != nil {
log.Fatalln("failed to generate iv:", err)
}
bme := cipher.NewCBCEncrypter(b, iv)
var in, block, last, crypt io.Reader
// Wrap our message as a reader. In normal circumstances, this
// may come from a file, a network socket, etc.
in = strings.NewReader(message)
// We want to only send slices whose lengths are a multiple of the
// block size (it will panic otherwise).
block = wrapio.NewBlockReader(bme.BlockSize(), in)
// The last block may not have a full block, so we should pad it.
last = wrapio.NewLastFuncReader(pad, block)
// Finally, we encrypt the data.
crypt = wrapio.NewFuncReader(func(p []byte) {
bme.CryptBlocks(p, p)
}, last)
// We'll just use ioutil.ReadAll to get the cipher text. Under
// normal circumstances, this may be passed along to something
// that reads the encrypted data. For example, you may pass it to
// net/http's client.Post() to send the file to a web server.
ct, err := ioutil.ReadAll(crypt)
if err != nil {
log.Fatalln("failed to read all:", err)
}
fmt.Println("cipher text: ", ct)
// On the other end we'll decrypt it. We'll just use a
// bytes.Reader but we could wrap net/http's response.Body if we
// were pulling our encrypted file from a web server.
bmd := cipher.NewCBCDecrypter(b, iv)
in = bytes.NewReader(ct)
// We want to only send slices whose lengths are a multiple of the
// block size (it will panic otherwise).
block = wrapio.NewBlockReader(bmd.BlockSize(), in)
// Decrypt the data we get.
crypt = wrapio.NewFuncReader(func(p []byte) {
bmd.CryptBlocks(p, p)
}, block)
// The last block may have padding at the end, so remove it.
last = wrapio.NewLastFuncReader(unpad, crypt)
// We'll use ReadAll to get the plain text. If we wanted to save
// it to a file, we could use io.Copy.
pt, err := ioutil.ReadAll(last)
if err != nil {
log.Fatalln("failed to read all:", err)
}
fmt.Println("plain text: ", string(pt))
fmt.Println()
}
}
func unpad(p []byte) []byte {
l := len(p)
nl := l - 1
for ; nl >= 0; nl-- {
if p[nl] == 0x80 {
break
}
if p[nl] != 0x00 || (l-nl) > aes.BlockSize {
return p
}
}
return p[:nl]
}
func pad(m []byte) []byte {
l := len(m)
pl := aes.BlockSize - l%aes.BlockSize
m = append(m, 0x80)
for x := 0; x < pl-1; x++ {
m = append(m, 0x00)
}
return m
}
original text: this is the first message.
cipher text: [248 56 179 225 52 13 186 243 230 109 125 13 6 128 74 169 184 225 203 51 54 8 167 44 131 6 105 216 153 114 149 171]
plain text: this is the first message.
original text: I wonder about this encryption thing. Is it safe?
cipher text: [112 179 152 130 163 139 28 186 49 186 79 59 68 75 188 252 131 82 254 100 19 88 24 104 53 75 89 60 65 12 4 97 112 123 110 61 199 70 44 44 3 18 254 137 159 88 2 115 9 119 18 8 91 236 243 52 236 15 119 90 25 198 126 38]
plain text: I wonder about this encryption thing. Is it safe?
original text: 01234567890123456789012345678901
cipher text: [246 63 173 106 166 72 36 106 154 154 87 239 12 41 241 78 249 30 200 151 16 187 132 93 160 240 159 92 105 113 55 196 64 54 228 237 166 56 155 254 238 177 246 43 105 171 233 97]
plain text: 01234567890123456789012345678901
original text: 012345678901234567890123456789012
cipher text: [67 222 139 133 127 216 7 201 34 227 197 91 87 253 55 123 174 73 166 21 243 164 199 47 21 229 41 193 81 105 128 191 209 203 91 183 33 187 80 3 255 25 198 68 193 27 173 207]
plain text: 012345678901234567890123456789012
original text: 0123456789012345678901234567890
cipher text: [8 55 11 134 24 147 188 111 226 141 243 88 91 52 118 127 223 123 26 187 42 154 175 240 139 158 81 44 94 181 238 52]
plain text: 0123456789012345678901234567890
original text: See what I did there?
cipher text: [104 143 126 41 215 113 122 104 68 149 43 105 7 28 189 79 85 39 76 182 93 67 190 234 11 164 135 213 220 41 253 149]
plain text: See what I did there?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment