diff --git a/cbcmac/cbcmac.go b/cbcmac/cbcmac.go index 6b365b0..8978161 100644 --- a/cbcmac/cbcmac.go +++ b/cbcmac/cbcmac.go @@ -33,9 +33,8 @@ type cbcmac struct { size int } -// NewCBCMAC returns a CBC-MAC instance that implements the MAC with the given block cipher. -// The padding scheme is ISO/IEC 9797-1 method 2. -// GB/T 15821.1-2020 MAC scheme 1 +// NewCBCMAC returns a CBC-MAC (GB/T 15821.1-2020 MAC scheme 1) instance that +// implements the MAC with the given block cipher. The padding scheme is ISO/IEC 9797-1 method 2. func NewCBCMAC(b cipher.Block, size int) BockCipherMAC { return NewCBCMACWithPadding(b, size, padding.NewISO9797M2Padding) } @@ -45,19 +44,11 @@ func NewCBCMAC(b cipher.Block, size int) BockCipherMAC { // with the specified block cipher, MAC size, and padding function. The MAC size must be greater // than 0 and less than or equal to the block size of the cipher. If the size is invalid, the // function will panic. The padding function is used to pad the input to the block size of the cipher. -// -// Parameters: -// - b: The block cipher to use for CBC-MAC. -// - size: The size of the MAC in bytes. Must be greater than 0 and less than or equal to the block size of the cipher. -// - paddingFunc: The padding function to use for padding the input to the block size of the cipher. -// -// Returns: -// - A BockCipherMAC instance that can be used to compute the CBC-MAC. -func NewCBCMACWithPadding(b cipher.Block, size int, paddingFunc padding.PaddingFunc) BockCipherMAC { +func NewCBCMACWithPadding(b cipher.Block, size int, newPaddingFunc padding.NewPaddingFunc) BockCipherMAC { if size <= 0 || size > b.BlockSize() { panic("cbcmac: invalid size") } - return &cbcmac{b: b, pad: paddingFunc(uint(b.BlockSize())), size: size} + return &cbcmac{b: b, pad: newPaddingFunc(uint(b.BlockSize())), size: size} } func (c *cbcmac) Size() int { @@ -85,23 +76,14 @@ type emac struct { size int } -// NewEMAC returns an EMAC instance that implements MAC with the given block cipher. -// The padding scheme is ISO/IEC 9797-1 method 2. -// GB/T 15821.1-2020 MAC scheme 2 +// NewEMAC returns an EMAC (GB/T 15821.1-2020 MAC scheme 2) instance that +// implements MAC with the given block cipher. The padding scheme is ISO/IEC 9797-1 method 2. func NewEMAC(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int) BockCipherMAC { return NewEMACWithPadding(creator, key1, key2, size, padding.NewISO9797M2Padding) } // NewEMACWithPadding creates a new instance of EMAC (Encrypted Message Authentication Code) with padding. -// It takes the following parameters: -// - creator: a function that takes a key and returns a cipher.Block and an error. -// - key1: the first key used to create the first cipher.Block. -// - key2: the second key used to create the second cipher.Block. -// - size: the size of the MAC. It must be greater than 0 and less than or equal to the block size of the cipher. -// - paddingFunc: a function that returns the padding to be used. -// -// The function returns a BockCipherMAC instance. It panics if there is an error creating the cipher.Blocks or if the size is invalid. -func NewEMACWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, paddingFunc padding.PaddingFunc) BockCipherMAC { +func NewEMACWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, newPaddingFunc padding.NewPaddingFunc) BockCipherMAC { var b1, b2 cipher.Block var err error if b1, err = creator(key1); err != nil { @@ -113,7 +95,7 @@ func NewEMACWithPadding(creator func(key []byte) (cipher.Block, error), key1, ke if b2, err = creator(key2); err != nil { panic(err) } - return &emac{pad: paddingFunc(uint(b1.BlockSize())), b1: b1, b2: b2, size: size} + return &emac{pad: newPaddingFunc(uint(b1.BlockSize())), b1: b1, b2: b2, size: size} } func (e *emac) Size() int { @@ -135,24 +117,15 @@ func (e *emac) MAC(src []byte) []byte { type ansiRetailMAC emac -// NewANSIRetailMAC returns an ANSI Retail MAC instance that implements MAC with the given block cipher. -// The padding scheme is ISO/IEC 9797-1 method 2. -// GB/T 15821.1-2020 MAC scheme 3 +// NewANSIRetailMAC returns an ANSI Retail MAC (GB/T 15821.1-2020 MAC scheme 3) instance that +// implements MAC with the given block cipher. The padding scheme is ISO/IEC 9797-1 method 2. func NewANSIRetailMAC(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int) BockCipherMAC { return NewANSIRetailMACWithPadding(creator, key1, key2, size, padding.NewISO9797M2Padding) } // NewANSIRetailMACWithPadding creates a new ANSI Retail MAC with padding. -// It takes the following parameters: -// - creator: a function that takes a key and returns a cipher.Block and an error. -// - key1: the first key used for the MAC. -// - key2: the second key used for the MAC. -// - size: the size of the MAC. -// - paddingFunc: a function used to pad the input data. -// -// It returns a BockCipherMAC which is an instance of ansiRetailMAC. -func NewANSIRetailMACWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, paddingFunc padding.PaddingFunc) BockCipherMAC { - return (*ansiRetailMAC)(NewEMACWithPadding(creator, key1, key2, size, paddingFunc).(*emac)) +func NewANSIRetailMACWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, newPaddingFunc padding.NewPaddingFunc) BockCipherMAC { + return (*ansiRetailMAC)(NewEMACWithPadding(creator, key1, key2, size, newPaddingFunc).(*emac)) } func (e *ansiRetailMAC) Size() int { @@ -179,14 +152,13 @@ type macDES struct { size int } -// NewMACDES returns a MAC-DES instance that implements MAC with the given block cipher. -// The padding scheme is ISO/IEC 9797-1 method 2. -// GB/T 15821.1-2020 MAC scheme 4 +// NewMACDES returns a MAC-DES (GB/T 15821.1-2020 MAC scheme 4) instance that +// implements MAC with the given block cipher. The padding scheme is ISO/IEC 9797-1 method 2. func NewMACDES(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int) BockCipherMAC { return NewMACDESWithPadding(creator, key1, key2, size, padding.NewISO9797M2Padding) } -func NewMACDESWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, paddingFunc padding.PaddingFunc) BockCipherMAC { +func NewMACDESWithPadding(creator func(key []byte) (cipher.Block, error), key1, key2 []byte, size int, newPaddingFunc padding.NewPaddingFunc) BockCipherMAC { var b1, b2, b3 cipher.Block var err error if b1, err = creator(key1); err != nil { @@ -206,7 +178,7 @@ func NewMACDESWithPadding(creator func(key []byte) (cipher.Block, error), key1, if b3, err = creator(key3); err != nil { panic(err) } - return &macDES{pad: paddingFunc(uint(b1.BlockSize())), b1: b1, b2: b2, b3: b3, size: size} + return &macDES{pad: newPaddingFunc(uint(b1.BlockSize())), b1: b1, b2: b2, b3: b3, size: size} } func (m *macDES) Size() int { @@ -241,8 +213,7 @@ type cmac struct { len uint64 } -// NewCMAC returns a CMAC instance that implements MAC with the given block cipher. -// GB/T 15821.1-2020 MAC scheme 5 +// NewCMAC returns a CMAC (GB/T 15821.1-2020 MAC scheme 5) instance that implements MAC with the given block cipher. // // Reference: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38B.pdf func NewCMAC(b cipher.Block, size int) *cmac { @@ -381,22 +352,14 @@ type lmac struct { size int } -// NewLMAC returns an LMAC instance that implements MAC with the given block cipher. -// GB/T 15821.1-2020 MAC scheme 6 +// NewLMAC returns an LMAC (GB/T 15821.1-2020 MAC scheme 6) instance that +// implements MAC with the given block cipher. The padding scheme is ISO/IEC 9797-1 method 2. func NewLMAC(creator func(key []byte) (cipher.Block, error), key []byte, size int) BockCipherMAC { return NewLMACWithPadding(creator, key, size, padding.NewISO9797M2Padding) } // NewLMACWithPadding creates a new LMAC (Length-based Message Authentication Code) with padding. -// It takes the following parameters: -// - creator: a function that takes a key and returns a cipher.Block and an error. -// - key: the key used for the MAC. -// - size: the size of the MAC output. It must be greater than 0 and less than or equal to the block size of the cipher. -// - paddingFunc: a function that returns a padding function for the given block size. -// -// The function initializes two cipher blocks using derived keys and returns an instance of BockCipherMAC. -// It panics if the key creation fails or if the size is invalid. -func NewLMACWithPadding(creator func(key []byte) (cipher.Block, error), key []byte, size int, paddingFunc padding.PaddingFunc) BockCipherMAC { +func NewLMACWithPadding(creator func(key []byte) (cipher.Block, error), key []byte, size int, newPaddingFunc padding.NewPaddingFunc) BockCipherMAC { var b, b1, b2 cipher.Block var err error if b, err = creator(key); err != nil { @@ -419,7 +382,7 @@ func NewLMACWithPadding(creator func(key []byte) (cipher.Block, error), key []by panic(err) } - return &lmac{b1: b1, b2: b2, pad: paddingFunc(uint(blockSize)), size: size} + return &lmac{b1: b1, b2: b2, pad: newPaddingFunc(uint(blockSize)), size: size} } func (l *lmac) Size() int { @@ -445,8 +408,8 @@ type trCBCMAC struct { size int } -// NewTRCBCMAC returns a TR-CBC-MAC instance that implements MAC with the given block cipher. -// GB/T 15821.1-2020 MAC scheme 7 +// NewTRCBCMAC returns a TR-CBC-MAC (GB/T 15821.1-2020 MAC scheme 7) instance that +// implements MAC with the given block cipher. // // Reference: TrCBC: Another look at CBC-MAC. func NewTRCBCMAC(b cipher.Block, size int) BockCipherMAC { @@ -485,8 +448,7 @@ type cbcrMAC struct { size int } -// NewCBCRMAC returns a CBCRMAC instance that implements MAC with the given block cipher. -// GB/T 15821.1-2020 MAC scheme 8 +// NewCBCRMAC returns a CBCRMAC (GB/T 15821.1-2020 MAC scheme 8) instance that implements MAC with the given block cipher. // // Reference: CBCR: CBC MAC with rotating transformations. func NewCBCRMAC(b cipher.Block, size int) BockCipherMAC { diff --git a/cbcmac/cbcmac_test.go b/cbcmac/cbcmac_test.go index a859498..aa8bffd 100644 --- a/cbcmac/cbcmac_test.go +++ b/cbcmac/cbcmac_test.go @@ -52,10 +52,10 @@ func TestCBCMAC(t *testing.T) { func TestCBCMACWithPadding(t *testing.T) { // Test vectors from GB/T 15821.1-2020 Appendix B. cases := []struct { - key []byte - src []byte - tag []byte - paddingFunc padding.PaddingFunc + key []byte + src []byte + tag []byte + newPaddingFunc padding.NewPaddingFunc }{ { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -94,7 +94,7 @@ func TestCBCMACWithPadding(t *testing.T) { if err != nil { t.Errorf("#%d: failed to create cipher: %v", i, err) } - mac := NewCBCMACWithPadding(block, len(c.tag), c.paddingFunc) + mac := NewCBCMACWithPadding(block, len(c.tag), c.newPaddingFunc) tag := mac.MAC(c.src) if !bytes.Equal(tag, c.tag) { t.Errorf("#%d: expect tag %x, got %x", i, c.tag, tag) @@ -105,11 +105,11 @@ func TestCBCMACWithPadding(t *testing.T) { func TestEMACWithPadding(t *testing.T) { // Test vectors from GB/T 15821.1-2020 Appendix B. cases := []struct { - key1 []byte - key2 []byte - src []byte - tag []byte - paddingFunc padding.PaddingFunc + key1 []byte + key2 []byte + src []byte + tag []byte + newPaddingFunc padding.NewPaddingFunc }{ { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -149,7 +149,7 @@ func TestEMACWithPadding(t *testing.T) { } for i, c := range cases { - mac := NewEMACWithPadding(sm4.NewCipher, c.key1, c.key2, len(c.tag), c.paddingFunc) + mac := NewEMACWithPadding(sm4.NewCipher, c.key1, c.key2, len(c.tag), c.newPaddingFunc) tag := mac.MAC(c.src) if !bytes.Equal(tag, c.tag) { t.Errorf("#%d: expect tag %x, got %x", i, c.tag, tag) @@ -234,11 +234,11 @@ func TestANSIRetailMAC(t *testing.T) { func TestANSIRetailMACWithPadding(t *testing.T) { // Test vectors from GB/T 15821.1-2020 Appendix B. cases := []struct { - key1 []byte - key2 []byte - src []byte - tag []byte - paddingFunc padding.PaddingFunc + key1 []byte + key2 []byte + src []byte + tag []byte + newPaddingFunc padding.NewPaddingFunc }{ { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -278,7 +278,7 @@ func TestANSIRetailMACWithPadding(t *testing.T) { } for i, c := range cases { - mac := NewANSIRetailMACWithPadding(sm4.NewCipher, c.key1, c.key2, len(c.tag), c.paddingFunc) + mac := NewANSIRetailMACWithPadding(sm4.NewCipher, c.key1, c.key2, len(c.tag), c.newPaddingFunc) tag := mac.MAC(c.src) if !bytes.Equal(tag, c.tag) { t.Errorf("#%d: expect tag %x, got %x", i, c.tag, tag) @@ -326,11 +326,11 @@ func TestMACDES(t *testing.T) { func TestMACDESWithPadding(t *testing.T) { // Test vectors from GB/T 15821.1-2020 Appendix B. cases := []struct { - key1 []byte - key2 []byte - src []byte - tag []byte - paddingFunc padding.PaddingFunc + key1 []byte + key2 []byte + src []byte + tag []byte + newPaddingFunc padding.NewPaddingFunc }{ { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -370,7 +370,7 @@ func TestMACDESWithPadding(t *testing.T) { } for i, c := range cases { - mac := NewMACDESWithPadding(sm4.NewCipher, c.key1, c.key2, 16, c.paddingFunc) + mac := NewMACDESWithPadding(sm4.NewCipher, c.key1, c.key2, 16, c.newPaddingFunc) tag := mac.MAC(c.src) if !bytes.Equal(tag, c.tag) { t.Errorf("#%d: expect tag %x, got %x", i, c.tag, tag) @@ -451,10 +451,10 @@ func TestLMAC(t *testing.T) { func TestLMACWithPadding(t *testing.T) { // Test vectors from GB/T 15821.1-2020 Appendix B. cases := []struct { - key []byte - src []byte - tag []byte - paddingFunc padding.PaddingFunc + key []byte + src []byte + tag []byte + newPaddingFunc padding.NewPaddingFunc }{ { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -489,7 +489,7 @@ func TestLMACWithPadding(t *testing.T) { } for i, c := range cases { - mac := NewLMACWithPadding(sm4.NewCipher, c.key, 16, c.paddingFunc) + mac := NewLMACWithPadding(sm4.NewCipher, c.key, 16, c.newPaddingFunc) tag := mac.MAC(c.src) if !bytes.Equal(tag, c.tag) { t.Errorf("#%d: expect tag %x, got %x", i, c.tag, tag) diff --git a/padding/schemes.go b/padding/schemes.go index 55d48b3..0a8bca9 100644 --- a/padding/schemes.go +++ b/padding/schemes.go @@ -8,8 +8,11 @@ type Padding interface { Unpad(src []byte) ([]byte, error) } -type PaddingFunc func(blockSize uint) Padding +type NewPaddingFunc func(blockSize uint) Padding +// NewPKCS7Padding creates a new PKCS7 padding scheme with the specified block size. +// The block size must be between 1 and 255, inclusive. If the block size is 0 or greater than 255, +// the function will panic with an "invalid block size" error. func NewPKCS7Padding(blockSize uint) Padding { if blockSize == 0 || blockSize > 255 { panic("padding: invalid block size") @@ -17,6 +20,9 @@ func NewPKCS7Padding(blockSize uint) Padding { return pkcs7Padding(blockSize) } +// NewANSIX923Padding creates a new instance of ANSI X.923 padding with the specified block size. +// The block size must be between 1 and 255, inclusive. If the block size is 0 or greater than 255, +// the function will panic with an "invalid block size" message. func NewANSIX923Padding(blockSize uint) Padding { if blockSize == 0 || blockSize > 255 { panic("padding: invalid block size") @@ -24,6 +30,8 @@ func NewANSIX923Padding(blockSize uint) Padding { return ansiX923Padding(blockSize) } +// NewISO9797M2Padding creates a new ISO/IEC 9797-1 Padding Method 2 (also known as ISO 10126) instance +// with the specified block size. The block size must be between 1 and 255 inclusive. func NewISO9797M2Padding(blockSize uint) Padding { if blockSize == 0 || blockSize > 255 { panic("padding: invalid block size") @@ -31,6 +39,8 @@ func NewISO9797M2Padding(blockSize uint) Padding { return iso9797M2Padding(blockSize) } +// NewISO9797M3Padding creates a new ISO/IEC 9797-1 Padding Method 3 (also known as ISO 10126) padding scheme +// with the specified block size. The block size must be between 1 and 255 inclusive. func NewISO9797M3Padding(blockSize uint) Padding { if blockSize == 0 || blockSize > 255 { panic("padding: invalid block size")