gitee.com/h79/goutils@v1.22.10/common/algorithm/padding.go (about) 1 package algorithm 2 3 import ( 4 "bytes" 5 "math/rand" 6 ) 7 8 func NewPadding() Padding { 9 return Padding{} 10 } 11 12 var newPadding = NewPadding() 13 14 // 明文补码算法 15 func pkcs7Padding(text []byte, blockSize int) []byte { 16 return newPadding.PKCS7Padding(text, blockSize) 17 } 18 19 // 明文减码算法 20 func pkcs7UnPadding(src []byte) []byte { 21 return newPadding.PKCS7UnPadding(src) 22 } 23 24 type Padding struct{} 25 26 // 明文补码算法 27 // 填充至符合块大小的整数倍,填充值为填充数量数 28 func (p Padding) PKCS7Padding(text []byte, blockSize int) []byte { 29 n := len(text) 30 if n == 0 || blockSize < 1 { 31 return text 32 } 33 34 // 补位 blockSize 值 35 paddingSize := blockSize - n%blockSize 36 paddingText := bytes.Repeat([]byte{byte(paddingSize)}, paddingSize) 37 38 return append(text, paddingText...) 39 } 40 41 // 明文减码算法 42 func (p Padding) PKCS7UnPadding(src []byte) []byte { 43 n := len(src) 44 if n == 0 { 45 return src 46 } 47 48 count := int(src[n-1]) 49 50 num := n - count 51 if num < 0 { 52 return src 53 } 54 55 text := src[:num] 56 return text 57 } 58 59 // PKCS7Padding的子集,块大小固定为8字节 60 func (p Padding) PKCS5Padding(text []byte) []byte { 61 return p.PKCS7Padding(text, 8) 62 } 63 64 func (p Padding) PKCS5UnPadding(src []byte) []byte { 65 return p.PKCS7UnPadding(src) 66 } 67 68 // ================== 69 70 // 数据长度不对齐时使用0填充,否则不填充 71 func (p Padding) ZeroPadding(text []byte, blockSize int) []byte { 72 n := len(text) 73 if n == 0 || blockSize < 1 { 74 return text 75 } 76 77 // 补位 blockSize 值 78 paddingSize := blockSize - n%blockSize 79 paddingText := bytes.Repeat([]byte{byte(0)}, paddingSize) 80 81 return append(text, paddingText...) 82 } 83 84 func (p Padding) ZeroUnPadding(src []byte) []byte { 85 return bytes.TrimRight(src, string([]byte{0})) 86 } 87 88 // ================== 89 90 // ISO/IEC 9797-1 Padding Method 2 91 func (p Padding) ISO97971Padding(text []byte, blockSize int) []byte { 92 return p.ZeroPadding(append(text, 0x80), blockSize) 93 } 94 95 func (p Padding) ISO97971UnPadding(src []byte) []byte { 96 data := p.ZeroUnPadding(src) 97 98 return data[:len(data)-1] 99 } 100 101 // ================== 102 103 // X923Padding 104 // 填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节填0 105 func (p Padding) X923Padding(text []byte, blockSize int) []byte { 106 n := len(text) 107 if n == 0 || blockSize < 1 { 108 return text 109 } 110 111 // 补位 blockSize 值 112 paddingSize := blockSize - n%blockSize 113 paddingText := bytes.Repeat([]byte{byte(0)}, paddingSize-1) 114 115 text = append(text, paddingText...) 116 text = append(text, byte(paddingSize)) 117 118 return text 119 } 120 121 func (p Padding) X923UnPadding(src []byte) []byte { 122 n := len(src) 123 if n == 0 { 124 return src 125 } 126 127 count := int(src[n-1]) 128 129 num := n - count 130 if num < 0 { 131 return src 132 } 133 134 text := src[:num] 135 return text 136 } 137 138 // ================== 139 140 // ISO10126Padding 141 // 填充至符合块大小的整数倍,填充值最后一个字节为填充的数量数,其他字节填充随机字节。 142 func (p Padding) ISO10126Padding(text []byte, blockSize int) []byte { 143 n := len(text) 144 if n == 0 || blockSize < 1 { 145 return text 146 } 147 148 // 补位 blockSize 值 149 paddingSize := blockSize - n%blockSize 150 151 for i := 0; i < paddingSize-1; i++ { 152 text = append(text, p.RandomBytes(1)...) 153 } 154 155 text = append(text, byte(paddingSize)) 156 157 return text 158 } 159 160 func (p Padding) ISO10126UnPadding(src []byte) []byte { 161 n := len(src) 162 if n == 0 { 163 return src 164 } 165 166 count := int(src[n-1]) 167 168 num := n - count 169 if num < 0 { 170 return src 171 } 172 173 text := src[:num] 174 return text 175 } 176 177 // ================== 178 179 // ISO7816_4Padding 180 // 填充至符合块大小的整数倍,填充值第一个字节为0x80,其他字节填0x00。 181 func (p Padding) ISO7816_4Padding(text []byte, blockSize int) []byte { 182 n := len(text) 183 if n == 0 || blockSize < 1 { 184 return text 185 } 186 187 // 补位 blockSize 值 188 paddingSize := blockSize - n%blockSize 189 190 text = append(text, 0x80) 191 192 paddingText := bytes.Repeat([]byte{0x00}, paddingSize-1) 193 text = append(text, paddingText...) 194 195 return text 196 } 197 198 func (p Padding) ISO7816_4UnPadding(src []byte) []byte { 199 n := len(src) 200 if n == 0 { 201 return src 202 } 203 204 count := bytes.LastIndexByte(src, 0x80) 205 if count == -1 { 206 return src 207 } 208 209 return src[:count] 210 } 211 212 // ================== 213 214 // TBCPadding(Trailling-Bit-Compliment) 215 // 填充至符合块大小的整数倍,原文最后一位为1时填充0x00,最后一位为0时填充0xFF。 216 func (p Padding) TBCPadding(text []byte, blockSize int) []byte { 217 n := len(text) 218 if n == 0 || blockSize < 1 { 219 return text 220 } 221 222 // 补位 blockSize 值 223 paddingSize := blockSize - n%blockSize 224 225 lastBit := text[n-1] & 0x1 226 227 var paddingByte byte 228 if lastBit != 0 { 229 paddingByte = 0x00 230 } else { 231 paddingByte = 0xFF 232 } 233 234 paddingText := bytes.Repeat([]byte{paddingByte}, paddingSize) 235 text = append(text, paddingText...) 236 237 return text 238 } 239 240 func (p Padding) TBCUnPadding(src []byte) []byte { 241 n := len(src) 242 if n == 0 { 243 return src 244 } 245 246 lastByte := src[n-1] 247 248 switch { 249 case lastByte == 0x00: 250 for i := n - 2; i >= 0; i-- { 251 if src[i] != 0x00 { 252 return src[:i+1] 253 } 254 } 255 case lastByte == 0xFF: 256 for i := n - 2; i >= 0; i-- { 257 if src[i] != 0xFF { 258 return src[:i+1] 259 } 260 } 261 } 262 263 return src 264 } 265 266 // ================== 267 268 // 填充格式如下: 269 // Padding = 00 + BT + PS + 00 + D 270 // 00为固定字节 271 // BT为处理模式 272 // PS为填充字节,填充数量为k - 3 - D,k表示密钥长度, D表示原文长度。 273 // PS的最小长度为8个字节。填充的值根据BT值来定: 274 // BT = 00时,填充全00 275 // BT = 01时,填充全FF 276 // BT = 02时,随机填充,但不能为00。 277 func (p Padding) PKCS1Padding(text []byte, blockSize int, bt string) []byte { 278 n := len(text) 279 if n == 0 || blockSize < 1 { 280 return text 281 } 282 283 paddingSize := blockSize - 3 - n 284 285 if paddingSize < 1 { 286 return text 287 } 288 289 // 00 290 text = append(text, 0x00) 291 292 switch { 293 case bt == "00": 294 // BT 295 text = append(text, 0x00) 296 297 // PS 298 for i := 1; i <= paddingSize; i++ { 299 text = append(text, 0x00) 300 } 301 case bt == "01": 302 text = append(text, 0x01) 303 304 for i := 1; i <= paddingSize; i++ { 305 text = append(text, 0xFF) 306 } 307 case bt == "02": 308 text = append(text, 0x02) 309 310 for i := 1; i <= paddingSize; i++ { 311 text = append(text, p.RandomBytes(1)...) 312 } 313 } 314 315 // 00 316 text = append(text, 0x00) 317 318 // D 319 text = append(text, byte(n)) 320 321 return text 322 } 323 324 func (p Padding) PKCS1UnPadding(src []byte) []byte { 325 n := len(src) 326 if n == 0 { 327 return src 328 } 329 330 count := int(src[n-1]) 331 return src[:count] 332 } 333 334 // ================== 335 336 // 随机字节 337 func (p Padding) RandomBytes(length uint) []byte { 338 charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789" 339 340 b := make([]byte, length) 341 for i := range b { 342 b[i] = charset[rand.Int63()%int64(len(charset))] 343 } 344 345 return b 346 }