Skip to content

Instantly share code, notes, and snippets.

@gasserk
Created August 4, 2015 14:35
Show Gist options
  • Save gasserk/1186cd8ef495bd8b9438 to your computer and use it in GitHub Desktop.
Save gasserk/1186cd8ef495bd8b9438 to your computer and use it in GitHub Desktop.
Simple (and flawed) example of Crypto and REST in Go
package main
import (
"fmt"
"net/http"
"regexp"
"code.google.com/p/gorest"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"io"
)
const (
KEY = "Very Simple RESTful Crypto Demo." // 32 byte key for AES-256
)
type SSNService struct {
gorest.RestService `root:"/ssn/"`
ssnEncrypt gorest.EndPoint `method:"GET" path:"/encrypt/{ptssn64:string}" output:"string"`
ssnDecrypt gorest.EndPoint `method:"GET" path:"/decrypt/{ctssn64:string}" output:"string"`
}
func (serv SSNService) SsnEncrypt(ptssn64 string) string {
ptssn, _ := base64.URLEncoding.DecodeString(ptssn64)
fmt.Println("Value to be encrypted: " + string(ptssn))
var validSSN = regexp.MustCompile(`^\d{9}$`)
if !validSSN.MatchString(string(ptssn)) {
panic("Value being encrypted is not a valid SSN.")
}
ctssn, _ := encrypt(ptssn)
ctssn64 := base64.URLEncoding.EncodeToString(ctssn)
return ctssn64
}
func (serv SSNService) SsnDecrypt(ctssn64 string) string {
ctssn, _ := base64.URLEncoding.DecodeString(ctssn64)
ptssn, _ := decrypt(ctssn)
fmt.Println("Decrypted value: " + string(ptssn))
var validSSN = regexp.MustCompile(`^\d{9}$`)
if !validSSN.MatchString(string(ptssn)) {
panic("Value decrypted is not a valid SSN.")
}
ptssn64 := base64.URLEncoding.EncodeToString(ptssn)
fmt.Println(ptssn64)
return ptssn64
}
func main() {
gorest.RegisterService(new(SSNService))
http.Handle("/", gorest.Handle())
http.ListenAndServe(":8080", nil)
}
// Adapted from http://stackoverflow.com/questions/18817336/golang-encrypting-a-string-with-aes-and-base64
func encrypt(text []byte) ([]byte, error) {
block, err := aes.NewCipher([]byte(KEY))
if err != nil {
return nil, err
}
b := base64.StdEncoding.EncodeToString(text)
ciphertext := make([]byte, aes.BlockSize+len(b))
//Re-seed initialization vector and append to block each time
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
return ciphertext, nil
}
func decrypt(text []byte) ([]byte, error) {
block, err := aes.NewCipher([]byte(KEY))
if err != nil {
return nil, err
}
if len(text) < aes.BlockSize {
return nil, errors.New("Ciphertext is too short.")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
data, err := base64.StdEncoding.DecodeString(string(text))
if err != nil {
return nil, err
}
return data, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment