crypto: add a crypto.des module (#13065)

pull/13067/head
688862 2022-01-07 19:51:37 +08:00 committed by GitHub
parent 7276705684
commit 2b42ea9883
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 793 additions and 0 deletions

View File

@ -0,0 +1,121 @@
// The source code refers to the go standard library, which will be combined with AES in the future.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
// Cipher block chaining (CBC) mode.
// CBC provides confidentiality by xoring (chaining) each plaintext block
// with the previous ciphertext block before applying the block cipher.
// See NIST SP 800-38A, pp 10-11
// NOTE this will be moved to crypto.cipher interface (joe-c)
module cipher
import crypto.internal.subtle
struct Cbc {
mut:
b Block
block_size int
iv []byte
tmp []byte
}
// internal
fn new_des_cbc(b Block, iv []byte) Cbc {
return Cbc{
b: b
block_size: b.block_size
iv: iv.clone()
tmp: []byte{len: b.block_size}
}
}
// new_cbc returns a `DesCbc` which encrypts in cipher block chaining
// mode, using the given Block. The length of iv must be the same as the
// Block's block size.
pub fn new_cbc(b Block, iv []byte) Cbc {
if iv.len != b.block_size {
panic('crypto.cipher.new_cbc_encrypter: IV length must equal block size')
}
return new_des_cbc(b, iv)
}
// encrypt_blocks encrypts the blocks in `src_` to `dst_`.
// Please note: `dst_` is mutable for performance reasons.
pub fn (x &Cbc) encrypt_blocks(mut dst_ []byte, src_ []byte) {
unsafe {
mut dst := *dst_
mut src := src_
if src.len % x.block_size != 0 {
panic('crypto.cipher: input not full blocks')
}
if dst.len < src.len {
panic('crypto.cipher: output smaller than input')
}
if subtle.inexact_overlap(dst[..src.len], src_) {
panic('crypto.cipher: invalid buffer overlap')
}
mut iv := x.iv
for src.len > 0 {
// Write the xor to dst, then encrypt in place.
xor_bytes(mut dst[..x.block_size], src[..x.block_size], iv)
x.b.encrypt(mut dst[..x.block_size], dst[..x.block_size])
// Move to the next block with this block as the next iv.
iv = dst[..x.block_size]
if x.block_size >= src.len {
src = []
} else {
src = src[x.block_size..]
}
dst = dst[x.block_size..]
}
// Save the iv for the next crypt_blocks call.
copy(x.iv, iv)
}
}
// decrypt_blocks decrypts the blocks in `src` to `dst`.
// Please note: `dst` is mutable for performance reasons.
pub fn (mut x Cbc) decrypt_blocks(mut dst []byte, src []byte) {
if src.len % x.block_size != 0 {
panic('crypto.cipher: input not full blocks')
}
if dst.len < src.len {
panic('crypto.cipher: output smaller than input')
}
if subtle.inexact_overlap((*dst)[..src.len], src) {
panic('crypto.cipher: invalid buffer overlap')
}
if src.len == 0 {
return
}
// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
// To avoid making a copy each time, we loop over the blocks BACKWARDS.
mut end := src.len
mut start := end - x.block_size
mut prev := start - x.block_size
// Copy the last block of ciphertext in preparation as the new iv.
copy(x.tmp, src[start..end])
// Loop over all but the first block.
for start > 0 {
src_chunk := src[start..end]
x.b.decrypt(mut (*dst)[start..end], src_chunk)
xor_bytes(mut (*dst)[start..end], (*dst)[start..end], src[prev..start])
end = start
start = prev
prev -= x.block_size
}
// The first block is special because it uses the saved iv.
src_chunk := src[start..end]
x.b.decrypt(mut (*dst)[start..end], src_chunk)
xor_bytes(mut (*dst)[start..end], (*dst)[start..end], x.iv)
// Set the new iv to the first block we copied earlier.
x.iv = x.tmp
x.tmp = x.iv
}
fn (x &Cbc) set_iv(iv []byte) {
if iv.len != x.iv.len {
panic('cipher: incorrect length IV')
}
copy(x.iv, iv)
}

View File

@ -0,0 +1,55 @@
// The source code refers to the go standard library, which will be combined with AES in the future.
module cipher
// A Block represents an implementation of block cipher
// using a given key. It provides the capability to encrypt
// or decrypt individual blocks. The mode implementations
// extend that capability to streams of blocks.
interface Block {
block_size int // block_size returns the cipher's block size.
encrypt(mut dst []byte, src []byte) // Encrypt encrypts the first block in src into dst.
// Dst and src must overlap entirely or not at all.
decrypt(mut dst []byte, src []byte) // Decrypt decrypts the first block in src into dst.
// Dst and src must overlap entirely or not at all.
}
// A Stream represents a stream cipher.
interface Stream {
// xor_key_stream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
// If len(dst) < len(src), xor_key_stream should panic. It is acceptable
// to pass a dst bigger than src, and in that case, xor_key_stream will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to xor_key_stream behave as if the concatenation of
// the src buffers was passed in a single run. That is, Stream
// maintains state and does not reset at each xor_key_stream call.
xor_key_stream(mut dst []byte, src []byte)
}
// A BlockMode represents a block cipher running in a block-based mode (CBC,
// ECB etc).
interface BlockMode {
block_size int // block_size returns the mode's block size.
crypt_blocks(mut dst []byte, src []byte) // crypt_blocks encrypts or decrypts a number of blocks. The length of
// src must be a multiple of the block size. Dst and src must overlap
// entirely or not at all.
//
// If len(dst) < len(src), crypt_blocks should panic. It is acceptable
// to pass a dst bigger than src, and in that case, crypt_blocks will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to crypt_blocks behave as if the concatenation of
// the src buffers was passed in a single run. That is, BlockMode
// maintains state and does not reset at each crypt_blocks call.
}
// Utility routines
// fn dup(p []byte) []byte {
// q := make([]byte, p.len)
// copy(q, p)
// return q
// }

View File

@ -0,0 +1,54 @@
import crypto.des
import crypto.cipher
const (
key = '123456789012345678901234'.bytes()
iv = 'abcdegfh'.bytes()
str = '73c86d43a9d700a253a96c85b0f6b03ac9792e0e757f869cca306bd3cba1c62b'
)
fn test_triple_des_cbc() {
mut src := str.bytes()
triple_des_cbc_en(mut src, key, iv)
assert src.hex() == '59d657007dc96062e8fffd574afda480ddba21fa06337ac5676eb4e40db256f2ab31ed442c0e4a82ef59b96292d24902c86b20c50bd8506e387775ca58f8c4fe'
triple_des_cbc_de(mut src, key, iv)
assert src.bytestr() == str
println('test_triple_des_cbc ok')
}
fn test_des_cbc() {
mut src := str.bytes()
des_cbc_en(mut src, key[..8], iv)
assert src.hex() == '198f94ca5989900ce73b26c3ce0005fa747b74d81e8cc5d529f96c1a2e7748d39f9900b9049cbfda35ef720d495b134f4f7dd2d7d3d910af488cdccd27d9f057'
des_cbc_de(mut src, key[..8], iv)
assert src.bytestr() == str
println('test_des_cbc ok')
}
fn des_cbc_en(mut src []byte, key []byte, iv []byte) {
block := des.new_cipher(key)
mode := cipher.new_cbc(block, iv)
mode.encrypt_blocks(mut src, src.clone())
}
fn des_cbc_de(mut src []byte, key []byte, iv []byte) {
block := des.new_cipher(key)
mut mode := cipher.new_cbc(block, iv)
mode.decrypt_blocks(mut src, src.clone())
}
fn triple_des_cbc_en(mut src []byte, key []byte, iv []byte) {
block := des.new_triple_des_cipher(key)
mode := cipher.new_cbc(block, iv)
mode.encrypt_blocks(mut src, src.clone())
}
fn triple_des_cbc_de(mut src []byte, key []byte, iv []byte) {
block := des.new_triple_des_cipher(key)
mut mode := cipher.new_cbc(block, iv)
mode.decrypt_blocks(mut src, src.clone())
}

View File

@ -0,0 +1,189 @@
// The source code refers to the go standard library, which can be merged with AES later
module des
import encoding.binary
fn feistel(ll u32, rr u32, k0 u64, k1 u64) (u32, u32) {
mut l := ll
mut r := rr
mut t := r ^ u32(k0 >> 32)
l ^= feistel_box[7][t & 0x3f] ^ feistel_box[5][(t >> 8) & 0x3f] ^ feistel_box[3][(t >> 16) & 0x3f] ^ feistel_box[1][(t >> 24) & 0x3f]
t = ((r << 28) | (r >> 4)) ^ u32(k0)
l ^= feistel_box[6][t & 0x3f] ^ feistel_box[4][(t >> 8) & 0x3f] ^ feistel_box[2][(t >> 16) & 0x3f] ^ feistel_box[0][(t >> 24) & 0x3f]
t = l ^ u32(k1 >> 32)
r ^= feistel_box[7][t & 0x3f] ^ feistel_box[5][(t >> 8) & 0x3f] ^ feistel_box[3][(t >> 16) & 0x3f] ^ feistel_box[1][(t >> 24) & 0x3f]
t = ((l << 28) | (l >> 4)) ^ u32(k1)
r ^= feistel_box[6][t & 0x3f] ^ feistel_box[4][(t >> 8) & 0x3f] ^ feistel_box[2][(t >> 16) & 0x3f] ^ feistel_box[0][(t >> 24) & 0x3f]
return l, r
}
fn crypt_block(subkeys []u64, mut dst []byte, src []byte, decrypt bool) {
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)
if decrypt {
for i := 0; i < 8; i++ {
left, right = feistel(left, right, subkeys[15 - 2 * i], subkeys[15 - (2 * i + 1)])
}
} else {
for i := 0; i < 8; i++ {
left, right = feistel(left, right, subkeys[2 * i], subkeys[2 * i + 1])
}
}
left = (left << 31) | (left >> 1)
right = (right << 31) | (right >> 1)
// switch left & right and perform final permutation
pre_output := (u64(right) << 32) | u64(left)
binary.big_endian_put_u64(mut dst, permute_final_block(pre_output))
}
// Encrypt one block from src into dst, using the subkeys.
pub fn encrypt_block(subkeys []u64, mut dst []byte, src []byte) {
crypt_block(subkeys, mut dst, src, false)
}
// Decrypt one block from src into dst, using the subkeys.
fn decrypt_block(subkeys []u64, mut dst []byte, src []byte) {
crypt_block(subkeys, mut dst, src, true)
}
// general purpose function to perform DES block permutations
fn permute_block(src u64, permutation []byte) u64 {
mut block := u64(0)
for position, n in permutation {
bit := (src >> u64(u8(n))) & 1
block |= bit << u64((permutation.len - 1) - position)
}
return block
}
// permuteInitial_block is equivalent to the permutation defined
// by initialPermutation.
fn permute_initial_block(b u64) u64 {
// block = b7 b6 b5 b4 b3 b2 b1 b0 (8 bytes)
mut block := b
mut b1 := block >> 48
mut b2 := block << 48
block ^= b1 ^ b2 ^ b1 << 48 ^ b2 >> 48
// block = b1 b0 b5 b4 b3 b2 b7 b6
b1 = block >> 32 & 0xff00ff
b2 = (block & 0xff00ff00)
block ^= b1 << 32 ^ b2 ^ b1 << 8 ^ b2 << 24 // exchange b0 b4 with b3 b7
// block is now b1 b3 b5 b7 b0 b2 b4 b6, the permutation:
// ... 8
// ... 24
// ... 40
// ... 56
// 7 6 5 4 3 2 1 0
// 23 22 21 20 19 18 17 16
// ... 32
// ... 48
// exchange 4,5,6,7 with 32,33,34,35 etc.
b1 = block & 0x0f0f00000f0f0000
b2 = block & 0x0000f0f00000f0f0
block ^= b1 ^ b2 ^ b1 >> 12 ^ b2 << 12
// block is the permutation:
//
// [+8] [+40]
//
// 7 6 5 4
// 23 22 21 20
// 3 2 1 0
// 19 18 17 16 [+32]
// exchange 0,1,4,5 with 18,19,22,23
b1 = block & 0x3300330033003300
b2 = block & 0x00cc00cc00cc00cc
block ^= b1 ^ b2 ^ b1 >> 6 ^ b2 << 6
// block is the permutation:
// 15 14
// 13 12
// 11 10
// 9 8
// 7 6
// 5 4
// 3 2
// 1 0 [+16] [+32] [+64]
// exchange 0,2,4,6 with 9,11,13,15:
b1 = block & 0xaaaaaaaa55555555
block ^= b1 ^ b1 >> 33 ^ b1 << 33
// block is the permutation:
// 6 14 22 30 38 46 54 62
// 4 12 20 28 36 44 52 60
// 2 10 18 26 34 42 50 58
// 0 8 16 24 32 40 48 56
// 7 15 23 31 39 47 55 63
// 5 13 21 29 37 45 53 61
// 3 11 19 27 35 43 51 59
// 1 9 17 25 33 41 49 57
return block
}
// permuteInitial_block is equivalent to the permutation defined
// by finalPermutation.
fn permute_final_block(b u64) u64 {
// Perform the same bit exchanges as permuteInitial_block
// but in reverse order.
mut block := b
mut b1 := block & 0xaaaaaaaa55555555
block ^= b1 ^ b1 >> 33 ^ b1 << 33
b1 = block & 0x3300330033003300
mut b2 := block & 0x00cc00cc00cc00cc
block ^= b1 ^ b2 ^ b1 >> 6 ^ b2 << 6
b1 = block & 0x0f0f00000f0f0000
b2 = block & 0x0000f0f00000f0f0
block ^= b1 ^ b2 ^ b1 >> 12 ^ b2 << 12
b1 = block >> 32 & 0xff00ff
b2 = (block & 0xff00ff00)
block ^= b1 << 32 ^ b2 ^ b1 << 8 ^ b2 << 24
b1 = block >> 48
b2 = block << 48
block ^= b1 ^ b2 ^ b1 << 48 ^ b2 >> 48
return block
}
// creates 16 28-bit blocks rotated according
// to the rotation schedule
fn ks_rotate(ain u32) []u32 {
mut out := []u32{len: 16}
mut last := ain
for i := 0; i < 16; i++ {
// 28-bit circular left shift
left := (last << (4 + ks_rotations[i])) >> 4
right := (last << 4) >> (32 - ks_rotations[i])
out[i] = left | right
last = out[i]
}
return out
}
// Expand 48-bit input to 64-bit, with each 6-bit block padded by extra two bits at the top.
// By doing so, we can have the input blocks (four bits each), and the key blocks (six bits each) well-aligned without
// extra shifts/rotations for alignments.
fn unpack(x u64) u64 {
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)
}

