| 1 | // The source code refers to the go standard library, which can be merged with AES later |
| 2 | |
| 3 | module des |
| 4 | |
| 5 | import encoding.binary |
| 6 | |
| 7 | fn feistel(ll u32, rr u32, k0 u64, k1 u64) (u32, u32) { |
| 8 | mut l := ll |
| 9 | mut r := rr |
| 10 | mut t := r ^ u32(k0 >> 32) |
| 11 | |
| 12 | l ^= feistel_box[7][t & 0x3f] ^ feistel_box[5][(t >> 8) & 0x3f] ^ feistel_box[3][(t >> 16) & 0x3f] ^ feistel_box[1][(t >> 24) & 0x3f] |
| 13 | |
| 14 | t = ((r << 28) | (r >> 4)) ^ u32(k0) |
| 15 | l ^= feistel_box[6][t & 0x3f] ^ feistel_box[4][(t >> 8) & 0x3f] ^ feistel_box[2][(t >> 16) & 0x3f] ^ feistel_box[0][(t >> 24) & 0x3f] |
| 16 | |
| 17 | t = l ^ u32(k1 >> 32) |
| 18 | r ^= feistel_box[7][t & 0x3f] ^ feistel_box[5][(t >> 8) & 0x3f] ^ feistel_box[3][(t >> 16) & 0x3f] ^ feistel_box[1][(t >> 24) & 0x3f] |
| 19 | |
| 20 | t = ((l << 28) | (l >> 4)) ^ u32(k1) |
| 21 | r ^= feistel_box[6][t & 0x3f] ^ feistel_box[4][(t >> 8) & 0x3f] ^ feistel_box[2][(t >> 16) & 0x3f] ^ feistel_box[0][(t >> 24) & 0x3f] |
| 22 | |
| 23 | return l, r |
| 24 | } |
| 25 | |
| 26 | fn crypt_block(subkeys []u64, mut dst []u8, src []u8, decrypt bool) { |
| 27 | mut b := binary.big_endian_u64(src) |
| 28 | b = permute_initial_block(b) |
| 29 | |
| 30 | mut left, mut right := u32(b >> 32), u32(b) |
| 31 | |
| 32 | left = (left << 1) | (left >> 31) |
| 33 | right = (right << 1) | (right >> 31) |
| 34 | |
| 35 | if decrypt { |
| 36 | for i := 0; i < 8; i++ { |
| 37 | left, right = feistel(left, right, subkeys[15 - 2 * i], subkeys[15 - (2 * i + 1)]) |
| 38 | } |
| 39 | } else { |
| 40 | for i := 0; i < 8; i++ { |
| 41 | left, right = feistel(left, right, subkeys[2 * i], subkeys[2 * i + 1]) |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | left = (left << 31) | (left >> 1) |
| 46 | right = (right << 31) | (right >> 1) |
| 47 | |
| 48 | // switch left & right and perform final permutation |
| 49 | pre_output := (u64(right) << 32) | u64(left) |
| 50 | binary.big_endian_put_u64(mut dst, permute_final_block(pre_output)) |
| 51 | } |
| 52 | |
| 53 | // Encrypt one block from src into dst, using the subkeys. |
| 54 | pub fn encrypt_block(subkeys []u64, mut dst []u8, src []u8) { |
| 55 | crypt_block(subkeys, mut dst, src, false) |
| 56 | } |
| 57 | |
| 58 | // Decrypt one block from src into dst, using the subkeys. |
| 59 | fn decrypt_block(subkeys []u64, mut dst []u8, src []u8) { |
| 60 | crypt_block(subkeys, mut dst, src, true) |
| 61 | } |
| 62 | |
| 63 | // general purpose function to perform DES block permutations |
| 64 | fn permute_block(src u64, permutation []u8) u64 { |
| 65 | mut block := u64(0) |
| 66 | for position, n in permutation { |
| 67 | bit := (src >> u64(u8(n))) & 1 |
| 68 | block |= bit << u64((permutation.len - 1) - position) |
| 69 | } |
| 70 | return block |
| 71 | } |
| 72 | |
| 73 | // permuteInitial_block is equivalent to the permutation defined |
| 74 | // by initialPermutation. |
| 75 | fn permute_initial_block(b u64) u64 { |
| 76 | // block = b7 b6 b5 b4 b3 b2 b1 b0 (8 bytes) |
| 77 | mut block := b |
| 78 | mut b1 := block >> 48 |
| 79 | mut b2 := block << 48 |
| 80 | block ^= b1 ^ b2 ^ b1 << 48 ^ b2 >> 48 |
| 81 | |
| 82 | // block = b1 b0 b5 b4 b3 b2 b7 b6 |
| 83 | b1 = (block >> 32) & 0xff00ff |
| 84 | b2 = (block & 0xff00ff00) |
| 85 | block ^= b1 << 32 ^ b2 ^ b1 << 8 ^ b2 << 24 // exchange b0 b4 with b3 b7 |
| 86 | |
| 87 | // block is now b1 b3 b5 b7 b0 b2 b4 b6, the permutation: |
| 88 | // ... 8 |
| 89 | // ... 24 |
| 90 | // ... 40 |
| 91 | // ... 56 |
| 92 | // 7 6 5 4 3 2 1 0 |
| 93 | // 23 22 21 20 19 18 17 16 |
| 94 | // ... 32 |
| 95 | // ... 48 |
| 96 | |
| 97 | // exchange 4,5,6,7 with 32,33,34,35 etc. |
| 98 | b1 = block & 0x0f0f00000f0f0000 |
| 99 | b2 = block & 0x0000f0f00000f0f0 |
| 100 | block ^= b1 ^ b2 ^ b1 >> 12 ^ b2 << 12 |
| 101 | |
| 102 | // block is the permutation: |
| 103 | // |
| 104 | // [+8] [+40] |
| 105 | // |
| 106 | // 7 6 5 4 |
| 107 | // 23 22 21 20 |
| 108 | // 3 2 1 0 |
| 109 | // 19 18 17 16 [+32] |
| 110 | |
| 111 | // exchange 0,1,4,5 with 18,19,22,23 |
| 112 | b1 = block & 0x3300330033003300 |
| 113 | b2 = block & 0x00cc00cc00cc00cc |
| 114 | block ^= b1 ^ b2 ^ b1 >> 6 ^ b2 << 6 |
| 115 | |
| 116 | // block is the permutation: |
| 117 | // 15 14 |
| 118 | // 13 12 |
| 119 | // 11 10 |
| 120 | // 9 8 |
| 121 | // 7 6 |
| 122 | // 5 4 |
| 123 | // 3 2 |
| 124 | // 1 0 [+16] [+32] [+64] |
| 125 | |
| 126 | // exchange 0,2,4,6 with 9,11,13,15: |
| 127 | b1 = block & 0xaaaaaaaa55555555 |
| 128 | block ^= b1 ^ b1 >> 33 ^ b1 << 33 |
| 129 | |
| 130 | // block is the permutation: |
| 131 | // 6 14 22 30 38 46 54 62 |
| 132 | // 4 12 20 28 36 44 52 60 |
| 133 | // 2 10 18 26 34 42 50 58 |
| 134 | // 0 8 16 24 32 40 48 56 |
| 135 | // 7 15 23 31 39 47 55 63 |
| 136 | // 5 13 21 29 37 45 53 61 |
| 137 | // 3 11 19 27 35 43 51 59 |
| 138 | // 1 9 17 25 33 41 49 57 |
| 139 | return block |
| 140 | } |
| 141 | |
| 142 | // permuteInitial_block is equivalent to the permutation defined |
| 143 | // by finalPermutation. |
| 144 | fn permute_final_block(b u64) u64 { |
| 145 | // Perform the same bit exchanges as permuteInitial_block |
| 146 | // but in reverse order. |
| 147 | mut block := b |
| 148 | mut b1 := block & 0xaaaaaaaa55555555 |
| 149 | block ^= b1 ^ b1 >> 33 ^ b1 << 33 |
| 150 | |
| 151 | b1 = block & 0x3300330033003300 |
| 152 | mut b2 := block & 0x00cc00cc00cc00cc |
| 153 | block ^= b1 ^ b2 ^ b1 >> 6 ^ b2 << 6 |
| 154 | |
| 155 | b1 = block & 0x0f0f00000f0f0000 |
| 156 | b2 = block & 0x0000f0f00000f0f0 |
| 157 | block ^= b1 ^ b2 ^ b1 >> 12 ^ b2 << 12 |
| 158 | |
| 159 | b1 = (block >> 32) & 0xff00ff |
| 160 | b2 = (block & 0xff00ff00) |
| 161 | block ^= b1 << 32 ^ b2 ^ b1 << 8 ^ b2 << 24 |
| 162 | |
| 163 | b1 = block >> 48 |
| 164 | b2 = block << 48 |
| 165 | block ^= b1 ^ b2 ^ b1 << 48 ^ b2 >> 48 |
| 166 | return block |
| 167 | } |
| 168 | |
| 169 | // creates 16 28-bit blocks rotated according |
| 170 | // to the rotation schedule |
| 171 | fn ks_rotate(ain u32) []u32 { |
| 172 | mut out := []u32{len: 16} |
| 173 | mut last := ain |
| 174 | for i := 0; i < 16; i++ { |
| 175 | // 28-bit circular left shift |
| 176 | left := (last << (4 + ks_rotations[i])) >> 4 |
| 177 | right := (last << 4) >> (32 - ks_rotations[i]) |
| 178 | out[i] = left | right |
| 179 | last = out[i] |
| 180 | } |
| 181 | return out |
| 182 | } |
| 183 | |
| 184 | // Expand 48-bit input to 64-bit, with each 6-bit block padded by extra two bits at the top. |
| 185 | // By doing so, we can have the input blocks (four bits each), and the key blocks (six bits each) well-aligned without |
| 186 | // extra shifts/rotations for alignments. |
| 187 | fn unpack(x u64) u64 { |
| 188 | return ((x >> (6 * 1)) & 0xff) << (8 * 0) | ((x >> (6 * 3)) & 0xff) << (8 * 1) | ((x >> (6 * 5)) & 0xff) << (8 * 2) | ((x >> (6 * 7)) & 0xff) << (8 * 3) | ((x >> (6 * 0)) & 0xff) << (8 * 4) | ((x >> (6 * 2)) & 0xff) << (8 * 5) | ((x >> (6 * 4)) & 0xff) << (8 * 6) | ((x >> (6 * 6)) & 0xff) << (8 * 7) |
| 189 | } |
| 190 | |