Last active
September 27, 2023 19:43
-
-
Save ayubmalik/2c973c2a7ae7e0d22ece7f5c4dfbd726 to your computer and use it in GitHub Desktop.
Go (golang) crypto sample using cipher.StreamWriter and cipher.StreamReader to wrap io.Writer and io.Reader with AES encryption.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/aes" | |
"crypto/cipher" | |
"crypto/md5" | |
"crypto/rand" | |
"errors" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"os" | |
"strings" | |
) | |
// EncryptedWriter wraps w with an OFB cipher stream. | |
func EncryptedWriter(key string, w io.Writer) (*cipher.StreamWriter, error) { | |
// generate random initial value | |
iv := make([]byte, aes.BlockSize) | |
if _, err := io.ReadFull(rand.Reader, iv); err != nil { | |
return nil, err | |
} | |
// write clear IV to allow for decryption | |
n, err := w.Write(iv) | |
if err != nil || n != len(iv) { | |
return nil, errors.New("could not write initial value") | |
} | |
block, err := newBlock(key) | |
if err != nil { | |
return nil, err | |
} | |
stream := cipher.NewOFB(block, iv) | |
return &cipher.StreamWriter{S: stream, W: w}, nil | |
} | |
// EncryptedReader wraps r with an OFB cipher stream. | |
func EncryptedReader(key string, r io.Reader) (*cipher.StreamReader, error) { | |
// read initial value | |
iv := make([]byte, aes.BlockSize) | |
n, err := r.Read(iv) | |
if err != nil || n != len(iv) { | |
return nil, errors.New("could not read initial value") | |
} | |
block, err := newBlock(key) | |
if err != nil { | |
return nil, err | |
} | |
stream := cipher.NewOFB(block, iv) | |
return &cipher.StreamReader{S: stream, R: r}, nil | |
} | |
func newBlock(key string) (cipher.Block, error) { | |
hash := md5.Sum([]byte(key)) | |
block, err := aes.NewCipher(hash[:]) | |
if err != nil { | |
return nil, err | |
} | |
return block, nil | |
} | |
func main() { | |
// Load your secret key from a safe | |
// place and use for encrypt/decrypt | |
secretKey := "1234567890abcdefghijk" | |
/******************************************/ | |
/* example to encrypt/decrypt to a string */ | |
/******************************************/ | |
var sb strings.Builder | |
w, err := EncryptedWriter(secretKey, &sb) | |
if err != nil { | |
panic(err) | |
} | |
// as w is a StreamWriter we can write/encrypt directly to it | |
w.Write([]byte("Hello gophers!")) | |
encrypted := sb.String() | |
fmt.Printf("encrypted message = %s\n", encrypted) | |
// as r is a StreamReader we can decrypt/read directly from it | |
r, err := EncryptedReader(secretKey, strings.NewReader(encrypted)) | |
if err != nil { | |
panic(err) | |
} | |
decrypted, _ := ioutil.ReadAll(r) | |
fmt.Printf("decrypted message = %s\n", decrypted) | |
/*********************************************************/ | |
/* example to encrypt/decrypt to a file */ | |
/* skipping error handling and file.Close() for examples */ | |
/*********************************************************/ | |
file, err := os.Create("/tmp/encmsg.txt") | |
if err != nil { | |
panic(err) | |
} | |
w, _ = EncryptedWriter(secretKey, file) | |
io.WriteString(w, "Hello again gophers!") | |
file, _ = os.Open("/tmp/encmsg.txt") // use flags/file param for prod code | |
r, _ = EncryptedReader(secretKey, file) | |
contents, _ := ioutil.ReadAll(r) | |
fmt.Printf("contents of decrypted file = %s\n", contents) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks