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.

198 lines
5.4 KiB

  1. // Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
  2. // Use of this source code is governed by a license that can be
  3. // found in the LICENSE file.
  4. // Package skein implements the Skein512 hash function
  5. // based on the Threefish tweakable block cipher.
  6. //
  7. //
  8. // Overview
  9. //
  10. // Skein is a hash function family using the tweakable block cipher
  11. // Threefish in Unique Block Iteration (UBI) chaining mode while
  12. // leveraging an optional low-overhead argument-system
  13. // for flexibility. There are three versions of Skein, each of them
  14. // using the corresponding Threefish version:
  15. // - Skein256 using Threefish256 and processes 256 bit blocks
  16. // - Skein512 using Threefish512 and processes 512 bit blocks
  17. // - Skein1024 using Threefish1024 and processes 1024 bit blocks
  18. //
  19. // Skein can be used as hash function, MAC or KDF and supports personalized,
  20. // randomized (salted) and public-key-bound hashing. Furthermore Skein
  21. // has some additional features (currently) not implemented here. For
  22. // details see http://www.skein-hash.info/
  23. // Skein was submitted to the SHA-3 challenge.
  24. //
  25. // Skein can produce hash values of any size (up to (2^64 -1) x BlockSize bytes)
  26. // not only the common sizes 160, 224, 256, 384 and 512 bit.
  27. //
  28. //
  29. // Security and Recommendations
  30. //
  31. // All Skein varaiants (as far as known) secure. The Skein authors recommend to use
  32. // Skein512 for most applications. Skein256 should be used for small devices
  33. // like smartcards. Skein1024 is the ultra-conservative variant providing a level of
  34. // security (mostly) not needed.
  35. package skein // import "github.com/aead/skein"
  36. import "hash"
  37. // Config contains the Skein configuration:
  38. // - Key for computing MACs
  39. // - Personal for personalized hashing
  40. // - PublicKey for public-key-bound hashing
  41. // - KeyID for key derivation
  42. // - Nonce for randomized hashing
  43. // All fields are optional and can be nil.
  44. type Config struct {
  45. Key []byte // Optional: The secret key for MAC
  46. Personal []byte // Optional: The personalization for unique hashing
  47. PublicKey []byte // Optional: The public key for public-key bound hashing
  48. KeyID []byte // Optional: The key id for key derivation
  49. Nonce []byte // Optional: The nonce for randomized hashing
  50. }
  51. // Sum512 computes the 512 bit Skein512 checksum (or MAC if key is set) of msg
  52. // and writes it to out. The key is optional and can be nil.
  53. func Sum512(out *[64]byte, msg, key []byte) {
  54. s := new(hashFunc)
  55. if len(key) > 0 {
  56. s.initialize(64, &Config{Key: key})
  57. } else {
  58. s.hVal = iv512
  59. s.hValCpy = iv512
  60. s.hashsize = BlockSize
  61. s.tweak[0] = 0
  62. s.tweak[1] = CfgMessage<<56 | FirstBlock
  63. }
  64. s.Write(msg)
  65. s.finalizeHash()
  66. s.output(out, 0)
  67. }
  68. // Sum384 computes the 384 bit Skein512 checksum (or MAC if key is set) of msg
  69. // and writes it to out. The key is optional and can be nil.
  70. func Sum384(out *[48]byte, msg, key []byte) {
  71. var out512 [64]byte
  72. s := new(hashFunc)
  73. if len(key) > 0 {
  74. s.initialize(48, &Config{Key: key})
  75. } else {
  76. s.hVal = iv384
  77. s.hValCpy = iv384
  78. s.hashsize = 48
  79. s.tweak[0] = 0
  80. s.tweak[1] = CfgMessage<<56 | FirstBlock
  81. }
  82. s.Write(msg)
  83. s.finalizeHash()
  84. s.output(&out512, 0)
  85. copy(out[:], out512[:48])
  86. }
  87. // Sum256 computes the 256 bit Skein512 checksum (or MAC if key is set) of msg
  88. // and writes it to out. The key is optional and can be nil.
  89. func Sum256(out *[32]byte, msg, key []byte) {
  90. var out512 [64]byte
  91. s := new(hashFunc)
  92. if len(key) > 0 {
  93. s.initialize(32, &Config{Key: key})
  94. } else {
  95. s.hVal = iv256
  96. s.hValCpy = iv256
  97. s.hashsize = 32
  98. s.tweak[0] = 0
  99. s.tweak[1] = CfgMessage<<56 | FirstBlock
  100. }
  101. s.Write(msg)
  102. s.finalizeHash()
  103. s.output(&out512, 0)
  104. copy(out[:], out512[:32])
  105. }
  106. // Sum160 computes the 160 bit Skein512 checksum (or MAC if key is set) of msg
  107. // and writes it to out. The key is optional and can be nil.
  108. func Sum160(out *[20]byte, msg, key []byte) {
  109. var out512 [64]byte
  110. s := new(hashFunc)
  111. if len(key) > 0 {
  112. s.initialize(20, &Config{Key: key})
  113. } else {
  114. s.hVal = iv160
  115. s.hValCpy = iv160
  116. s.hashsize = 20
  117. s.tweak[0] = 0
  118. s.tweak[1] = CfgMessage<<56 | FirstBlock
  119. }
  120. s.Write(msg)
  121. s.finalizeHash()
  122. s.output(&out512, 0)
  123. copy(out[:], out512[:20])
  124. }
  125. // Sum returns the Skein512 checksum with the given hash size of msg using the (optional)
  126. // conf for configuration. The hashsize must be > 0.
  127. func Sum(msg []byte, hashsize int, conf *Config) []byte {
  128. s := New(hashsize, conf)
  129. s.Write(msg)
  130. return s.Sum(nil)
  131. }
  132. // New512 returns a hash.Hash computing the Skein512 512 bit checksum.
  133. // The key is optional and turns the hash into a MAC.
  134. func New512(key []byte) hash.Hash {
  135. s := new(hashFunc)
  136. if len(key) > 0 {
  137. s.initialize(BlockSize, &Config{Key: key})
  138. } else {
  139. copy(s.hVal[:8], iv512[:])
  140. s.hValCpy = s.hVal
  141. s.hashsize = BlockSize
  142. s.tweak[0] = 0
  143. s.tweak[1] = CfgMessage<<56 | FirstBlock
  144. }
  145. return s
  146. }
  147. // New256 returns a hash.Hash computing the Skein512 256 bit checksum.
  148. // The key is optional and turns the hash into a MAC.
  149. func New256(key []byte) hash.Hash {
  150. s := new(hashFunc)
  151. if len(key) > 0 {
  152. s.initialize(32, &Config{Key: key})
  153. } else {
  154. copy(s.hVal[:8], iv256[:])
  155. s.hValCpy = s.hVal
  156. s.hashsize = 32
  157. s.tweak[0] = 0
  158. s.tweak[1] = CfgMessage<<56 | FirstBlock
  159. }
  160. return s
  161. }
  162. // New returns a hash.Hash computing the Skein512 checksum with the given hash size.
  163. // The conf is optional and configurates the hash.Hash
  164. func New(hashsize int, conf *Config) hash.Hash {
  165. s := new(hashFunc)
  166. s.initialize(hashsize, conf)
  167. return s
  168. }