forked from OneOfOne/go-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added crypto.NewReader/NewWriter to support stream (en|de)cryption.
- Loading branch information
Showing
4 changed files
with
178 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package crypto | ||
|
||
import ( | ||
"bytes" | ||
"crypto/des" | ||
"io/ioutil" | ||
"testing" | ||
) | ||
|
||
var ( | ||
iv = GenerateAesIV() | ||
key = GenerateKey(192, []byte(`I'm Jack's Wasted Life`)) | ||
msg = []byte(`I'm Jack's Complete Lack Of Surprise.`) | ||
) | ||
|
||
func TestAes(t *testing.T) { | ||
b := &bytes.Buffer{} | ||
enc, err := NewAesWriter(b, iv, key) | ||
if err != nil { | ||
t.Error(err) | ||
return | ||
} | ||
enc.Write(msg) | ||
emsg := b.Bytes() | ||
dec, err := NewAesReader(b, iv, key) | ||
if err != nil { | ||
t.Error(err) | ||
return | ||
} | ||
|
||
dmsg, _ := ioutil.ReadAll(dec) | ||
t.Logf("\niv (%2d): %x\nkey (%2d): %x\nenc (%d): %x\ndec (%d): %s\n", len(iv), iv, len(key), key, len(emsg), emsg, len(dmsg), dmsg) | ||
} | ||
|
||
func BenchmarkAes(b *testing.B) { | ||
buf := &bytes.Buffer{} | ||
enc, _ := NewAesWriter(buf, iv, key) | ||
dec, _ := NewAesReader(buf, iv, key) | ||
for i := 0; i < b.N; i++ { | ||
enc.Write(msg) | ||
ioutil.ReadAll(dec) | ||
} | ||
} | ||
|
||
func BenchmarkTripleDes(b *testing.B) { | ||
buf := &bytes.Buffer{} | ||
enc, _ := NewWriter(buf, iv[:8], key, des.NewTripleDESCipher) | ||
dec, _ := NewReader(buf, iv[:8], key, des.NewTripleDESCipher) | ||
for i := 0; i < b.N; i++ { | ||
enc.Write(msg) | ||
ioutil.ReadAll(dec) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"crypto/rand" | ||
"crypto/sha256" | ||
) | ||
|
||
type CryptoInitilizer func(key []byte) (cipher.Block, error) | ||
|
||
// ZeroSlice sets all the bytes in a slice to 0, should be used on keys and IVs. | ||
func ZeroSlice(p []byte) { | ||
for i := range p { | ||
p[i] = 0 | ||
} | ||
} | ||
|
||
// GenerateIV generates an IV for the given blocksize | ||
func GenerateIV(blockSize int) (p []byte) { | ||
p = make([]byte, blockSize) | ||
if _, err := rand.Read(p); err != nil { | ||
panic(err) | ||
} | ||
return | ||
} | ||
|
||
// GenerateAesIV generates an IV with AES's BlockSize | ||
func GenerateAesIV() []byte { | ||
return GenerateIV(aes.BlockSize) | ||
} | ||
|
||
// GenerateKey generates a hashed key based on the number of bits | ||
func GenerateKey(bits int, key []byte) []byte { | ||
if bits%64 != 0 || bits < 128 { | ||
panic("bits % 64 != 0 || bits < 128") | ||
} | ||
n := bits / 8 | ||
p := make([]byte, n+(n%32)) | ||
|
||
for i := 0; i < n; i += 32 { // future proof in case we need a key larger than 256 bits | ||
tmp := append(p, key...) | ||
h := sha256.Sum256(tmp) | ||
copy(p[i:], h[:]) | ||
ZeroSlice(tmp) | ||
} | ||
return p[:n:n] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"io" | ||
) | ||
|
||
type reader struct { | ||
dec cipher.Stream | ||
r io.Reader | ||
} | ||
|
||
// NewReader returns a new Reader with the specific crypto Algroithm | ||
// Note that it uses CFB mode for streams. | ||
func NewReader(r io.Reader, iv, key []byte, init CryptoInitilizer) (io.Reader, error) { | ||
c, err := init(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
rd := &reader{ | ||
dec: cipher.NewCFBDecrypter(c, iv), | ||
r: r, | ||
} | ||
return rd, nil | ||
} | ||
|
||
func (r *reader) Read(p []byte) (n int, err error) { | ||
in := make([]byte, len(p)) | ||
if n, err = r.r.Read(in); err != nil { | ||
return | ||
} | ||
r.dec.XORKeyStream(p, in) | ||
return | ||
} | ||
|
||
// NewAesReader an alias for NewReader(r, iv, key, aes.NewCipher) | ||
func NewAesReader(r io.Reader, iv, key []byte) (io.Reader, error) { | ||
return NewReader(r, iv, key, aes.NewCipher) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto/aes" | ||
"crypto/cipher" | ||
"io" | ||
) | ||
|
||
type writer struct { | ||
enc cipher.Stream | ||
w io.Writer | ||
} | ||
|
||
// NewReader returns a new Reader with the specific crypto Algroithm | ||
// Note that it uses CFB mode for streams. | ||
func NewWriter(w io.Writer, iv, key []byte, init CryptoInitilizer) (io.Writer, error) { | ||
c, err := init(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
wr := &writer{ | ||
enc: cipher.NewCFBEncrypter(c, iv), | ||
w: w, | ||
} | ||
return wr, nil | ||
} | ||
|
||
func (w *writer) Write(p []byte) (n int, err error) { | ||
out := make([]byte, len(p)) | ||
w.enc.XORKeyStream(out, p) | ||
return w.w.Write(out) | ||
} | ||
|
||
// NewAesWriter alias for NewWriter(w, iv, key, aes.NewCipher) | ||
func NewAesWriter(w io.Writer, iv, key []byte) (io.Writer, error) { | ||
return NewWriter(w, iv, key, aes.NewCipher) | ||
} |