View File

@ -0,0 +1,154 @@
// The source code refers to the go standard library, which can be merged with AES later
// Package des implements the Data Encryption Standard (DES) and the
// Triple Data Encryption Algorithm (TDEA) as defined
// in U.S. Federal Information Processing Standards Publication 46-3.
//
// DES is cryptographically broken and should not be used for secure
// applications.
module des
// Used to perform an initial permutation of a 64-bit input block.
// const initial_permutation = [byte(6), 14, 22, 30, 38, 46, 54, 62, 4, 12, 20, 28, 36, 44, 52, 60,
// 2, 10, 18, 26, 34, 42, 50, 58, 0, 8, 16, 24, 32, 40, 48, 56, 7, 15, 23, 31, 39, 47, 55, 63,
// 5, 13, 21, 29, 37, 45, 53, 61, 3, 11, 19, 27, 35, 43, 51, 59, 1, 9, 17, 25, 33, 41, 49, 57]
// // Used to perform a final permutation of a 4-bit preoutput block. This is the
// // inverse of initialPermutation
// const final_permutation = [byte(24), 56, 16, 48, 8, 40, 0, 32, 25, 57, 17, 49, 9, 41, 1, 33, 26,
// 58, 18, 50, 10, 42, 2, 34, 27, 59, 19, 51, 11, 43, 3, 35, 28, 60, 20, 52, 12, 44, 4, 36, 29,
// 61, 21, 53, 13, 45, 5, 37, 30, 62, 22, 54, 14, 46, 6, 38, 31, 63, 23, 55, 15, 47, 7, 39]
// // Used to expand an input block of 32 bits, producing an output block of 48
// // bits.
// const expansion_function = [byte(0), 31, 30, 29, 28, 27, 28, 27, 26, 25, 24, 23, 24, 23, 22, 21,
// 20, 19, 20, 19, 18, 17, 16, 15, 16, 15, 14, 13, 12, 11, 12, 11, 10, 9, 8, 7, 8, 7, 6, 5, 4,
// 3, 4, 3, 2, 1, 0, 31]
// // Yields a 32-bit output from a 32-bit input
// const permutation_function = [byte(16), 25, 12, 11, 3, 20, 4, 15, 31, 17, 9, 6, 27, 14, 1, 22,
// 30, 24, 8, 18, 0, 5, 29, 23, 13, 19, 2, 26, 10, 21, 28, 7]
// Used in the key schedule to select 56 bits
// from a 64-bit input.
const permuted_choice1 = [byte(7), 15, 23, 31, 39, 47, 55, 63, 6, 14, 22, 30, 38, 46, 54, 62, 5,
13, 21, 29, 37, 45, 53, 61, 4, 12, 20, 28, 1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34,
42, 50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 36, 44, 52, 60]
// Used in the key schedule to produce each subkey by selecting 48 bits from
// the 56-bit input
const permuted_choice2 = [byte(42), 39, 45, 32, 55, 51, 53, 28, 41, 50, 35, 46, 33, 37, 44, 52,
30, 48, 40, 49, 29, 36, 43, 54, 15, 4, 25, 19, 9, 1, 26, 16, 5, 11, 23, 8, 12, 7, 17, 0, 22,
3, 10, 14, 6, 20, 27, 24]
// 8 S-boxes composed of 4 rows and 16 columns
// Used in the DES cipher function
// const s_boxes = [
// [
// [u8(14), 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
// [u8(0), 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
// [u8(4), 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
// [u8(15), 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
// ],
// [
// [u8(15), 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
// [u8(3), 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
// [u8(0), 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
// [u8(13), 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
// ],
// [
// [u8(10), 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
// [u8(13), 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
// [u8(13), 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
// [u8(1), 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
// ],
// [
// [u8(7), 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
// [u8(13), 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
// [u8(10), 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
// [u8(3), 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
// ],
// [
// [u8(2), 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
// [u8(14), 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
// [u8(4), 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
// [u8(11), 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
// ],
// [
// [u8(12), 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
// [u8(10), 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
// [u8(9), 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
// [u8(4), 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
// ],
// [
// [u8(4), 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
// [u8(13), 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
// [u8(1), 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
// [u8(6), 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
// ],
// [
// [u8(13), 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
// [u8(1), 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
// [u8(7), 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
// [u8(2), 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
// ],
// ]
const feistel_box = [
[u32(16843776), 0, 65536, 16843780, 16842756, 66564, 4, 65536, 1024, 16843776, 16843780, 1024,
16778244, 16842756, 16777216, 4, 1028, 16778240, 16778240, 66560, 66560, 16842752, 16842752,
16778244, 65540, 16777220, 16777220, 65540, 0, 1028, 66564, 16777216, 65536, 16843780,
4, 16842752, 16843776, 16777216, 16777216, 1024, 16842756, 65536, 66560, 16777220, 1024,
4, 16778244, 66564, 16843780, 65540, 16842752, 16778244, 16777220, 1028, 66564, 16843776,
1028, 16778240, 16778240, 0, 65540, 66560, 0, 16842756],
[u32(2148565024), 2147516416, 32768, 1081376, 1048576, 32, 2148532256, 2147516448, 2147483680,
2148565024, 2148564992, 2147483648, 2147516416, 1048576, 32, 2148532256, 1081344, 1048608,
2147516448, 0, 2147483648, 32768, 1081376, 2148532224, 1048608, 2147483680, 0, 1081344,
32800, 2148564992, 2148532224, 32800, 0, 1081376, 2148532256, 1048576, 2147516448, 2148532224,
2148564992, 32768, 2148532224, 2147516416, 32, 2148565024, 1081376, 32, 32768, 2147483648,
32800, 2148564992, 1048576, 2147483680, 1048608, 2147516448, 2147483680, 1048608, 1081344,
0, 2147516416, 32800, 2147483648, 2148532256, 2148565024, 1081344],
[u32(520), 134349312, 0, 134348808, 134218240, 0, 131592, 134218240, 131080, 134217736, 134217736,
131072, 134349320, 131080, 134348800, 520, 134217728, 8, 134349312, 512, 131584, 134348800,
134348808, 131592, 134218248, 131584, 131072, 134218248, 8, 134349320, 512, 134217728,
134349312, 134217728, 131080, 520, 131072, 134349312, 134218240, 0, 512, 131080, 134349320,
134218240, 134217736, 512, 0, 134348808, 134218248, 131072, 134217728, 134349320, 8, 131592,
131584, 134217736, 134348800, 134218248, 520, 134348800, 131592, 8, 134348808, 131584],
[u32(8396801), 8321, 8321, 128, 8396928, 8388737, 8388609, 8193, 0, 8396800, 8396800, 8396929,
129, 0, 8388736, 8388609, 1, 8192, 8388608, 8396801, 128, 8388608, 8193, 8320, 8388737,
1, 8320, 8388736, 8192, 8396928, 8396929, 129, 8388736, 8388609, 8396800, 8396929, 129,
0, 0, 8396800, 8320, 8388736, 8388737, 1, 8396801, 8321, 8321, 128, 8396929, 129, 1, 8192,
8388609, 8193, 8396928, 8388737, 8193, 8320, 8388608, 8396801, 128, 8388608, 8192, 8396928],
[u32(256), 34078976, 34078720, 1107296512, 524288, 256, 1073741824, 34078720, 1074266368, 524288,
33554688, 1074266368, 1107296512, 1107820544, 524544, 1073741824, 33554432, 1074266112,
1074266112, 0, 1073742080, 1107820800, 1107820800, 33554688, 1107820544, 1073742080, 0,
1107296256, 34078976, 33554432, 1107296256, 524544, 524288, 1107296512, 256, 33554432,
1073741824, 34078720, 1107296512, 1074266368, 33554688, 1073741824, 1107820544, 34078976,
1074266368, 256, 33554432, 1107820544, 1107820800, 524544, 1107296256, 1107820800, 34078720,
0, 1074266112, 1107296256, 524544, 33554688, 1073742080, 524288, 0, 1074266112, 34078976,
1073742080],
[u32(536870928), 541065216, 16384, 541081616, 541065216, 16, 541081616, 4194304, 536887296,
4210704, 4194304, 536870928, 4194320, 536887296, 536870912, 16400, 0, 4194320, 536887312,
16384, 4210688, 536887312, 16, 541065232, 541065232, 0, 4210704, 541081600, 16400, 4210688,
541081600, 536870912, 536887296, 16, 541065232, 4210688, 541081616, 4194304, 16400, 536870928,
4194304, 536887296, 536870912, 16400, 536870928, 541081616, 4210688, 541065216, 4210704,
541081600, 0, 541065232, 16, 16384, 541065216, 4210704, 16384, 4194320, 536887312, 0,
541081600, 536870912, 4194320, 536887312],
[u32(2097152), 69206018, 67110914, 0, 2048, 67110914, 2099202, 69208064, 69208066, 2097152,
0, 67108866, 2, 67108864, 69206018, 2050, 67110912, 2099202, 2097154, 67110912, 67108866,
69206016, 69208064, 2097154, 69206016, 2048, 2050, 69208066, 2099200, 2, 67108864, 2099200,
67108864, 2099200, 2097152, 67110914, 67110914, 69206018, 69206018, 2, 2097154, 67108864,
67110912, 2097152, 69208064, 2050, 2099202, 69208064, 2050, 67108866, 69208066, 69206016,
2099200, 0, 2, 69208066, 0, 2099202, 69206016, 2048, 67108866, 67110912, 2048, 2097154],
[u32(268439616), 4096, 262144, 268701760, 268435456, 268439616, 64, 268435456, 262208, 268697600,
268701760, 266240, 268701696, 266304, 4096, 64, 268697600, 268435520, 268439552, 4160,
266240, 262208, 268697664, 268701696, 4160, 0, 0, 268697664, 268435520, 268439552, 266304,
262144, 266304, 262144, 268701696, 4096, 64, 268697664, 4096, 266304, 268439552, 64,
268435520, 268697600, 268697664, 268435456, 262144, 268439616, 0, 268701760, 262208,
268435520, 268697600, 268439552, 268439616, 0, 268701760, 266240, 266240, 4160, 4160, 262208,
268435456, 268701696],
]
// Size of left rotation per round in each half of the key schedule
const ks_rotations = [u8(1), 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]

