1
2
3
4
5 package des
6
7 import (
8 "crypto/cipher"
9 "encoding/binary"
10 "strconv"
11 )
12
13
14 const BlockSize = 8
15
16 type KeySizeError int
17
18 func (k KeySizeError) Error() string {
19 return "crypto/des: invalid key size " + strconv.Itoa(int(k))
20 }
21
22
23 type desCipher struct {
24 subkeys [16]uint64
25 }
26
27
28 func NewCipher(key []byte) (cipher.Block, error) {
29 if len(key) != 8 {
30 return nil, KeySizeError(len(key))
31 }
32
33 c := new(desCipher)
34 c.generateSubkeys(key)
35 return c, nil
36 }
37
38 func (c *desCipher) BlockSize() int { return BlockSize }
39
40 func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
41
42 func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
43
44
45 type tripleDESCipher struct {
46 cipher1, cipher2, cipher3 desCipher
47 }
48
49
50 func NewTripleDESCipher(key []byte) (cipher.Block, error) {
51 if len(key) != 24 {
52 return nil, KeySizeError(len(key))
53 }
54
55 c := new(tripleDESCipher)
56 c.cipher1.generateSubkeys(key[:8])
57 c.cipher2.generateSubkeys(key[8:16])
58 c.cipher3.generateSubkeys(key[16:])
59 return c, nil
60 }
61
62 func (c *tripleDESCipher) BlockSize() int { return BlockSize }
63
64 func (c *tripleDESCipher) Encrypt(dst, src []byte) {
65 b := binary.BigEndian.Uint64(src)
66 b = permuteInitialBlock(b)
67 left, right := uint32(b>>32), uint32(b)
68
69 left = (left << 1) | (left >> 31)
70 right = (right << 1) | (right >> 31)
71
72 for i := 0; i < 8; i++ {
73 left, right = feistel(left, right, c.cipher1.subkeys[2*i], c.cipher1.subkeys[2*i+1])
74 }
75 for i := 0; i < 8; i++ {
76 right, left = feistel(right, left, c.cipher2.subkeys[15-2*i], c.cipher2.subkeys[15-(2*i+1)])
77 }
78 for i := 0; i < 8; i++ {
79 left, right = feistel(left, right, c.cipher3.subkeys[2*i], c.cipher3.subkeys[2*i+1])
80 }
81
82 left = (left << 31) | (left >> 1)
83 right = (right << 31) | (right >> 1)
84
85 preOutput := (uint64(right) << 32) | uint64(left)
86 binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
87 }
88
89 func (c *tripleDESCipher) Decrypt(dst, src []byte) {
90 b := binary.BigEndian.Uint64(src)
91 b = permuteInitialBlock(b)
92 left, right := uint32(b>>32), uint32(b)
93
94 left = (left << 1) | (left >> 31)
95 right = (right << 1) | (right >> 31)
96
97 for i := 0; i < 8; i++ {
98 left, right = feistel(left, right, c.cipher3.subkeys[15-2*i], c.cipher3.subkeys[15-(2*i+1)])
99 }
100 for i := 0; i < 8; i++ {
101 right, left = feistel(right, left, c.cipher2.subkeys[2*i], c.cipher2.subkeys[2*i+1])
102 }
103 for i := 0; i < 8; i++ {
104 left, right = feistel(left, right, c.cipher1.subkeys[15-2*i], c.cipher1.subkeys[15-(2*i+1)])
105 }
106
107 left = (left << 31) | (left >> 1)
108 right = (right << 31) | (right >> 1)
109
110 preOutput := (uint64(right) << 32) | uint64(left)
111 binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
112 }
113
View as plain text