-
Notifications
You must be signed in to change notification settings - Fork 0
/
threefish.go
66 lines (55 loc) · 2.01 KB
/
threefish.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Package threefish implements the Threefish tweakable block cipher.
//
// Threefish is a block cipher that was developed as part of the Skein hash
// function as a submission to the NIST hash function competition. Threefish
// supports block sizes of 256, 512, and 1024 bits.
//
// For the full Threefish specification, see [1].
//
// Test vectors were extracted from the latest reference implementation [2].
//
// Encryption and decryption loops have been unrolled to contain eight rounds
// in each iteration. This allows rotation constants to be embedded in the code
// without being repeated. This practice is described in detail in the paper [1]
// which also provides detailed performance information.
//
// [1] http://www.skein-hash.info/sites/default/files/skein1.3.pdf
// [2] http://www.skein-hash.info/sites/default/files/NIST_CD_102610.zip
package threefish
import (
"encoding/binary"
"fmt"
)
const (
// Size of the tweak value in bytes, as expected from the user
tweakSize int = 16
// Constant used to ensure that key extension cannot result in all zeroes
c240 uint64 = 0x1bd11bdaa9fc1a22
)
// Aliases to help produce concise code
var (
loadWord = binary.LittleEndian.Uint64
storeWord = binary.LittleEndian.PutUint64
)
// A KeySizeError is returned when the provided key isn't the correct size.
type KeySizeError int
// Error describes a KeySizeError.
func (e KeySizeError) Error() string {
return fmt.Sprintf("threefish: key size must be %d bytes", e)
}
// A TweakSizeError is returned when the provided tweak isn't the correct size.
type TweakSizeError struct{}
// Error describes a TweakSizeError.
func (e TweakSizeError) Error() string {
return fmt.Sprintf("threefish: tweak size must be %d bytes", tweakSize)
}
// calculateTweak loads a tweak value from src and extends it into dst.
func calculateTweak(dst *[(tweakSize / 8) + 1]uint64, src []byte) error {
if len(src) != tweakSize {
return new(TweakSizeError)
}
dst[0] = loadWord(src[0:8])
dst[1] = loadWord(src[8:16])
dst[2] = dst[0] ^ dst[1]
return nil
}