1
2
3
4
5 package des
6
7 import (
8 "crypto/cipher"
9 "crypto/internal/fips140/alias"
10 "crypto/internal/fips140only"
11 "errors"
12 "internal/byteorder"
13 "strconv"
14 )
15
16
17 const BlockSize = 8
18
19 type KeySizeError int
20
21 func (k KeySizeError) Error() string {
22 return "crypto/des: invalid key size " + strconv.Itoa(int(k))
23 }
24
25
26 type desCipher struct {
27 subkeys [16]uint64
28 }
29
30
31 func NewCipher(key []byte) (cipher.Block, error) {
32 if fips140only.Enabled {
33 return nil, errors.New("crypto/des: use of DES is not allowed in FIPS 140-only mode")
34 }
35
36 if len(key) != 8 {
37 return nil, KeySizeError(len(key))
38 }
39
40 c := new(desCipher)
41 c.generateSubkeys(key)
42 return c, nil
43 }
44
45 func (c *desCipher) BlockSize() int { return BlockSize }
46
47 func (c *desCipher) Encrypt(dst, src []byte) {
48 if len(src) < BlockSize {
49 panic("crypto/des: input not full block")
50 }
51 if len(dst) < BlockSize {
52 panic("crypto/des: output not full block")
53 }
54 if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
55 panic("crypto/des: invalid buffer overlap")
56 }
57 cryptBlock(c.subkeys[:], dst, src, false)
58 }
59
60 func (c *desCipher) Decrypt(dst, src []byte) {
61 if len(src) < BlockSize {
62 panic("crypto/des: input not full block")
63 }
64 if len(dst) < BlockSize {
65 panic("crypto/des: output not full block")
66 }
67 if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
68 panic("crypto/des: invalid buffer overlap")
69 }
70 cryptBlock(c.subkeys[:], dst, src, true)
71 }
72
73
74 type tripleDESCipher struct {
75 cipher1, cipher2, cipher3 desCipher
76 }
77
78
79 func NewTripleDESCipher(key []byte) (cipher.Block, error) {
80 if fips140only.Enabled {
81 return nil, errors.New("crypto/des: use of TripleDES is not allowed in FIPS 140-only mode")
82 }
83
84 if len(key) != 24 {
85 return nil, KeySizeError(len(key))
86 }
87
88 c := new(tripleDESCipher)
89 c.cipher1.generateSubkeys(key[:8])
90 c.cipher2.generateSubkeys(key[8:16])
91 c.cipher3.generateSubkeys(key[16:])
92 return c, nil
93 }
94
95 func (c *tripleDESCipher) BlockSize() int { return BlockSize }
96
97 func (c *tripleDESCipher) Encrypt(dst, src []byte) {
98 if len(src) < BlockSize {
99 panic("crypto/des: input not full block")
100 }
101 if len(dst) < BlockSize {
102 panic("crypto/des: output not full block")
103 }
104 if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
105 panic("crypto/des: invalid buffer overlap")
106 }
107
108 b := byteorder.BEUint64(src)
109 b = permuteInitialBlock(b)
110 left, right := uint32(b>>32), uint32(b)
111
112 left = (left << 1) | (left >> 31)
113 right = (right << 1) | (right >> 31)
114
115 for i := 0; i < 8; i++ {
116 left, right = feistel(left, right, c.cipher1.subkeys[2*i], c.cipher1.subkeys[2*i+1])
117 }
118 for i := 0; i < 8; i++ {
119 right, left = feistel(right, left, c.cipher2.subkeys[15-2*i], c.cipher2.subkeys[15-(2*i+1)])
120 }
121 for i := 0; i < 8; i++ {
122 left, right = feistel(left, right, c.cipher3.subkeys[2*i], c.cipher3.subkeys[2*i+1])
123 }
124
125 left = (left << 31) | (left >> 1)
126 right = (right << 31) | (right >> 1)
127
128 preOutput := (uint64(right) << 32) | uint64(left)
129 byteorder.BEPutUint64(dst, permuteFinalBlock(preOutput))
130 }
131
132 func (c *tripleDESCipher) Decrypt(dst, src []byte) {
133 if len(src) < BlockSize {
134 panic("crypto/des: input not full block")
135 }
136 if len(dst) < BlockSize {
137 panic("crypto/des: output not full block")
138 }
139 if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
140 panic("crypto/des: invalid buffer overlap")
141 }
142
143 b := byteorder.BEUint64(src)
144 b = permuteInitialBlock(b)
145 left, right := uint32(b>>32), uint32(b)
146
147 left = (left << 1) | (left >> 31)
148 right = (right << 1) | (right >> 31)
149
150 for i := 0; i < 8; i++ {
151 left, right = feistel(left, right, c.cipher3.subkeys[15-2*i], c.cipher3.subkeys[15-(2*i+1)])
152 }
153 for i := 0; i < 8; i++ {
154 right, left = feistel(right, left, c.cipher2.subkeys[2*i], c.cipher2.subkeys[2*i+1])
155 }
156 for i := 0; i < 8; i++ {
157 left, right = feistel(left, right, c.cipher1.subkeys[15-2*i], c.cipher1.subkeys[15-(2*i+1)])
158 }
159
160 left = (left << 31) | (left >> 1)
161 right = (right << 31) | (right >> 1)
162
163 preOutput := (uint64(right) << 32) | uint64(left)
164 byteorder.BEPutUint64(dst, permuteFinalBlock(preOutput))
165 }
166
View as plain text