forked from HACKERALERT/serpent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
serpent.go
119 lines (102 loc) · 3.24 KB
/
serpent.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// Package serpent implements the Serpent block cipher
// submitted to the AES challenge. Serpent was designed by
// Ross Anderson, Eli Biham und Lars Knudsen.
// The block cipher takes a 128, 192 or 256 bit key and
// has a block size of 128 bit.
package serpent // import "github.com/aead/serpent"
import (
"crypto/cipher"
"errors"
)
// BlockSize is the serpent block size in bytes.
const BlockSize = 16
const phi = 0x9e3779b9 // The Serpent phi constant (sqrt(5) - 1) * 2**31
var errKeySize = errors.New("invalid key size")
// NewCipher returns a new cipher.Block implementing the serpent block cipher.
// The key argument must be 128, 192 or 256 bit (16, 24, 32 byte).
func NewCipher(key []byte) (cipher.Block, error) {
if k := len(key); k != 16 && k != 24 && k != 32 {
return nil, errKeySize
}
s := &subkeys{}
s.keySchedule(key)
return s, nil
}
// The 132 32 bit subkeys of serpent
type subkeys [132]uint32
func (s *subkeys) BlockSize() int { return BlockSize }
func (s *subkeys) Encrypt(dst, src []byte) {
if len(src) < BlockSize {
panic("src buffer to small")
}
if len(dst) < BlockSize {
panic("dst buffer to small")
}
encryptBlock(dst, src, s)
}
func (s *subkeys) Decrypt(dst, src []byte) {
if len(src) < BlockSize {
panic("src buffer to small")
}
if len(dst) < BlockSize {
panic("dst buffer to small")
}
decryptBlock(dst, src, s)
}
// The key schedule of serpent.
func (s *subkeys) keySchedule(key []byte) {
var k [16]uint32
j := 0
for i := 0; i+4 <= len(key); i += 4 {
k[j] = uint32(key[i]) | uint32(key[i+1])<<8 | uint32(key[i+2])<<16 | uint32(key[i+3])<<24
j++
}
if j < 8 {
k[j] = 1
}
for i := 8; i < 16; i++ {
x := k[i-8] ^ k[i-5] ^ k[i-3] ^ k[i-1] ^ phi ^ uint32(i-8)
k[i] = (x << 11) | (x >> 21)
s[i-8] = k[i]
}
for i := 8; i < 132; i++ {
x := s[i-8] ^ s[i-5] ^ s[i-3] ^ s[i-1] ^ phi ^ uint32(i)
s[i] = (x << 11) | (x >> 21)
}
sb3(&s[0], &s[1], &s[2], &s[3])
sb2(&s[4], &s[5], &s[6], &s[7])
sb1(&s[8], &s[9], &s[10], &s[11])
sb0(&s[12], &s[13], &s[14], &s[15])
sb7(&s[16], &s[17], &s[18], &s[19])
sb6(&s[20], &s[21], &s[22], &s[23])
sb5(&s[24], &s[25], &s[26], &s[27])
sb4(&s[28], &s[29], &s[30], &s[31])
sb3(&s[32], &s[33], &s[34], &s[35])
sb2(&s[36], &s[37], &s[38], &s[39])
sb1(&s[40], &s[41], &s[42], &s[43])
sb0(&s[44], &s[45], &s[46], &s[47])
sb7(&s[48], &s[49], &s[50], &s[51])
sb6(&s[52], &s[53], &s[54], &s[55])
sb5(&s[56], &s[57], &s[58], &s[59])
sb4(&s[60], &s[61], &s[62], &s[63])
sb3(&s[64], &s[65], &s[66], &s[67])
sb2(&s[68], &s[69], &s[70], &s[71])
sb1(&s[72], &s[73], &s[74], &s[75])
sb0(&s[76], &s[77], &s[78], &s[79])
sb7(&s[80], &s[81], &s[82], &s[83])
sb6(&s[84], &s[85], &s[86], &s[87])
sb5(&s[88], &s[89], &s[90], &s[91])
sb4(&s[92], &s[93], &s[94], &s[95])
sb3(&s[96], &s[97], &s[98], &s[99])
sb2(&s[100], &s[101], &s[102], &s[103])
sb1(&s[104], &s[105], &s[106], &s[107])
sb0(&s[108], &s[109], &s[110], &s[111])
sb7(&s[112], &s[113], &s[114], &s[115])
sb6(&s[116], &s[117], &s[118], &s[119])
sb5(&s[120], &s[121], &s[122], &s[123])
sb4(&s[124], &s[125], &s[126], &s[127])
sb3(&s[128], &s[129], &s[130], &s[131])
}