github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/xcrypto/des.go (about) 1 package xcrypto 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/des" 8 "errors" 9 "io" 10 ) 11 12 // DesCBCEncrypt 加密 13 func DesCBCEncrypt(originText, key, iv []byte) ([]byte, error) { 14 15 block, err := des.NewCipher(key) 16 if err != nil { 17 return nil, err 18 } 19 20 // 返回加密字节块的大小 21 blockSize := block.BlockSize() 22 23 // PKCS5填充需加密内容 24 originText = pKCS5Padding(originText, blockSize) 25 26 // 返回一个密码分组链接模式的、底层用Block加密的cipher.BlockMode,初始向量iv的长度必须等于Block的块尺寸(Block块尺寸等于密钥尺寸) 27 blockMode := cipher.NewCBCEncrypter(block, iv) 28 29 // 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址 30 cipherText := make([]byte, len(originText)) 31 32 // 加密或解密连续的数据块,将加密内容存储到dst中,src需加密内容的长度必须是块大小的整数倍,src和dst可指向同一内存地址 33 blockMode.CryptBlocks(cipherText, originText) 34 35 return cipherText, nil 36 } 37 38 // DesCBCDecrypt 解密 39 func DesCBCDecrypt(cipherText, key, iv []byte) ([]byte, error) { 40 41 block, err := des.NewCipher(key) 42 if err != nil { 43 return nil, err 44 } 45 46 // 返回一个密码分组链接模式的、底层用b解密的cipher.BlockMode,初始向量iv必须和加密时使用的iv相同 47 blockMode := cipher.NewCBCDecrypter(block, iv) 48 49 // 根据 密文[]byte长度,初始化一个新的byte数组,返回byte数组内存地址 50 originText := make([]byte, len(cipherText)) 51 52 // 加密或解密连续的数据块,将解密内容存储到dst中,src需加密内容的长度必须是块大小的整数倍,src和dst可指向同一内存地址 53 blockMode.CryptBlocks(originText, cipherText) 54 55 // PKCS5反填充解密内容 56 originText = pKCS5UnPadding(originText) 57 return originText, nil 58 } 59 60 // DesCFBEncrypt 加密 61 func DesCFBEncrypt(originText, key, iv []byte) ([]byte, error) { 62 63 block, err := des.NewCipher(key) 64 if err != nil { 65 return nil, err 66 } 67 68 // 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址 69 cipherText := make([]byte, aes.BlockSize+len(originText)) 70 71 // 返回一个密码反馈模式的、底层用block加密的cipher.Stream,初始向量iv的长度必须等于block的块尺寸 72 stream := cipher.NewCFBEncrypter(block, iv) 73 74 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 75 // cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分 76 stream.XORKeyStream(cipherText[aes.BlockSize:], originText) 77 78 return cipherText, nil 79 } 80 81 // DesCFBDecrypt 解密 82 func DesCFBDecrypt(cipherText, key, iv []byte) ([]byte, error) { 83 84 block, err := des.NewCipher(key) 85 if err != nil { 86 return nil, err 87 } 88 89 if len(cipherText) < aes.BlockSize { 90 return nil, errors.New("cipherText too short") 91 } 92 93 // 只使用cipherText除去iv部分 94 cipherText = cipherText[aes.BlockSize:] 95 96 // 返回一个密码反馈模式的、底层用block解密的cipher.Stream,初始向量iv必须和加密时使用的iv相同 97 stream := cipher.NewCFBDecrypter(block, iv) 98 99 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 100 stream.XORKeyStream(cipherText, cipherText) 101 102 return cipherText, nil 103 } 104 105 // DesCTREncrypt 加密 106 func DesCTREncrypt(originText, key, iv []byte) ([]byte, error) { 107 108 block, err := des.NewCipher(key) 109 if err != nil { 110 return nil, err 111 } 112 113 // 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址 114 cipherText := make([]byte, aes.BlockSize+len(originText)) 115 116 // 返回一个计数器模式的、底层采用block生成key流的cipher.Stream,初始向量iv的长度必须等于block的块尺寸 117 stream := cipher.NewCTR(block, iv) 118 119 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 120 // cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分 121 stream.XORKeyStream(cipherText[aes.BlockSize:], originText) 122 123 return cipherText, nil 124 } 125 126 // DesCTRDecrypt 解密 127 func DesCTRDecrypt(cipherText, key, iv []byte) ([]byte, error) { 128 129 block, err := des.NewCipher(key) 130 if err != nil { 131 return nil, err 132 } 133 134 // 只使用cipherText除去iv部分 135 cipherText = cipherText[aes.BlockSize:] 136 137 // 返回一个计数器模式的、底层采用block生成key流的cipher.Stream,初始向量iv的长度必须等于block的块尺寸 138 stream := cipher.NewCTR(block, iv) 139 140 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 141 stream.XORKeyStream(cipherText, cipherText) 142 143 return cipherText, nil 144 } 145 146 // DesOFBEncrypt 加密 147 func DesOFBEncrypt(originText, key, iv []byte) ([]byte, error) { 148 149 block, err := des.NewCipher(key) 150 if err != nil { 151 return nil, err 152 } 153 154 // 根据 需加密内容[]byte长度,初始化一个新的byte数组,返回byte数组内存地址 155 cipherText := make([]byte, aes.BlockSize+len(originText)) 156 157 // 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸 158 stream := cipher.NewOFB(block, iv) 159 160 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 161 // cipherText[:aes.BlockSize]为iv值,所以只写入cipherText后面部分 162 stream.XORKeyStream(cipherText[aes.BlockSize:], originText) 163 164 return cipherText, nil 165 } 166 167 // DesOFBDecrypt 解密 168 func DesOFBDecrypt(cipherText, key, iv []byte) ([]byte, error) { 169 170 block, err := des.NewCipher(key) 171 if err != nil { 172 return nil, err 173 } 174 175 // 只使用cipherText除去iv部分 176 cipherText = cipherText[aes.BlockSize:] 177 178 // 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸 179 stream := cipher.NewOFB(block, iv) 180 181 // 从加密器的key流和src中依次取出字节二者xor后写入dst,src和dst可指向同一内存地址 182 stream.XORKeyStream(cipherText, cipherText) 183 184 return cipherText, nil 185 } 186 187 // DesOFBEncryptStreamReader 加密 188 func DesOFBEncryptStreamReader(originText, key, iv []byte) ([]byte, error) { 189 190 block, err := des.NewCipher(key) 191 if err != nil { 192 return nil, err 193 } 194 195 // 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸 196 stream := cipher.NewOFB(block, iv) 197 198 // 初始化cipher.StreamReader。将一个cipher.Stream与一个io.Reader关联起来,Read方法会调用XORKeyStream方法来处理获取的所有切片 199 reader := &cipher.StreamReader{ 200 S: stream, 201 R: bytes.NewReader(originText), 202 } 203 204 return io.ReadAll(reader) 205 } 206 207 // DesOFBDecryptStreamWriter 解密 208 func DesOFBDecryptStreamWriter(cipherText, key, iv []byte) ([]byte, error) { 209 210 block, err := des.NewCipher(key) 211 if err != nil { 212 return nil, err 213 } 214 215 // 返回一个输出反馈模式的、底层采用b生成key流的cipher.Stream,初始向量iv的长度必须等于b的块尺寸 216 stream := cipher.NewOFB(block, iv) 217 218 // 声明buffer 219 var originText bytes.Buffer 220 221 // 初始化cipher.StreamWriter。将一个cipher.Stream与一个io.Writer接口关联起来,Write方法会调用XORKeyStream方法来处理提供的所有切片 222 // 如果Write方法返回的n小于提供的切片的长度,则表示StreamWriter不同步,必须丢弃。StreamWriter没有内建的缓存,不需要调用Close方法去清空缓存 223 writer := &cipher.StreamWriter{ 224 S: stream, 225 W: &originText, 226 } 227 228 // 把reader内容拷贝到writer, writer会调用write方法写入内容 229 if _, err = io.Copy(writer, bytes.NewReader(cipherText)); err != nil { 230 return nil, err 231 } 232 233 return originText.Bytes(), nil 234 }