View File

@ -0,0 +1,169 @@
// 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))
}

View File

@ -0,0 +1,51 @@
import crypto.des
const (
key = '123456789012345678901234'.bytes()
iv = 'abcdegfh'.bytes()
str = 'aaaaaaaa'
)
fn test_triple_des() {
mut src := str.bytes()
triple_des_en(mut src, key, iv)
assert src.hex() == '45902cf00aa1df46'
triple_des_de(mut src, key, iv)
assert src.bytestr() == str
println('test_triple_des ok')
}
fn test_des() {
mut src := str.bytes()
des_en(mut src, key[..8], iv)
assert src.hex() == '72dca13c37223cf0'
des_de(mut src, key[..8], iv)
assert src.bytestr() == str
println('test_des ok')
}
fn des_en(mut src []byte, key []byte, iv []byte) {
block := des.new_cipher(key)
block.encrypt(mut src, src.clone())
}
fn des_de(mut src []byte, key []byte, iv []byte) {
block := des.new_cipher(key)
block.decrypt(mut src, src.clone())
}
fn triple_des_en(mut src []byte, key []byte, iv []byte) {
block := des.new_triple_des_cipher(key)
block.encrypt(mut src, src.clone())
}
fn triple_des_de(mut src []byte, key []byte, iv []byte) {
block := des.new_triple_des_cipher(key)
inbuf := src.clone()
block.decrypt(mut src, inbuf)
}