| 1 | // The source code refers to the go standard library |
| 2 | |
| 3 | module des |
| 4 | |
| 5 | import crypto.cipher |
| 6 | import crypto.internal.subtle |
| 7 | import encoding.binary |
| 8 | |
| 9 | const block_size = 8 |
| 10 | |
| 11 | // A tripleDesCipher is an instance of TripleDES encryption. |
| 12 | struct TripleDesCipher { |
| 13 | block_size int = block_size |
| 14 | mut: |
| 15 | cipher1 DesCipher |
| 16 | cipher2 DesCipher |
| 17 | cipher3 DesCipher |
| 18 | } |
| 19 | |
| 20 | // DesCipher is an instance of DES encryption. |
| 21 | struct DesCipher { |
| 22 | block_size int = block_size |
| 23 | mut: |
| 24 | subkeys [16]u64 |
| 25 | } |
| 26 | |
| 27 | // NewCipher creates and returns a new cipher.Block. |
| 28 | pub 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 |
| 39 | fn (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 |
| 60 | pub 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 |
| 74 | pub 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. |
| 88 | pub 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 |
| 100 | pub 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 |
| 137 | pub 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 | |