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  }