v / vlib / crypto / des / des.v
173 lines · 146 sloc · 4.8 KB · 3aed78e76ab5a0764bfb4bff28b8ab6eb540c236
Raw
1// The source code refers to the go standard library
2
3module des
4
5import crypto.cipher
6import crypto.internal.subtle
7import encoding.binary
8
9const block_size = 8
10
11// A tripleDesCipher is an instance of TripleDES encryption.
12struct TripleDesCipher {
13 block_size int = block_size
14mut:
15 cipher1 DesCipher
16 cipher2 DesCipher
17 cipher3 DesCipher
18}
19
20// DesCipher is an instance of DES encryption.
21struct DesCipher {
22 block_size int = block_size
23mut:
24 subkeys [16]u64
25}
26
27// NewCipher creates and returns a new cipher.Block.
28pub fn new_cipher(key []u8) cipher.Block {
29 if key.len != 8 {
30 panic('crypto.aes: invalid key size')
31 }
32
33 mut c := DesCipher{}
34 c.generate_subkeys(key)
35 return c
36}
37
38// creates 16 56-bit subkeys from the original key
39fn (mut c DesCipher) generate_subkeys(key_bytes []u8) {
40 // feistel_box_once.do(initFeistel_box)
41
42 // apply PC1 permutation to key
43 key := binary.big_endian_u64(key_bytes)
44 permuted_key := permute_block(key, permuted_choice1[..])
45
46 // rotate halves of permuted key according to the rotation schedule
47 left_rotations := ks_rotate(u32(permuted_key >> 28))
48 right_rotations := ks_rotate(u32(permuted_key << 4) >> 4)
49
50 // generate subkeys
51 for i := 0; i < 16; i++ {
52 // combine halves to form 56-bit input to PC2
53 pc2_input := u64(left_rotations[i]) << 28 | u64(right_rotations[i])
54 // apply PC2 permutation to 7 byte input
55 c.subkeys[i] = unpack(permute_block(pc2_input, permuted_choice2[..]))
56 }
57}
58
59// encrypt a block of data using the DES algorithm
60pub fn (c &DesCipher) encrypt(mut dst []u8, src []u8) {
61 if src.len < block_size {
62 panic('crypto/des: input not full block')
63 }
64 if dst.len < block_size {
65 panic('crypto/des: output not full block')
66 }
67 if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
68 panic('crypto/des: invalid buffer overlap')
69 }
70 encrypt_block(c.subkeys[..], mut dst, src)
71}
72
73// decrypt a block of data using the DES algorithm
74pub fn (c &DesCipher) decrypt(mut dst []u8, src []u8) {
75 if src.len < block_size {
76 panic('crypto/des: input not full block')
77 }
78 if dst.len < block_size {
79 panic('crypto/des: output not full block')
80 }
81 if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
82 panic('crypto/des: invalid buffer overlap')
83 }
84 decrypt_block(c.subkeys[..], mut dst, src)
85}
86
87// NewTripleDesCipher creates and returns a new cipher.Block.
88pub fn new_triple_des_cipher(key []u8) cipher.Block {
89 if key.len != 24 {
90 panic('crypto.des: invalid key size')
91 }
92 mut c := TripleDesCipher{}
93 c.cipher1.generate_subkeys(key[..8])
94 c.cipher2.generate_subkeys(key[8..16])
95 c.cipher3.generate_subkeys(key[16..])
96 return c
97}
98
99// encrypt a block of data using the TripleDES algorithm
100pub fn (c &TripleDesCipher) encrypt(mut dst []u8, src []u8) {
101 if src.len < block_size {
102 panic('crypto/des: input not full block')
103 }
104 if dst.len < block_size {
105 panic('crypto/des: output not full block')
106 }
107 if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
108 panic('crypto/des: invalid buffer overlap')
109 }
110
111 mut b := binary.big_endian_u64(src)
112 b = permute_initial_block(b)
113 mut left, mut right := u32(b >> 32), u32(b)
114
115 left = (left << 1) | (left >> 31)
116 right = (right << 1) | (right >> 31)
117
118 for i := 0; i < 8; i++ {
119 left, right = feistel(left, right, c.cipher1.subkeys[2 * i], c.cipher1.subkeys[2 * i + 1])
120 }
121 for i := 0; i < 8; i++ {
122 right, left = feistel(right, left, c.cipher2.subkeys[15 - 2 * i], c.cipher2.subkeys[15 - (
123 2 * i + 1)])
124 }
125 for i := 0; i < 8; i++ {
126 left, right = feistel(left, right, c.cipher3.subkeys[2 * i], c.cipher3.subkeys[2 * i + 1])
127 }
128
129 left = (left << 31) | (left >> 1)
130 right = (right << 31) | (right >> 1)
131
132 pre_output := (u64(right) << 32) | u64(left)
133 binary.big_endian_put_u64(mut dst, permute_final_block(pre_output))
134}
135
136// decrypt a block of data using the TripleDES algorithm
137pub fn (c &TripleDesCipher) decrypt(mut dst []u8, src []u8) {
138 if src.len < block_size {
139 panic('crypto/des: input not full block')
140 }
141 if dst.len < block_size {
142 panic('crypto/des: output not full block')
143 }
144 if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
145 panic('crypto/des: invalid buffer overlap')
146 }
147
148 mut b := binary.big_endian_u64(src)
149 b = permute_initial_block(b)
150
151 mut left, mut right := u32(b >> 32), u32(b)
152
153 left = (left << 1) | (left >> 31)
154 right = (right << 1) | (right >> 31)
155
156 for i := 0; i < 8; i++ {
157 left, right = feistel(left, right, c.cipher3.subkeys[15 - 2 * i], c.cipher3.subkeys[15 - (
158 2 * i + 1)])
159 }
160 for i := 0; i < 8; i++ {
161 right, left = feistel(right, left, c.cipher2.subkeys[2 * i], c.cipher2.subkeys[2 * i + 1])
162 }
163 for i := 0; i < 8; i++ {
164 left, right = feistel(left, right, c.cipher1.subkeys[15 - 2 * i], c.cipher1.subkeys[15 - (
165 2 * i + 1)])
166 }
167
168 left = (left << 31) | (left >> 1)
169 right = (right << 31) | (right >> 1)
170
171 pre_output := (u64(right) << 32) | u64(left)
172 binary.big_endian_put_u64(mut dst, permute_final_block(pre_output))
173}
174