aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bhash.go6
-rw-r--r--bhash/bhash.go41
-rw-r--r--bhash/bhash_test.go33
3 files changed, 78 insertions, 2 deletions
diff --git a/bhash.go b/bhash.go
index 19c1ee8..04591a2 100644
--- a/bhash.go
+++ b/bhash.go
@@ -8,6 +8,8 @@ import (
var magic = []byte("OxychromaticBlowfishSwatDynamite")
+const rounds = 64 // fixed
+
// blowfish hash
type digest struct {
c *blowfish.Cipher
@@ -26,11 +28,11 @@ func (d *digest) Reset() {
}
func (d *digest) Size() int {
- panic("not implemented")
+ return blowfish.BlockSize * 4
}
func (d *digest) BlockSize() int {
- return d.c.BlockSize()
+ return blowfish.BlockSize
}
func NewBHash() hash.Hash {
diff --git a/bhash/bhash.go b/bhash/bhash.go
new file mode 100644
index 0000000..170855e
--- /dev/null
+++ b/bhash/bhash.go
@@ -0,0 +1,41 @@
+package bhash
+
+import (
+ "bytes"
+
+ "golang.org/x/crypto/blowfish"
+)
+
+var magic = []byte("OxychromaticBlowfishSwatDynamite")
+
+const rounds = 64
+
+func Hash(pass, salt []byte) []byte {
+ c, err := blowfish.NewSaltedCipher(pass, salt)
+ if err != nil {
+ panic(err)
+ }
+ // key expansion
+ for i := 0; i < rounds; i++ {
+ blowfish.ExpandKey(salt, c)
+ blowfish.ExpandKey(pass, c)
+ }
+ // encryption
+ buf := new(bytes.Buffer)
+ bSz := c.BlockSize()
+ for n := 0; n < len(magic)/bSz; n++ {
+ b := make([]byte, bSz)
+ copy(b, magic[n*bSz:(n+1)*bSz])
+ for i := 0; i < rounds; i++ {
+ c.Encrypt(b, b)
+ }
+ // copy out
+ b[0], b[1], b[2], b[3] = b[3], b[2], b[1], b[0]
+ b[4], b[5], b[6], b[7] = b[7], b[6], b[5], b[4]
+ buf.Write(b)
+ }
+ return buf.Bytes()
+}
+
+func Pbkdf() {
+}
diff --git a/bhash/bhash_test.go b/bhash/bhash_test.go
new file mode 100644
index 0000000..c49f687
--- /dev/null
+++ b/bhash/bhash_test.go
@@ -0,0 +1,33 @@
+package bhash
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestHash(t *testing.T) {
+ golden := []byte{
+ 0xa9, 0xd1, 0x46, 0x93, 0x6d, 0xc1, 0xe6, 0x22,
+ 0x87, 0xe0, 0xbd, 0x84, 0xe3, 0x0b, 0x4a, 0x0d,
+ 0x34, 0xd2, 0x08, 0x7d, 0x57, 0xea, 0x25, 0x75,
+ 0xa7, 0x3d, 0x5f, 0x42, 0xd5, 0x73, 0x41, 0x4a,
+ }
+ res := Hash([]byte("pass"), []byte("salt"))
+ if !bytes.Equal(res, golden) {
+ t.Errorf("got %x, want %x", res, golden)
+ }
+}
+
+func TestHashZero(t *testing.T) {
+ golden := []byte{
+ 0x46, 0x02, 0x86, 0xe9, 0x72, 0xfa, 0x83, 0x3f,
+ 0x8b, 0x12, 0x83, 0xad, 0x8f, 0xa9, 0x19, 0xfa,
+ 0x29, 0xbd, 0xe2, 0x0e, 0x23, 0x32, 0x9e, 0x77,
+ 0x4d, 0x84, 0x22, 0xba, 0xc0, 0xa7, 0x92, 0x6c,
+ }
+ zero := [32]byte{}
+ res := Hash(zero[:], zero[:])
+ if !bytes.Equal(res, golden) {
+ t.Errorf("got %x, want %x", res, golden)
+ }
+}