Black Lives Matter. Support the Equal Justice Initiative.

Source file src/crypto/des/cipher.go

Documentation: crypto/des

     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  	"crypto/cipher"
     9  	"crypto/internal/subtle"
    10  	"encoding/binary"
    11  	"strconv"
    12  )
    13  
    14  // The DES block size in bytes.
    15  const BlockSize = 8
    16  
    17  type KeySizeError int
    18  
    19  func (k KeySizeError) Error() string {
    20  	return "crypto/des: invalid key size " + strconv.Itoa(int(k))
    21  }
    22  
    23  // desCipher is an instance of DES encryption.
    24  type desCipher struct {
    25  	subkeys [16]uint64
    26  }
    27  
    28  // NewCipher creates and returns a new cipher.Block.
    29  func NewCipher(key []byte) (cipher.Block, error) {
    30  	if len(key) != 8 {
    31  		return nil, KeySizeError(len(key))
    32  	}
    33  
    34  	c := new(desCipher)
    35  	c.generateSubkeys(key)
    36  	return c, nil
    37  }
    38  
    39  func (c *desCipher) BlockSize() int { return BlockSize }
    40  
    41  func (c *desCipher) Encrypt(dst, src []byte) {
    42  	if len(src) < BlockSize {
    43  		panic("crypto/des: input not full block")
    44  	}
    45  	if len(dst) < BlockSize {
    46  		panic("crypto/des: output not full block")
    47  	}
    48  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
    49  		panic("crypto/des: invalid buffer overlap")
    50  	}
    51  	encryptBlock(c.subkeys[:], dst, src)
    52  }
    53  
    54  func (c *desCipher) Decrypt(dst, src []byte) {
    55  	if len(src) < BlockSize {
    56  		panic("crypto/des: input not full block")
    57  	}
    58  	if len(dst) < BlockSize {
    59  		panic("crypto/des: output not full block")
    60  	}
    61  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
    62  		panic("crypto/des: invalid buffer overlap")
    63  	}
    64  	decryptBlock(c.subkeys[:], dst, src)
    65  }
    66  
    67  // A tripleDESCipher is an instance of TripleDES encryption.
    68  type tripleDESCipher struct {
    69  	cipher1, cipher2, cipher3 desCipher
    70  }
    71  
    72  // NewTripleDESCipher creates and returns a new cipher.Block.
    73  func NewTripleDESCipher(key []byte) (cipher.Block, error) {
    74  	if len(key) != 24 {
    75  		return nil, KeySizeError(len(key))
    76  	}
    77  
    78  	c := new(tripleDESCipher)
    79  	c.cipher1.generateSubkeys(key[:8])
    80  	c.cipher2.generateSubkeys(key[8:16])
    81  	c.cipher3.generateSubkeys(key[16:])
    82  	return c, nil
    83  }
    84  
    85  func (c *tripleDESCipher) BlockSize() int { return BlockSize }
    86  
    87  func (c *tripleDESCipher) Encrypt(dst, src []byte) {
    88  	if len(src) < BlockSize {
    89  		panic("crypto/des: input not full block")
    90  	}
    91  	if len(dst) < BlockSize {
    92  		panic("crypto/des: output not full block")
    93  	}
    94  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
    95  		panic("crypto/des: invalid buffer overlap")
    96  	}
    97  
    98  	b := binary.BigEndian.Uint64(src)
    99  	b = permuteInitialBlock(b)
   100  	left, right := uint32(b>>32), uint32(b)
   101  
   102  	left = (left << 1) | (left >> 31)
   103  	right = (right << 1) | (right >> 31)
   104  
   105  	for i := 0; i < 8; i++ {
   106  		left, right = feistel(left, right, c.cipher1.subkeys[2*i], c.cipher1.subkeys[2*i+1])
   107  	}
   108  	for i := 0; i < 8; i++ {
   109  		right, left = feistel(right, left, c.cipher2.subkeys[15-2*i], c.cipher2.subkeys[15-(2*i+1)])
   110  	}
   111  	for i := 0; i < 8; i++ {
   112  		left, right = feistel(left, right, c.cipher3.subkeys[2*i], c.cipher3.subkeys[2*i+1])
   113  	}
   114  
   115  	left = (left << 31) | (left >> 1)
   116  	right = (right << 31) | (right >> 1)
   117  
   118  	preOutput := (uint64(right) << 32) | uint64(left)
   119  	binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
   120  }
   121  
   122  func (c *tripleDESCipher) Decrypt(dst, src []byte) {
   123  	if len(src) < BlockSize {
   124  		panic("crypto/des: input not full block")
   125  	}
   126  	if len(dst) < BlockSize {
   127  		panic("crypto/des: output not full block")
   128  	}
   129  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
   130  		panic("crypto/des: invalid buffer overlap")
   131  	}
   132  
   133  	b := binary.BigEndian.Uint64(src)
   134  	b = permuteInitialBlock(b)
   135  	left, right := uint32(b>>32), uint32(b)
   136  
   137  	left = (left << 1) | (left >> 31)
   138  	right = (right << 1) | (right >> 31)
   139  
   140  	for i := 0; i < 8; i++ {
   141  		left, right = feistel(left, right, c.cipher3.subkeys[15-2*i], c.cipher3.subkeys[15-(2*i+1)])
   142  	}
   143  	for i := 0; i < 8; i++ {
   144  		right, left = feistel(right, left, c.cipher2.subkeys[2*i], c.cipher2.subkeys[2*i+1])
   145  	}
   146  	for i := 0; i < 8; i++ {
   147  		left, right = feistel(left, right, c.cipher1.subkeys[15-2*i], c.cipher1.subkeys[15-(2*i+1)])
   148  	}
   149  
   150  	left = (left << 31) | (left >> 1)
   151  	right = (right << 31) | (right >> 1)
   152  
   153  	preOutput := (uint64(right) << 32) | uint64(left)
   154  	binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
   155  }
   156  

View as plain text