]> Cypherpunks.ru repositories - balloon.git/blobdiff - balloon.go
Compatible results with other implementations
[balloon.git] / balloon.go
index 8f296b74ee8c6305af4364ec060407b4d17b5a51..9d34db8fd261f622cea969737fef97256e34e1a0 100644 (file)
@@ -27,37 +27,35 @@ import (
        "math/big"
 )
 
-const (
-       delta = 3
-)
+const delta = 3
 
 // This function takes hash, password, salt, space cost (buffer size,
 // number of hash-output sized blocks), time cost (number of rounds) and
 // performs the following:
 //
-//    # Expand input into buffer.
-//    buf[0] = hash(cnt++ || passwd || salt)
-//    for m from 1 to sCost-1:
-//        buf[m] = hash(cnt++ || buf[m-1])
-//    # Mix buffer contents.
-//    for t from 0 to tCost-1:
-//        for m from 0 to sCost-1:
-//            # Hash last and current blocks.
-//            prev = buf[(m-1) mod sCost]
-//            buf[m] = hash(cnt++ || prev || buf[m])
-//            # Hash in pseudorandomly chosen blocks.
-//            for i from 0 to delta-1:
-//                other = to_int(hash(cnt++ || salt || t || m || i)) mod sCost
-//                buf[m] = hash(cnt++ || buf[m] || buf[other])
-//    # Extract output from buffer.
-//    return buf[sCost-1]
+//     # Expand input into buffer.
+//     buf[0] = hash(cnt++ || passwd || salt)
+//     for m from 1 to sCost-1:
+//         buf[m] = hash(cnt++ || buf[m-1])
+//     # Mix buffer contents.
+//     for t from 0 to tCost-1:
+//         for m from 0 to sCost-1:
+//             # Hash last and current blocks.
+//             prev = buf[(m-1) mod sCost]
+//             buf[m] = hash(cnt++ || prev || buf[m])
+//             # Hash in pseudorandomly chosen blocks.
+//             for i from 0 to delta-1:
+//                 other = to_int(hash(cnt++ || salt || t || m || i)) mod sCost
+//                 buf[m] = hash(cnt++ || buf[m] || buf[other])
+//     # Extract output from buffer.
+//     return buf[sCost-1]
 func B(h hash.Hash, passwd, salt []byte, sCost, tCost uint64) []byte {
        var cnt uint64
        intBuf := make([]byte, 8)
        hSize := uint64(h.Size())
        buf := make([]byte, 0, sCost*hSize)
        // Expand input into buffer
-       binary.BigEndian.PutUint64(intBuf, cnt)
+       binary.LittleEndian.PutUint64(intBuf, cnt)
        cnt++
        h.Write(intBuf)
        h.Write(passwd)
@@ -65,7 +63,7 @@ func B(h hash.Hash, passwd, salt []byte, sCost, tCost uint64) []byte {
        buf = h.Sum(buf)
        var m uint64
        for m = 1; m < sCost; m++ {
-               binary.BigEndian.PutUint64(intBuf, cnt)
+               binary.LittleEndian.PutUint64(intBuf, cnt)
                cnt++
                h.Reset()
                h.Write(intBuf)
@@ -87,7 +85,7 @@ func B(h hash.Hash, passwd, salt []byte, sCost, tCost uint64) []byte {
                        } else {
                                prev = buf[(m-1)*hSize : m*hSize]
                        }
-                       binary.BigEndian.PutUint64(intBuf, cnt)
+                       binary.LittleEndian.PutUint64(intBuf, cnt)
                        cnt++
                        h.Reset()
                        h.Write(intBuf)
@@ -97,21 +95,27 @@ func B(h hash.Hash, passwd, salt []byte, sCost, tCost uint64) []byte {
 
                        // Hash in pseudorandomly chosen blocks
                        for i = 0; i < delta; i++ {
-                               binary.BigEndian.PutUint64(intBuf, cnt)
-                               cnt++
                                h.Reset()
+                               binary.LittleEndian.PutUint64(intBuf, t)
                                h.Write(intBuf)
-                               h.Write(salt)
-                               binary.BigEndian.PutUint64(intBuf, t)
+                               binary.LittleEndian.PutUint64(intBuf, m)
                                h.Write(intBuf)
-                               binary.BigEndian.PutUint64(intBuf, m)
+                               binary.LittleEndian.PutUint64(intBuf, i)
                                h.Write(intBuf)
-                               binary.BigEndian.PutUint64(intBuf, i)
+                               biBuf = h.Sum(biBuf[:0])
+                               binary.LittleEndian.PutUint64(intBuf, cnt)
+                               cnt++
+                               h.Reset()
                                h.Write(intBuf)
+                               h.Write(salt)
+                               h.Write(biBuf)
                                biBuf = h.Sum(biBuf[:0])
+                               for i, j := 0, len(biBuf)-1; i < j; i, j = i+1, j-1 {
+                                       biBuf[i], biBuf[j] = biBuf[j], biBuf[i]
+                               }
                                bi.SetBytes(biBuf)
                                bi.Mod(bi, bs)
-                               binary.BigEndian.PutUint64(intBuf, cnt)
+                               binary.LittleEndian.PutUint64(intBuf, cnt)
                                cnt++
                                h.Reset()
                                h.Write(intBuf)
@@ -130,11 +134,11 @@ func B(h hash.Hash, passwd, salt []byte, sCost, tCost uint64) []byte {
 // run several hashers (jobs) simultaneously and second-preimage resistant
 // password double hashing.
 //
-//     H(p, s, jobs) = hash(p || s || (
-//         B(p, s || "1") XOR
-//         B(p, s || "2") XOR
-//         B(p, s || jobs)
-//     ))
+//     H(p, s, jobs) = hash(p || s || (
+//         B(p, s || "1") XOR
+//         B(p, s || "2") XOR
+//         B(p, s || jobs)
+//     ))
 func H(hasher func() hash.Hash, passwd, salt []byte, sCost, tCost int, jobs int) []byte {
        var i int
        results := make(chan []byte)
@@ -142,7 +146,7 @@ func H(hasher func() hash.Hash, passwd, salt []byte, sCost, tCost int, jobs int)
                go func(i int) {
                        saltBuf := make([]byte, len(salt)+8)
                        copy(saltBuf, salt)
-                       binary.BigEndian.PutUint64(saltBuf[len(salt):], uint64(i))
+                       binary.LittleEndian.PutUint64(saltBuf[len(salt):], uint64(i))
                        results <- B(hasher(), passwd, saltBuf, uint64(sCost), uint64(tCost))
                }(i)
        }