github.com/searKing/golang/go@v1.2.117/crypto/padding.go (about) 1 // Copyright 2021 The searKing Author. 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 crypto 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "math/rand" 11 12 rand_ "github.com/searKing/golang/go/crypto/rand" 13 ) 14 15 // See https://en.wikipedia.org/wiki/Data_source_name 16 var ZeroPadding = ISO9791Method1Padding 17 var ZeroUnPadding = ISO9791Method1UnPadding 18 var BitPadding = ISO9791Method2Padding 19 var BitUnPadding = ISO9791Method2UnPadding 20 21 // ISO/IEC 7816-4:2005[9] is identical to the bit padding scheme, applied to a plain text of N bytes. 22 // This means in practice that the first byte is a mandatory byte valued '80' (Hexadecimal) followed, if needed, 23 // by 0 to N − 1 bytes set to '00', until the end of the block is reached. ISO/IEC 7816-4 itself 24 // is a communication standard for smart cards containing a file system, 25 // and in itself does not contain any cryptographic specifications. 26 var ISO78164Padding = ISO9791Method2Padding 27 var ISO78164UnPadding = ISO9791Method2UnPadding 28 29 // the data string D to be input to the MAC algorithm shall be right-padded with as few (possible none) '0' bits 30 // as necessary to obtain a data string whose length(in bits) is a positive integer multiple of n. 31 // NOTE 32 // 1 MAC algorithm using Padding Method 1 may be subject to trivial forgery attacks. 33 // 2 If the data string is empty, Padding Method1 specifies that it is right-padded with n '0' bits. 34 // See https://en.wikipedia.org/wiki/ISO/IEC_9797-1#Padding_method_1 35 func ISO9791Method1Padding(s []byte, block int) []byte { 36 // If the data string is empty, Padding Method1 specifies that it is right-padded with n '0' bits. 37 if block <= 0 || len(s) == 0 { 38 return s 39 } 40 padding := block - (len(s) % block) 41 if padding == 0 { 42 return s 43 } 44 tmp := make([]byte, padding) 45 return append(s, tmp...) 46 } 47 48 func ISO9791Method1UnPadding(s []byte, block int) []byte { 49 var offset int 50 for i := 0; i < block; i++ { 51 j := len(s) - 1 - i 52 if j < 0 || j >= len(s) { 53 break 54 } 55 if s[j] != 0x00 { 56 offset = j 57 break 58 } 59 } 60 return s[:offset+1] 61 } 62 63 // the data string D to be input to the MAC algorithm shall be right-padded with a single '1' bit. 64 // The resulting string shall then be right-padded with as few (possible none) '0' bits 65 // as necessary to obtain a data string whose length(in bits) is a positive integer multiple of n. 66 // See https://en.wikipedia.org/wiki/ISO/IEC_9797-1#Padding_method_2 67 func ISO9791Method2Padding(s []byte, block int) []byte { 68 padding := block - (len(s) % block) 69 if padding == 0 { 70 padding = block 71 } 72 tmp := make([]byte, padding) 73 tmp[0] = 0x80 74 return append(s, tmp...) 75 } 76 77 func ISO9791Method2UnPadding(s []byte, block int) ([]byte, error) { 78 var offset int 79 var found bool 80 for i := 0; i < block; i++ { 81 j := len(s) - 1 - i 82 if j < 0 || j >= len(s) { 83 break 84 } 85 if s[j] == 0x00 { 86 continue 87 } 88 if s[j] == 0x80 { 89 offset = j 90 found = true 91 break 92 } 93 break 94 } 95 if !found { 96 return nil, fmt.Errorf("missing %#x, unpad failed", 0x80) 97 } 98 return s[:offset], nil 99 } 100 101 // the data string D to be input to the MAC algorithm shall be right-padded with as few (possible none) '0' bits 102 // as necessary to obtain a data string whose length(in bits) is a positive integer multiple of n. 103 // The resulting string shall then be left-padded with a block L. 104 // The block L consists of the binary representation of the length(in bits) Ld of the unpadded data string D, 105 // left-padded with as few (possible none) '0' bits as necessary to obtain an n-bit block. 106 // The right-most bit of the block L corresponds to the least significant bit of the binary representation of Ld. 107 // NOTE 108 // 1 Padding Method 3 is not suitable for use in situations where the length of the data string is not available prior 109 // to the start of the MAC calculation. 110 // See https://en.wikipedia.org/wiki/ISO/IEC_9797-1#Padding_method_2 111 func ISO9791Method3Padding(s []byte, block int) []byte { 112 // If the data string is empty, specifies that it is right-padded with n '0' bits. 113 if block <= 0 { 114 return s 115 } 116 unpaddedSizeInByte := len(s) 117 118 s = ISO9791Method1Padding(s, block) 119 padding := block 120 tmp := make([]byte, padding) 121 switch block { 122 case 1: 123 tmp[len(tmp)-1] = byte(unpaddedSizeInByte << 3) // append length in bits 124 case 2, 3: 125 binary.BigEndian.PutUint16(tmp[len(tmp)-2:], uint16(unpaddedSizeInByte<<3)) // append length in bits 126 case 4, 5, 6, 7: 127 binary.BigEndian.PutUint32(tmp[len(tmp)-2:], uint32(unpaddedSizeInByte<<3)) // append length in bits 128 default: 129 binary.BigEndian.PutUint64(tmp[len(tmp)-8:], uint64(unpaddedSizeInByte<<3)) // append length in bits 130 } 131 return append(tmp, s...) 132 } 133 134 func ISO9791Method3UnPadding(s []byte, block int) ([]byte, error) { 135 // If the data string is empty, specifies that it is right-padded with n '0' bits. 136 if block <= 0 { 137 return s, nil 138 } 139 var unpadded int 140 switch block { 141 case 1: 142 unpadded = int(s[block-1] >> 3) 143 case 2, 3: 144 unpadded = int(binary.BigEndian.Uint16(s[block-2:]) >> 3) 145 case 4, 5, 6, 7: 146 unpadded = int(binary.BigEndian.Uint32(s[block-4:]) >> 3) 147 default: 148 unpadded = int(binary.BigEndian.Uint64(s[block-8:]) >> 3) 149 } 150 if block+unpadded > len(s) { 151 return nil, fmt.Errorf("malformed unpadded length %d, unpad failed", unpadded) 152 } 153 return s[block : block+unpadded], nil 154 } 155 156 // In ANSI X9.23, between 1 and 8 bytes are always added as padding. 157 // The block is padded with random bytes (although many implementations use 00) and 158 // the last byte of the block is set to the number of bytes added.[6] 159 // Example: In the following example the block size is 8 bytes, 160 // and padding is required for 4 bytes (in hexadecimal format) 161 // ... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 | 162 // See https://en.wikipedia.org/wiki/Padding_(cryptography)#ANSI_X9.23 163 func ANSIX923Padding(s []byte, block int) []byte { 164 // If the data string is empty, specifies that it is right-padded with n '0' bits. 165 if block <= 0 { 166 return s 167 } 168 169 padding := block - (len(s) % block) 170 if padding == 0 { 171 padding = block 172 } 173 tmp := make([]byte, padding) 174 tmp[len(tmp)-1] = byte(padding) // append length in bytes 175 return append(s, tmp...) 176 } 177 178 func ANSIX923UnPadding(s []byte, block int) ([]byte, error) { 179 // If the data string is empty, specifies that it is right-padded with n '0' bits. 180 if block <= 0 || len(s) <= 0 { 181 return s, nil 182 } 183 offset := len(s) - int(s[len(s)-1]) 184 if offset > len(s) || offset < 0 { 185 return nil, fmt.Errorf("malformed padding length %d, unpad failed", int(s[len(s)-1])) 186 } 187 return s[:offset], nil 188 } 189 190 // ISO 10126 (withdrawn, 2007[7][8]) specifies that the padding should be done 191 // at the end of that last block with random bytes, and the padding boundary should be specified by the last byte. 192 // Example: In the following example the block size is 8 bytes and padding is required for 4 bytes 193 // ... | DD DD DD DD DD DD DD DD | DD DD DD DD 81 A6 23 04 | 194 // See https://en.wikipedia.org/wiki/Padding_(cryptography)#ISO_10126 195 func IOS10126Padding(s []byte, block int) []byte { 196 // If the data string is empty, specifies that it is right-padded with n '0' bits. 197 if block <= 0 { 198 return s 199 } 200 201 padding := block - (len(s) % block) 202 if padding == 0 { 203 padding = block 204 } 205 tmp, err := rand_.BytesCrypto(padding) 206 if err != nil { 207 tmp = make([]byte, padding) 208 for i := 0; i < padding; i++ { 209 tmp[i] = byte(rand.Uint32() & 0xFF) 210 } 211 } 212 213 tmp[len(tmp)-1] = byte(padding) // append length in bytes 214 215 return append(s, tmp...) 216 } 217 218 func IOS10126UnPadding(s []byte, block int) ([]byte, error) { 219 // If the data string is empty, specifies that it is right-padded with n '0' bits. 220 if block <= 0 || len(s) == 0 { 221 return s, nil 222 } 223 offset := len(s) - int(s[len(s)-1]) 224 if offset > len(s) || offset < 0 { 225 return nil, fmt.Errorf("malformed padding length %d, unpad failed", int(s[len(s)-1])) 226 } 227 return s[:offset], nil 228 } 229 230 // PKCS#5 padding is identical to PKCS#7 padding, 231 // except that it has only been defined for block ciphers that use a 64-bit (8-byte) block size. 232 // In practice the two can be used interchangeably. 233 func PKCS5Padding(s []byte) []byte { 234 return PKCS7Padding(s, 8) 235 } 236 237 func PKCS5UnPadding(s []byte) ([]byte, error) { 238 return PKCS7UnPadding(s, 8) 239 } 240 241 // Padding is in whole bytes. 242 // The value of each added byte is the number of bytes that are added, i.e. N bytes, each of value N are added. 243 // The number of bytes added will depend on the block boundary to which the message needs to be extended. 244 // The padding will be one of: 245 // 01 246 // 02 02 247 // 03 03 03 248 // 04 04 04 04 249 // 05 05 05 05 05 250 // 06 06 06 06 06 06 251 // etc. 252 // This padding method (as well as the previous two) is well-defined if and only if N is less than 256. 253 // Example: In the following example the block size is 8 bytes and padding is required for 4 bytes 254 // ... | DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 | 255 // If the length of the original data is an integer multiple of the block size B, 256 // then an extra block of bytes with value B is added. 257 // This is necessary so the deciphering algorithm can determine with certainty 258 // whether the last byte of the last block is a pad byte indicating the number of padding bytes added 259 // or part of the plaintext message. Consider a plaintext message 260 // that is an integer multiple of B bytes with the last byte of plaintext being 01. 261 // With no additional information, the deciphering algorithm will not be able to 262 // determine whether the last byte is a plaintext byte or a pad byte. 263 // However, by adding B bytes each of value B after the 01 plaintext byte, 264 // the deciphering algorithm can always treat the last byte as a pad byte and strip 265 // the appropriate number of pad bytes off the end of the ciphertext; 266 // said number of bytes to be stripped based on the value of the last byte. 267 // See https://tools.ietf.org/html/rfc5652#section-6.3 268 func PKCS7Padding(s []byte, block int) []byte { 269 // If the data string is empty, specifies that it is right-padded with n '0' bits. 270 if block <= 0 { 271 return s 272 } 273 274 padding := block - (len(s) % block) 275 if padding == 0 { 276 padding = block 277 } 278 tmp := make([]byte, padding) 279 for i := 0; i < padding; i++ { 280 tmp[i] = byte(padding) // append length in bytes 281 } 282 return append(s, tmp...) 283 } 284 285 func PKCS7UnPadding(s []byte, block int) ([]byte, error) { 286 // If the data string is empty, specifies that it is right-padded with n '0' bits. 287 if block <= 0 || len(s) == 0 { 288 return s, nil 289 } 290 offset := len(s) - int(s[len(s)-1]) 291 if offset > len(s) || offset < 0 { 292 return nil, fmt.Errorf("malformed padding length %d, unpad failed", int(s[len(s)-1])) 293 } 294 295 return s[:offset], nil 296 }