github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/crypto/des/cipher.go (about) 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 }