src/pkg/crypto/des/block.go - The Go Programming Language

Golang

Source file src/pkg/crypto/des/block.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package des
     6	
     7	import (
     8		"encoding/binary"
     9	)
    10	
    11	func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
    12		b := binary.BigEndian.Uint64(src)
    13		b = permuteBlock(b, initialPermutation[:])
    14		left, right := uint32(b>>32), uint32(b)
    15	
    16		var subkey uint64
    17		for i := 0; i < 16; i++ {
    18			if decrypt {
    19				subkey = subkeys[15-i]
    20			} else {
    21				subkey = subkeys[i]
    22			}
    23	
    24			left, right = right, left^feistel(right, subkey)
    25		}
    26		// switch left & right and perform final permutation
    27		preOutput := (uint64(right) << 32) | uint64(left)
    28		binary.BigEndian.PutUint64(dst, permuteBlock(preOutput, finalPermutation[:]))
    29	}
    30	
    31	// Encrypt one block from src into dst, using the subkeys.
    32	func encryptBlock(subkeys []uint64, dst, src []byte) {
    33		cryptBlock(subkeys, dst, src, false)
    34	}
    35	
    36	// Decrypt one block from src into dst, using the subkeys.
    37	func decryptBlock(subkeys []uint64, dst, src []byte) {
    38		cryptBlock(subkeys, dst, src, true)
    39	}
    40	
    41	// DES Feistel function
    42	func feistel(right uint32, key uint64) (result uint32) {
    43		sBoxLocations := key ^ permuteBlock(uint64(right), expansionFunction[:])
    44		var sBoxResult uint32
    45		for i := uint8(0); i < 8; i++ {
    46			sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
    47			sBoxLocations <<= 6
    48			// row determined by 1st and 6th bit
    49			row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
    50			// column is middle four bits
    51			column := (sBoxLocation >> 1) & 0xf
    52			sBoxResult |= uint32(sBoxes[i][row][column]) << (4 * (7 - i))
    53		}
    54		return uint32(permuteBlock(uint64(sBoxResult), permutationFunction[:]))
    55	}
    56	
    57	// general purpose function to perform DES block permutations
    58	func permuteBlock(src uint64, permutation []uint8) (block uint64) {
    59		for position, n := range permutation {
    60			bit := (src >> n) & 1
    61			block |= bit << uint((len(permutation)-1)-position)
    62		}
    63		return
    64	}
    65	
    66	// creates 16 28-bit blocks rotated according
    67	// to the rotation schedule
    68	func ksRotate(in uint32) (out []uint32) {
    69		out = make([]uint32, 16)
    70		last := in
    71		for i := 0; i < 16; i++ {
    72			// 28-bit circular left shift
    73			left := (last << (4 + ksRotations[i])) >> 4
    74			right := (last << 4) >> (32 - ksRotations[i])
    75			out[i] = left | right
    76			last = out[i]
    77		}
    78		return
    79	}
    80	
    81	// creates 16 56-bit subkeys from the original key
    82	func (c *desCipher) generateSubkeys(keyBytes []byte) {
    83		// apply PC1 permutation to key
    84		key := binary.BigEndian.Uint64(keyBytes)
    85		permutedKey := permuteBlock(key, permutedChoice1[:])
    86	
    87		// rotate halves of permuted key according to the rotation schedule
    88		leftRotations := ksRotate(uint32(permutedKey >> 28))
    89		rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
    90	
    91		// generate subkeys
    92		for i := 0; i < 16; i++ {
    93			// combine halves to form 56-bit input to PC2
    94			pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
    95			// apply PC2 permutation to 7 byte input
    96			c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
    97		}
    98	}