170 lines
4.7 KiB
V
170 lines
4.7 KiB
V
|
// The source code refers to the go standard library
|
||
|
|
||
|
module des
|
||
|
|
||
|
import crypto.cipher
|
||
|
import crypto.internal.subtle
|
||
|
import encoding.binary
|
||
|
|
||
|
const block_size = 8
|
||
|
|
||
|
// A tripleDesCipher is an instance of TripleDES encryption.
|
||
|
struct TripleDesCipher {
|
||
|
block_size int = des.block_size
|
||
|
mut:
|
||
|
cipher1 DesCipher
|
||
|
cipher2 DesCipher
|
||
|
cipher3 DesCipher
|
||
|
}
|
||
|
|
||
|
// DesCipher is an instance of DES encryption.
|
||
|
struct DesCipher {
|
||
|
block_size int = des.block_size
|
||
|
mut:
|
||
|
subkeys [16]u64
|
||
|
}
|
||
|
|
||
|
// NewCipher creates and returns a new cipher.Block.
|
||
|
pub fn new_cipher(key []byte) cipher.Block {
|
||
|
if key.len != 8 {
|
||
|
panic('crypto.aes: invalid key size')
|
||
|
}
|
||
|
|
||
|
mut c := DesCipher{}
|
||
|
c.generate_subkeys(key)
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
// creates 16 56-bit subkeys from the original key
|
||
|
fn (mut c DesCipher) generate_subkeys(key_bytes []byte) {
|
||
|
// feistel_box_once.do(initFeistel_box)
|
||
|
|
||
|
// apply PC1 permutation to key
|
||
|
key := binary.big_endian_u64(key_bytes)
|
||
|
permuted_key := permute_block(key, permuted_choice1[..])
|
||
|
|
||
|
// rotate halves of permuted key according to the rotation schedule
|
||
|
left_rotations := ks_rotate(u32(permuted_key >> 28))
|
||
|
right_rotations := ks_rotate(u32(permuted_key << 4) >> 4)
|
||
|
|
||
|
// generate subkeys
|
||
|
for i := 0; i < 16; i++ {
|
||
|
// combine halves to form 56-bit input to PC2
|
||
|
pc2_input := u64(left_rotations[i]) << 28 | u64(right_rotations[i])
|
||
|
// apply PC2 permutation to 7 byte input
|
||
|
c.subkeys[i] = unpack(permute_block(pc2_input, permuted_choice2[..]))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn (c &DesCipher) encrypt(mut dst []byte, src []byte) {
|
||
|
if src.len < des.block_size {
|
||
|
panic('crypto/des: input not full block')
|
||
|
}
|
||
|
if dst.len < des.block_size {
|
||
|
panic('crypto/des: output not full block')
|
||
|
}
|
||
|
if subtle.inexact_overlap(dst[..des.block_size], src[..des.block_size]) {
|
||
|
panic('crypto/des: invalid buffer overlap')
|
||
|
}
|
||
|
encrypt_block(c.subkeys[..], mut dst, src)
|
||
|
}
|
||
|
|
||
|
pub fn (c &DesCipher) decrypt(mut dst []byte, src []byte) {
|
||
|
if src.len < des.block_size {
|
||
|
panic('crypto/des: input not full block')
|
||
|
}
|
||
|
if dst.len < des.block_size {
|
||
|
panic('crypto/des: output not full block')
|
||
|
}
|
||
|
if subtle.inexact_overlap(dst[..des.block_size], src[..des.block_size]) {
|
||
|
panic('crypto/des: invalid buffer overlap')
|
||
|
}
|
||
|
decrypt_block(c.subkeys[..], mut dst, src)
|
||
|
}
|
||
|
|
||
|
// NewTripleDesCipher creates and returns a new cipher.Block.
|
||
|
pub fn new_triple_des_cipher(key []byte) cipher.Block {
|
||
|
if key.len != 24 {
|
||
|
panic('crypto.des: invalid key size')
|
||
|
}
|
||
|
mut c := TripleDesCipher{}
|
||
|
c.cipher1.generate_subkeys(key[..8])
|
||
|
c.cipher2.generate_subkeys(key[8..16])
|
||
|
c.cipher3.generate_subkeys(key[16..])
|
||
|
return c
|
||
|
}
|
||
|
|
||
|
pub fn (c &TripleDesCipher) encrypt(mut dst []byte, src []byte) {
|
||
|
if src.len < des.block_size {
|
||
|
panic('crypto/des: input not full block')
|
||
|
}
|
||
|
if dst.len < des.block_size {
|
||
|
panic('crypto/des: output not full block')
|
||
|
}
|
||
|
if subtle.inexact_overlap(dst[..des.block_size], src[..des.block_size]) {
|
||
|
panic('crypto/des: invalid buffer overlap')
|
||
|
}
|
||
|
|
||
|
mut b := binary.big_endian_u64(src)
|
||
|
b = permute_initial_block(b)
|
||
|
mut left, mut right := u32(b >> 32), u32(b)
|
||
|
|
||
|
left = (left << 1) | (left >> 31)
|
||
|
right = (right << 1) | (right >> 31)
|
||
|
|
||
|
for i := 0; i < 8; i++ {
|
||
|
left, right = feistel(left, right, c.cipher1.subkeys[2 * i], c.cipher1.subkeys[2 * i + 1])
|
||
|
}
|
||
|
for i := 0; i < 8; i++ {
|
||
|
right, left = feistel(right, left, c.cipher2.subkeys[15 - 2 * i], c.cipher2.subkeys[15 - (
|
||
|
2 * i + 1)])
|
||
|
}
|
||
|
for i := 0; i < 8; i++ {
|
||
|
left, right = feistel(left, right, c.cipher3.subkeys[2 * i], c.cipher3.subkeys[2 * i + 1])
|
||
|
}
|
||
|
|
||
|
left = (left << 31) | (left >> 1)
|
||
|
right = (right << 31) | (right >> 1)
|
||
|
|
||
|
pre_output := (u64(right) << 32) | u64(left)
|
||
|
binary.big_endian_put_u64(mut dst, permute_final_block(pre_output))
|
||
|
}
|
||
|
|
||
|
pub fn (c &TripleDesCipher) decrypt(mut dst []byte, src []byte) {
|
||
|
if src.len < des.block_size {
|
||
|
panic('crypto/des: input not full block')
|
||
|
}
|
||
|
if dst.len < des.block_size {
|
||
|
panic('crypto/des: output not full block')
|
||
|
}
|
||
|
if subtle.inexact_overlap(dst[..des.block_size], src[..des.block_size]) {
|
||
|
panic('crypto/des: invalid buffer overlap')
|
||
|
}
|
||
|
|
||
|
mut b := binary.big_endian_u64(src)
|
||
|
b = permute_initial_block(b)
|
||
|
|
||
|
mut left, mut right := u32(b >> 32), u32(b)
|
||
|
|
||
|
left = (left << 1) | (left >> 31)
|
||
|
right = (right << 1) | (right >> 31)
|
||
|
|
||
|
for i := 0; i < 8; i++ {
|
||
|
left, right = feistel(left, right, c.cipher3.subkeys[15 - 2 * i], c.cipher3.subkeys[15 - (
|
||
|
2 * i + 1)])
|
||
|
}
|
||
|
for i := 0; i < 8; i++ {
|
||
|
right, left = feistel(right, left, c.cipher2.subkeys[2 * i], c.cipher2.subkeys[2 * i + 1])
|
||
|
}
|
||
|
for i := 0; i < 8; i++ {
|
||
|
left, right = feistel(left, right, c.cipher1.subkeys[15 - 2 * i], c.cipher1.subkeys[15 - (
|
||
|
2 * i + 1)])
|
||
|
}
|
||
|
|
||
|
left = (left << 31) | (left >> 1)
|
||
|
right = (right << 31) | (right >> 1)
|
||
|
|
||
|
pre_output := (u64(right) << 32) | u64(left)
|
||
|
binary.big_endian_put_u64(mut dst, permute_final_block(pre_output))
|
||
|
}
|