Created
September 20, 2016 05:59
-
-
Save DanGe42/f27d924d9d4b850164372065e5a6fb4b to your computer and use it in GitHub Desktop.
A go/crypto + protobuf sample
This file contains 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/rand" | |
"encoding/base64" | |
"errors" | |
"fmt" | |
"io" | |
playground "playground/gcmcrypto/proto" | |
proto "github.com/golang/protobuf/proto" | |
) | |
var ( | |
ErrEncrypt = errors.New("secret: encryption failed") | |
ErrDecrypt = errors.New("secret: decryption failed") | |
) | |
// GenerateNonce creates a new random nonce. | |
func GenerateNonce(nonceSize int) (*[]byte, error) { | |
nonce := make([]byte, nonceSize) | |
_, err := io.ReadFull(rand.Reader, nonce[:]) | |
if err != nil { | |
return nil, err | |
} | |
return &nonce, nil | |
} | |
// Encrypt secures a message using AES-GCM. | |
func Encrypt(key, message []byte) ([]byte, error) { | |
c, err := aes.NewCipher(key) | |
if err != nil { | |
return nil, ErrEncrypt | |
} | |
gcm, err := cipher.NewGCM(c) | |
if err != nil { | |
return nil, ErrEncrypt | |
} | |
nonce, err := GenerateNonce(gcm.NonceSize()) | |
if err != nil { | |
return nil, ErrEncrypt | |
} | |
// Seal will append the output to the first argument; the usage | |
// here appends the ciphertext to the nonce. The final parameter | |
// is any additional data to be authenticated. | |
out := gcm.Seal(*nonce, *nonce, message, nil) | |
return out, nil | |
} | |
func Decrypt(key, message []byte) ([]byte, error) { | |
c, err := aes.NewCipher(key) | |
if err != nil { | |
return nil, ErrDecrypt | |
} | |
gcm, err := cipher.NewGCM(c) | |
if err != nil { | |
return nil, ErrDecrypt | |
} | |
nonce := make([]byte, gcm.NonceSize()) | |
copy(nonce, message) | |
out, err := gcm.Open(message[:0], nonce, message[gcm.NonceSize():], nil) | |
if err != nil { | |
return nil, ErrDecrypt | |
} | |
return out, nil | |
} | |
func generateToken(n int) (string, error) { | |
buf := make([]byte, n) | |
if _, err := rand.Read(buf); err != nil { | |
return "", err | |
} | |
return base64.URLEncoding.EncodeToString(buf), nil | |
} | |
func mustGenerateToken(n int) string { | |
if encoded, err := generateToken(n); err != nil { | |
panic(err) | |
} else { | |
return encoded | |
} | |
} | |
func main() { | |
key := []byte("00000000000000000000000000000000") | |
message := &playground.Context{ | |
Token1: proto.String("prefix1-prefix-" + mustGenerateToken(16)), | |
Token2: proto.String(mustGenerateToken(8)), | |
} | |
fmt.Println(message) | |
messageBytes, err := proto.Marshal(message) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println("len(message) = ", len(messageBytes)) | |
fmt.Println("len(base64(message) = ", len(base64.URLEncoding.EncodeToString(messageBytes))) | |
encrypted, err := Encrypt(key, messageBytes) | |
if err != nil { | |
panic(err) | |
} | |
b64message := base64.URLEncoding.EncodeToString(encrypted) | |
fmt.Printf("%s [len=%d]\n", b64message, len(b64message)) | |
unb64message, err := base64.URLEncoding.DecodeString(b64message) | |
if err != nil { | |
panic(err) | |
} | |
decrypted, err := Decrypt(key, unb64message) | |
origMessage := &playground.Context{} | |
if err := proto.Unmarshal(decrypted, origMessage); err != nil { | |
panic(err) | |
} | |
fmt.Println(origMessage) | |
} |
This file contains 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
# go run main.go | |
token1:"prefix1-prefix-Nra3S_677EweBAolqEm49w==" token2:"9j01k3uv8ns=" | |
len(message) = 55 | |
len(base64(message) = 76 | |
eQ4zNLYAKpi_ImNDZEvycf-rkU7E6frJh4SuB_LJkwtrO1MCrWony5CMWHqrv1NyKTVyAJF4LAexRc8apY0DDj9fMCqOOZAOtqXdcuODvfaFMxw= [len=112] | |
token1:"prefix1-prefix-Nra3S_677EweBAolqEm49w==" token2:"9j01k3uv8ns=" |
This file contains 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
// Code generated by protoc-gen-go. | |
// source: test.proto | |
// DO NOT EDIT! | |
/* | |
Package proto is a generated protocol buffer package. | |
It is generated from these files: | |
test.proto | |
It has these top-level messages: | |
Context | |
*/ | |
package proto | |
import proto1 "github.com/golang/protobuf/proto" | |
import fmt "fmt" | |
import math "math" | |
// Reference imports to suppress errors if they are not otherwise used. | |
var _ = proto1.Marshal | |
var _ = fmt.Errorf | |
var _ = math.Inf | |
// This is a compile-time assertion to ensure that this generated file | |
// is compatible with the proto package it is being compiled against. | |
// A compilation error at this line likely means your copy of the | |
// proto package needs to be updated. | |
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package | |
type Context struct { | |
Token1 *string `protobuf:"bytes,1,opt,name=token1" json:"token1,omitempty"` | |
Token2 *string `protobuf:"bytes,2,opt,name=token2" json:"token2,omitempty"` | |
XXX_unrecognized []byte `json:"-"` | |
} | |
func (m *Context) Reset() { *m = Context{} } | |
func (m *Context) String() string { return proto1.CompactTextString(m) } | |
func (*Context) ProtoMessage() {} | |
func (*Context) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | |
func (m *Context) GetToken1() string { | |
if m != nil && m.Token1 != nil { | |
return *m.Token1 | |
} | |
return "" | |
} | |
func (m *Context) GetToken2() string { | |
if m != nil && m.Token2 != nil { | |
return *m.Token2 | |
} | |
return "" | |
} | |
func init() { | |
proto1.RegisterType((*Context)(nil), "gemcrypto.proto.Context") | |
} | |
func init() { proto1.RegisterFile("test.proto", fileDescriptor0) } | |
var fileDescriptor0 = []byte{ | |
// 109 bytes of a gzipped FileDescriptorProto | |
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e, | |
0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4f, 0x4f, 0xcd, 0x4d, 0x2e, 0xaa, 0x2c, 0x28, | |
0xc9, 0x87, 0x08, 0x28, 0x59, 0x72, 0xb1, 0x3b, 0xe7, 0xe7, 0x95, 0xa4, 0x56, 0x94, 0x08, 0x89, | |
0x71, 0xb1, 0x95, 0xe4, 0x67, 0xa7, 0xe6, 0x19, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, | |
0x79, 0x70, 0x71, 0x23, 0x09, 0x26, 0x24, 0x71, 0x23, 0x27, 0x99, 0x28, 0xa9, 0x82, 0x9c, 0xc4, | |
0xca, 0xf4, 0xa2, 0xfc, 0xd2, 0xbc, 0x14, 0xfd, 0xf4, 0x64, 0xa8, 0xc1, 0xfa, 0x60, 0x83, 0x01, | |
0x01, 0x00, 0x00, 0xff, 0xff, 0x4f, 0xba, 0x63, 0x1b, 0x76, 0x00, 0x00, 0x00, | |
} |
This file contains 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
syntax = "proto2"; | |
package gemcrypto.proto; | |
option go_package = "playground/gcmcrypto/proto"; | |
message Context { | |
optional string token1 = 1; | |
optional string token2 = 2; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment