mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 04:36:19 +08:00
padding: ISO/IEC 9797 method 2
This commit is contained in:
parent
33d9dc7db7
commit
6478a408e6
49
padding/iso9797_m2.go
Normal file
49
padding/iso9797_m2.go
Normal file
@ -0,0 +1,49 @@
|
||||
package padding
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/alias"
|
||||
)
|
||||
|
||||
// Add a single bit with value 1 to the end of the data.
|
||||
// Then if necessary add bits with value 0 to the end of the data until the padded data is a multiple of n.
|
||||
//
|
||||
// https://en.wikipedia.org/wiki/ISO/IEC_9797-1
|
||||
// also GB/T 17964-2021 C.2 Padding method 2
|
||||
type iso9797M2Padding uint
|
||||
|
||||
func (pad iso9797M2Padding) BlockSize() int {
|
||||
return int(pad)
|
||||
}
|
||||
|
||||
func (pad iso9797M2Padding) Pad(src []byte) []byte {
|
||||
overhead := pad.BlockSize() - len(src)%pad.BlockSize()
|
||||
ret, out := alias.SliceForAppend(src, overhead)
|
||||
out[0] = 0x80
|
||||
for i := 1; i < overhead; i++ {
|
||||
out[i] = 0
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unpad decrypted plaintext, non-constant-time
|
||||
func (pad iso9797M2Padding) Unpad(src []byte) ([]byte, error) {
|
||||
srcLen := len(src)
|
||||
if srcLen == 0 || srcLen%pad.BlockSize() != 0 {
|
||||
return nil, errors.New("iso/iec 9797-1 method 2: src length is not multiple of block size")
|
||||
}
|
||||
padStart := -1
|
||||
|
||||
for i, b := range src[srcLen-pad.BlockSize() : srcLen] {
|
||||
if b == 0x80 {
|
||||
padStart = i
|
||||
} else if b != 0 && padStart >=0 {
|
||||
padStart = -1
|
||||
}
|
||||
}
|
||||
if padStart >= 0 {
|
||||
return src[:srcLen-pad.BlockSize()+padStart], nil
|
||||
}
|
||||
return src, nil
|
||||
}
|
82
padding/iso9797_m2_test.go
Normal file
82
padding/iso9797_m2_test.go
Normal file
@ -0,0 +1,82 @@
|
||||
package padding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_iso9797M2Padding_Pad(t *testing.T) {
|
||||
iso9797 := NewISO9797M2Padding(16)
|
||||
tests := []struct {
|
||||
name string
|
||||
src []byte
|
||||
want []byte
|
||||
}{
|
||||
{"16 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"15 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0x80}},
|
||||
{"14 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0x80, 0}},
|
||||
{"13 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0x80, 0, 0}},
|
||||
{"12 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x80, 0, 0, 0}},
|
||||
{"11 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0x80, 0, 0, 0, 0}},
|
||||
{"10 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x80, 0, 0, 0, 0, 0}},
|
||||
{"9 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0x80, 0, 0, 0, 0, 0, 0}},
|
||||
{"8 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 0x80, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"7 bytes", []byte{0, 1, 2, 3, 4, 5, 6}, []byte{0, 1, 2, 3, 4, 5, 6, 0x80, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"6 bytes", []byte{0, 1, 2, 3, 4, 5}, []byte{0, 1, 2, 3, 4, 5, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"5 bytes", []byte{0, 1, 2, 3, 4}, []byte{0, 1, 2, 3, 4, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"4 bytes", []byte{0, 1, 2, 3}, []byte{0, 1, 2, 3, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"3 bytes", []byte{0, 1, 2}, []byte{0, 1, 2, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"2 bytes", []byte{0, 1}, []byte{0, 1, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
{"1 bytes", []byte{0}, []byte{0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := iso9797.Pad(tt.src); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("iso9797M2Padding.Pad() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_iso9797M2Padding_Unpad(t *testing.T) {
|
||||
iso9797 := NewISO9797M2Padding(16)
|
||||
tests := []struct {
|
||||
name string
|
||||
want []byte
|
||||
src []byte
|
||||
wantErr bool
|
||||
}{
|
||||
{"16 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"15 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0x80}, false},
|
||||
{"14 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0x80, 0}, false},
|
||||
{"13 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0x80, 0, 0}, false},
|
||||
{"12 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x80, 0, 0, 0}, false},
|
||||
{"11 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0x80, 0, 0, 0, 0}, false},
|
||||
{"10 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x80, 0, 0, 0, 0, 0}, false},
|
||||
{"9 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 0x80, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"8 bytes", []byte{0, 1, 2, 3, 4, 5, 6, 7}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 0x80, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"7 bytes", []byte{0, 1, 2, 3, 4, 5, 6}, []byte{0, 1, 2, 3, 4, 5, 6, 0x80, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"6 bytes", []byte{0, 1, 2, 3, 4, 5}, []byte{0, 1, 2, 3, 4, 5, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"5 bytes", []byte{0, 1, 2, 3, 4}, []byte{0, 1, 2, 3, 4, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"4 bytes", []byte{0, 1, 2, 3}, []byte{0, 1, 2, 3, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"3 bytes", []byte{0, 1, 2}, []byte{0, 1, 2, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"2 bytes", []byte{0, 1}, []byte{0, 1, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"1 bytes", []byte{0}, []byte{0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"1 bytes with tag", []byte{0x80}, []byte{0x80, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"3 bytes with tag", []byte{0x80, 0, 0x80}, []byte{0x80, 0, 0x80, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"19 bytes with tag", []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x80, 0, 0x80}, []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x80, 0, 0x80, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false},
|
||||
{"invalid src length", nil, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := iso9797.Unpad(tt.src)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("case %v: iso9797M2Padding.Unpad() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("case %v: iso9797M2Padding.Unpad() = %v, want %v", tt.name, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -21,3 +21,10 @@ func NewANSIX923Padding(blockSize uint) Padding {
|
||||
}
|
||||
return ansiX923Padding(blockSize)
|
||||
}
|
||||
|
||||
func NewISO9797M2Padding(blockSize uint) Padding {
|
||||
if blockSize == 0 || blockSize > 255 {
|
||||
panic("padding: invalid block size")
|
||||
}
|
||||
return iso9797M2Padding(blockSize)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user