You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.2 KiB

  1. package keccak
  2. import "fmt"
  3. var roundConstantsU64 = []uint64{
  4. 0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
  5. 0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
  6. 0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
  7. 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
  8. 0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
  9. 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
  10. 0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
  11. 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
  12. }
  13. var roundConstants = u64ArrayToBits(roundConstantsU64)
  14. const (
  15. rounds = 24
  16. size = 32
  17. blockSize = 136
  18. domain = 0x01
  19. )
  20. func ComputeKeccak(b []bool) []bool {
  21. if len(b) >= blockSize*8 {
  22. // TODO absorb
  23. }
  24. s := final(b)
  25. b = squeeze(s)
  26. return b
  27. }
  28. func final(b []bool) [25 * 64]bool {
  29. last := pad(b)
  30. var s [25 * 64]bool
  31. s = absorb(s, last)
  32. return s
  33. }
  34. func pad(b []bool) []bool {
  35. padded := make([]bool, blockSize*8)
  36. copy(padded, b)
  37. copy(padded[len(b):len(b)+8], byteToBits(domain))
  38. copy(padded[(len(padded)-8):],
  39. or(padded[(len(padded)-8):], byteToBits(0x80)))
  40. return padded
  41. }
  42. func absorb(s [25 * 64]bool, block []bool) [25 * 64]bool {
  43. if len(block) != blockSize*8 {
  44. panic(fmt.Errorf("absorb: invalid block size: %d, expected: %d",
  45. len(block), blockSize*8))
  46. }
  47. for i := 0; i < blockSize/8; i++ {
  48. copy(s[i*64:i*64+64], xor(s[i*64:i*64+64], block[i*64:i*64+64]))
  49. }
  50. newS := keccakf(s)
  51. return newS
  52. }
  53. func squeeze(s [25 * 64]bool) []bool {
  54. // option1
  55. // b := make([]bool, 8*8*len(s))
  56. // for i := 0; i < 25; i++ {
  57. // copy(b[i*64:i*64+64], s[i*64:i*64+64])
  58. // }
  59. // return b[:size*8]
  60. // option2
  61. // out := make([]bool, size*8)
  62. // for i := 0; i < 25; i++ {
  63. // for j := 0; j < 64; j++ {
  64. // if i*64+j < size*8 {
  65. // out[i*64+j] = s[i*64+j]
  66. // }
  67. // }
  68. // }
  69. // return out
  70. // option3
  71. return s[:size*8]
  72. }
  73. func keccakfRound(s [25 * 64]bool, r int) [25 * 64]bool {
  74. s = theta(s)
  75. s = rhopi(s)
  76. s = chi(s)
  77. s = iot(s, r)
  78. return s
  79. }
  80. func keccakf(s [25 * 64]bool) [25 * 64]bool {
  81. for r := 0; r < rounds; r++ {
  82. s = keccakfRound(s, r)
  83. }
  84. return s
  85. }