mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 12:46:18 +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)
|
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