github.com/cloudflare/circl@v1.5.0/simd/keccakf1600/example_test.go (about) 1 package keccakf1600_test 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 7 "github.com/cloudflare/circl/internal/sha3" 8 "github.com/cloudflare/circl/simd/keccakf1600" 9 ) 10 11 func Example() { 12 // As an example, computes the (first 32 bytes of a) SHAKE-256 stream of 13 // four short strings at the same time. 14 msgs := [4][]byte{ 15 []byte("These are some short"), 16 []byte("strings of the same "), 17 []byte("length that fit in a"), 18 []byte("single block. "), 19 } 20 var hashes [4][32]byte 21 22 // The user could branch to a fast non-SIMD implementation if this function 23 // returns false. 24 if !keccakf1600.IsEnabledX4() { 25 // Compute hashes separately using golang.org/x/crypto/sha3 instead 26 // when a fast four-way implementation is not available. A generic 27 // keccakf1600 implementation is quite a bit slower than using 28 // the non-interleaved hashes because of the need to interleave and 29 // deinterleave the state. 30 for i := 0; i < 4; i++ { 31 h := sha3.NewShake256() 32 _, _ = h.Write(msgs[i]) 33 _, _ = h.Read(hashes[i][:]) 34 } 35 } else { 36 // f1600 acts on 1600 bits arranged as 25 uint64s. Our fourway f1600 37 // acts on four interleaved states; that is a [100]uint64. (A separate 38 // type is used to ensure that the encapsulated [100]uint64 is aligned 39 // properly to be used efficiently with vector instructions.) 40 var perm keccakf1600.StateX4 41 state := perm.Initialize(false) 42 43 // state is initialized with zeroes. As the messages fit within one 44 // block, we only need to write the messages, domain separators 45 // and padding. 46 for i := 0; i < 4; i++ { 47 // The messages. 48 state[i] = binary.LittleEndian.Uint64(msgs[i][:8]) 49 state[4+i] = binary.LittleEndian.Uint64(msgs[i][8:16]) 50 51 // Final bit of the message together with the SHAKE-256 domain 52 // separator (0b1111) and the start of the padding (0b10....) 53 state[8+i] = uint64(binary.LittleEndian.Uint32(msgs[i][16:])) | 54 (uint64(0x1f) << 32) 55 state[16*4+i] = 0x80 << 56 // end of padding (0b...01) 56 } 57 58 // Executes the permutation on state. 59 perm.Permute() 60 61 // As our desired output fits within one block, we can read it without 62 // repeating the permutation. 63 for i := 0; i < 4; i++ { 64 for j := 0; j < 4; j++ { 65 binary.LittleEndian.PutUint64( 66 hashes[i][8*j:8*(j+1)], 67 state[4*j+i], 68 ) 69 } 70 } 71 } 72 73 fmt.Printf("\n%x\n%x\n%x\n%x\n", hashes[0], hashes[1], hashes[2], hashes[3]) 74 // Output: 75 // 9b48efc4f4e562fe28c510b2ad3966b101ac20066dc88117d85a595cc965f7e4 76 // 19333d8bb71edce81f0630e4154abea83bf7d2f7e709d62fda878b6e9db9c9c1 77 // 28f31cc0b8d95185fbba5c4ed5cd94ed7dba0e13c21ca830d1325a212defdfc5 78 // 51392299d6b10e62b98eb02c9540784046cc9c83e46eddd2ce57cddc2037f917 79 }