gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm4soft/padding/pkcs7_padding_io.go (about) 1 // Copyright (c) 2022 zhaochun 2 // core-gm is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 /* 10 sm4soft 是sm4的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。 11 对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明 12 */ 13 14 package padding 15 16 import ( 17 "bytes" 18 "errors" 19 "io" 20 ) 21 22 // PKCS7PaddingReader 符合PKCS#7填充的输入流 23 type PKCS7PaddingReader struct { 24 fIn io.Reader 25 padding io.Reader 26 blockSize int 27 readed int64 28 eof bool 29 eop bool 30 } 31 32 // NewPKCS7PaddingReader 创建PKCS7填充Reader 33 // in: 输入流 34 // blockSize: 分块大小 35 func NewPKCS7PaddingReader(in io.Reader, blockSize int) *PKCS7PaddingReader { 36 return &PKCS7PaddingReader{ 37 fIn: in, 38 padding: nil, 39 eof: false, 40 eop: false, 41 blockSize: blockSize, 42 } 43 } 44 45 func (p *PKCS7PaddingReader) Read(buf []byte) (int, error) { 46 /* 47 - 读取文件 48 - 文件长度充足, 直接返还 49 - 不充足 50 - 读取到 n 字节, 剩余需要 m 字节 51 - 从 padding 中读取然后追加到 buff 52 - EOF 直接返回, 整个Reader end 53 */ 54 // 都读取完了 55 if p.eof && p.eop { 56 return 0, io.EOF 57 } 58 59 var n, off = 0, 0 60 var err error 61 if !p.eof { 62 // 读取文件 63 n, err = p.fIn.Read(buf) 64 if err != nil && !errors.Is(err, io.EOF) { 65 // 错误返回 66 return 0, err 67 } 68 p.readed += int64(n) 69 if errors.Is(err, io.EOF) { 70 // 标志文件结束 71 p.eof = true 72 } 73 if n == len(buf) { 74 // 长度足够直接返回 75 return n, nil 76 } 77 // 文件长度已经不足,根据已经已经读取的长度创建Padding 78 p.newPadding() 79 // 长度不足向Padding中索要 80 off = n 81 } 82 83 if !p.eop { 84 // 读取流 85 var n2 = 0 86 n2, err = p.padding.Read(buf[off:]) 87 n += n2 88 if errors.Is(err, io.EOF) { 89 p.eop = true 90 } 91 } 92 return n, err 93 } 94 95 // 新建Padding 96 func (p *PKCS7PaddingReader) newPadding() { 97 if p.padding != nil { 98 return 99 } 100 size := p.blockSize - int(p.readed%int64(p.blockSize)) 101 padding := bytes.Repeat([]byte{byte(size)}, size) 102 p.padding = bytes.NewReader(padding) 103 } 104 105 // PKCS7PaddingWriter 符合PKCS#7去除的输入流,最后一个 分组根据会根据填充情况去除填充。 106 type PKCS7PaddingWriter struct { 107 cache *bytes.Buffer // 缓存区 108 swap []byte // 临时交换区 109 out io.Writer // 输出位置 110 blockSize int // 分块大小 111 } 112 113 // NewPKCS7PaddingWriter PKCS#7 填充Writer 可以去除填充 114 func NewPKCS7PaddingWriter(out io.Writer, blockSize int) *PKCS7PaddingWriter { 115 cache := bytes.NewBuffer(make([]byte, 0, 1024)) 116 swap := make([]byte, 1024) 117 return &PKCS7PaddingWriter{out: out, blockSize: blockSize, cache: cache, swap: swap} 118 } 119 120 // Write 保留一个填充大小的数据,其余全部写入输出中 121 func (p *PKCS7PaddingWriter) Write(buff []byte) (n int, err error) { 122 // 写入缓存 123 n, err = p.cache.Write(buff) 124 if err != nil { 125 return 0, err 126 } 127 if p.cache.Len() > p.blockSize { 128 // 把超过一个分组长度的部分读取出来,写入到实际的out中 129 size := p.cache.Len() - p.blockSize 130 _, _ = p.cache.Read(p.swap[:size]) 131 _, err = p.out.Write(p.swap[:size]) 132 if err != nil { 133 return 0, err 134 } 135 } 136 return n, err 137 138 } 139 140 // Final 去除填充写入最后一个分块 141 func (p *PKCS7PaddingWriter) Final() error { 142 // 在Write 之后 cache 只会保留一个Block长度数据 143 b := p.cache.Bytes() 144 length := len(b) 145 if length != p.blockSize { 146 return errors.New("非法的PKCS7填充") 147 } 148 if length == 0 { 149 return nil 150 } 151 unpadding := int(b[length-1]) 152 if unpadding > p.blockSize || unpadding == 0 { 153 return errors.New("非法的PKCS7填充") 154 } 155 _, err := p.out.Write(b[:(length - unpadding)]) 156 return err 157 }