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  }