// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package des

import (
	
	
	
	
)

// The DES block size in bytes.
const BlockSize = 8

type KeySizeError int

func ( KeySizeError) () string {
	return "crypto/des: invalid key size " + strconv.Itoa(int())
}

// desCipher is an instance of DES encryption.
type desCipher struct {
	subkeys [16]uint64
}

// NewCipher creates and returns a new [cipher.Block].
func ( []byte) (cipher.Block, error) {
	if len() != 8 {
		return nil, KeySizeError(len())
	}

	 := new(desCipher)
	.generateSubkeys()
	return , nil
}

func ( *desCipher) () int { return BlockSize }

func ( *desCipher) (,  []byte) {
	if len() < BlockSize {
		panic("crypto/des: input not full block")
	}
	if len() < BlockSize {
		panic("crypto/des: output not full block")
	}
	if alias.InexactOverlap([:BlockSize], [:BlockSize]) {
		panic("crypto/des: invalid buffer overlap")
	}
	cryptBlock(.subkeys[:], , , false)
}

func ( *desCipher) (,  []byte) {
	if len() < BlockSize {
		panic("crypto/des: input not full block")
	}
	if len() < BlockSize {
		panic("crypto/des: output not full block")
	}
	if alias.InexactOverlap([:BlockSize], [:BlockSize]) {
		panic("crypto/des: invalid buffer overlap")
	}
	cryptBlock(.subkeys[:], , , true)
}

// A tripleDESCipher is an instance of TripleDES encryption.
type tripleDESCipher struct {
	cipher1, cipher2, cipher3 desCipher
}

// NewTripleDESCipher creates and returns a new [cipher.Block].
func ( []byte) (cipher.Block, error) {
	if len() != 24 {
		return nil, KeySizeError(len())
	}

	 := new(tripleDESCipher)
	.cipher1.generateSubkeys([:8])
	.cipher2.generateSubkeys([8:16])
	.cipher3.generateSubkeys([16:])
	return , nil
}

func ( *tripleDESCipher) () int { return BlockSize }

func ( *tripleDESCipher) (,  []byte) {
	if len() < BlockSize {
		panic("crypto/des: input not full block")
	}
	if len() < BlockSize {
		panic("crypto/des: output not full block")
	}
	if alias.InexactOverlap([:BlockSize], [:BlockSize]) {
		panic("crypto/des: invalid buffer overlap")
	}

	 := binary.BigEndian.Uint64()
	 = permuteInitialBlock()
	,  := uint32(>>32), uint32()

	 = ( << 1) | ( >> 31)
	 = ( << 1) | ( >> 31)

	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher1.subkeys[2*], .cipher1.subkeys[2*+1])
	}
	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher2.subkeys[15-2*], .cipher2.subkeys[15-(2*+1)])
	}
	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher3.subkeys[2*], .cipher3.subkeys[2*+1])
	}

	 = ( << 31) | ( >> 1)
	 = ( << 31) | ( >> 1)

	 := (uint64() << 32) | uint64()
	binary.BigEndian.PutUint64(, permuteFinalBlock())
}

func ( *tripleDESCipher) (,  []byte) {
	if len() < BlockSize {
		panic("crypto/des: input not full block")
	}
	if len() < BlockSize {
		panic("crypto/des: output not full block")
	}
	if alias.InexactOverlap([:BlockSize], [:BlockSize]) {
		panic("crypto/des: invalid buffer overlap")
	}

	 := binary.BigEndian.Uint64()
	 = permuteInitialBlock()
	,  := uint32(>>32), uint32()

	 = ( << 1) | ( >> 31)
	 = ( << 1) | ( >> 31)

	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher3.subkeys[15-2*], .cipher3.subkeys[15-(2*+1)])
	}
	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher2.subkeys[2*], .cipher2.subkeys[2*+1])
	}
	for  := 0;  < 8; ++ {
		,  = feistel(, , .cipher1.subkeys[15-2*], .cipher1.subkeys[15-(2*+1)])
	}

	 = ( << 31) | ( >> 1)
	 = ( << 31) | ( >> 1)

	 := (uint64() << 32) | uint64()
	binary.BigEndian.PutUint64(, permuteFinalBlock())
}