From 896ad654c8629931e5873a08f28762a102c7a762 Mon Sep 17 00:00:00 2001 From: InfiniteLoopSpace <35842605+InfiniteLoopSpace@users.noreply.github.com> Date: Wed, 14 Nov 2018 13:45:02 +0100 Subject: [PATCH] Add base64 encoding for S/MIME --- b64/b64.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 b64/b64.go diff --git a/b64/b64.go b/b64/b64.go new file mode 100644 index 0000000..29f4eb7 --- /dev/null +++ b/b64/b64.go @@ -0,0 +1,78 @@ +//Package b64 encodes base64 and does formating for S/MIME +package b64 + +import ( + "bytes" + "encoding/base64" + "io" +) + +// From https://golang.org/src/encoding/pem/pem.go + +//Takes an byteslice and outputs the base64 encoded version with linebreaks. The constant PemLineLength defines the lenght of the lines. +func EncodeBase64(in []byte) ([]byte, error) { + + var buf bytes.Buffer + var breaker lineBreaker + breaker.out = &buf + + b64 := base64.NewEncoder(base64.StdEncoding, &breaker) + if _, err := b64.Write(in); err != nil { + return nil, err + } + b64.Close() + breaker.Close() + + return buf.Bytes(), nil + +} + +//Lenght of the lines in the output of the function EncodeBase64. +const PemLineLength = 64 + +type lineBreaker struct { + line [PemLineLength]byte + used int + out io.Writer +} + +var nl = []byte{'\n'} + +func (l *lineBreaker) Write(b []byte) (n int, err error) { + if l.used+len(b) < PemLineLength { + copy(l.line[l.used:], b) + l.used += len(b) + return len(b), nil + } + + n, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + excess := PemLineLength - l.used + l.used = 0 + + n, err = l.out.Write(b[0:excess]) + if err != nil { + return + } + + n, err = l.out.Write(nl) + if err != nil { + return + } + + return l.Write(b[excess:]) +} + +func (l *lineBreaker) Close() (err error) { + if l.used > 0 { + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + _, err = l.out.Write(nl) + } + + return +}