mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 04:06:18 +08:00
cipher: add SM legacy operation modes
This commit is contained in:
parent
67c80c82b4
commit
ee397cdbd7
150
cipher/bc.go
Normal file
150
cipher/bc.go
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
// Block Chaining operation mode (BC mode) in Chinese national standard GB/T 17964-2021.
|
||||||
|
// See GB/T 17964-2021 Chapter 12.
|
||||||
|
package cipher
|
||||||
|
|
||||||
|
import (
|
||||||
|
_cipher "crypto/cipher"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
|
"github.com/emmansun/gmsm/internal/subtle"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bc struct {
|
||||||
|
b _cipher.Block
|
||||||
|
blockSize int
|
||||||
|
iv []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBC(b _cipher.Block, iv []byte) *bc {
|
||||||
|
c := &bc{
|
||||||
|
b: b,
|
||||||
|
blockSize: b.BlockSize(),
|
||||||
|
iv: make([]byte, b.BlockSize()),
|
||||||
|
}
|
||||||
|
copy(c.iv, iv)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
type bcEncrypter bc
|
||||||
|
|
||||||
|
// bcEncAble is an interface implemented by ciphers that have a specific
|
||||||
|
// optimized implementation of BC encryption.
|
||||||
|
// NewBCEncrypter will check for this interface and return the specific
|
||||||
|
// BlockMode if found.
|
||||||
|
type bcEncAble interface {
|
||||||
|
NewBCEncrypter(iv []byte) _cipher.BlockMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBCEncrypter returns a BlockMode which encrypts in block chaining
|
||||||
|
// mode, using the given Block. The length of iv must be the same as the
|
||||||
|
// Block's block size.
|
||||||
|
func NewBCEncrypter(b _cipher.Block, iv []byte) _cipher.BlockMode {
|
||||||
|
if len(iv) != b.BlockSize() {
|
||||||
|
panic("cipher.NewBCEncrypter: IV length must equal block size")
|
||||||
|
}
|
||||||
|
if bc, ok := b.(bcEncAble); ok {
|
||||||
|
return bc.NewBCEncrypter(iv)
|
||||||
|
}
|
||||||
|
return (*bcEncrypter)(newBC(b, iv))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *bcEncrypter) BlockSize() int { return x.blockSize }
|
||||||
|
|
||||||
|
func (x *bcEncrypter) CryptBlocks(dst, src []byte) {
|
||||||
|
if len(src)%x.blockSize != 0 {
|
||||||
|
panic("cipher: input not full blocks")
|
||||||
|
}
|
||||||
|
if len(dst) < len(src) {
|
||||||
|
panic("cipher: output smaller than input")
|
||||||
|
}
|
||||||
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
|
panic("cipher: invalid buffer overlap")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := x.iv
|
||||||
|
|
||||||
|
for len(src) > 0 {
|
||||||
|
// Write the xor to dst, then encrypt in place.
|
||||||
|
subtle.XORBytes(dst[:x.blockSize], src[:x.blockSize], iv)
|
||||||
|
x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
|
||||||
|
subtle.XORBytes(iv, iv, dst[:x.blockSize])
|
||||||
|
|
||||||
|
src = src[x.blockSize:]
|
||||||
|
dst = dst[x.blockSize:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the iv for the next CryptBlocks call.
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *bcEncrypter) SetIV(iv []byte) {
|
||||||
|
if len(iv) != len(x.iv) {
|
||||||
|
panic("cipher: incorrect length IV")
|
||||||
|
}
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
type bcDecrypter bc
|
||||||
|
|
||||||
|
// bcDecAble is an interface implemented by ciphers that have a specific
|
||||||
|
// optimized implementation of BC decryption.
|
||||||
|
// NewBCDecrypter will check for this interface and return the specific
|
||||||
|
// BlockMode if found.
|
||||||
|
type bcDecAble interface {
|
||||||
|
NewBCDecrypter(iv []byte) _cipher.BlockMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBCDecrypter returns a BlockMode which decrypts in block chaining
|
||||||
|
// mode, using the given Block. The length of iv must be the same as the
|
||||||
|
// Block's block size and must match the iv used to encrypt the data.
|
||||||
|
func NewBCDecrypter(b _cipher.Block, iv []byte) _cipher.BlockMode {
|
||||||
|
if len(iv) != b.BlockSize() {
|
||||||
|
panic("cipher.NewBCDecrypter: IV length must equal block size")
|
||||||
|
}
|
||||||
|
if bc, ok := b.(bcDecAble); ok {
|
||||||
|
return bc.NewBCDecrypter(iv)
|
||||||
|
}
|
||||||
|
return (*bcDecrypter)(newBC(b, iv))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *bcDecrypter) BlockSize() int { return x.blockSize }
|
||||||
|
|
||||||
|
func (x *bcDecrypter) CryptBlocks(dst, src []byte) {
|
||||||
|
if len(src)%x.blockSize != 0 {
|
||||||
|
panic("cipher: input not full blocks")
|
||||||
|
}
|
||||||
|
if len(dst) < len(src) {
|
||||||
|
panic("cipher: output smaller than input")
|
||||||
|
}
|
||||||
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
|
panic("cipher: invalid buffer overlap")
|
||||||
|
}
|
||||||
|
if len(src) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := x.iv
|
||||||
|
nextIV := make([]byte, x.blockSize)
|
||||||
|
|
||||||
|
for len(src) > 0 {
|
||||||
|
// Get F(i+1)
|
||||||
|
subtle.XORBytes(nextIV, iv, src[:x.blockSize])
|
||||||
|
// Get plaintext P(i)
|
||||||
|
x.b.Decrypt(dst[:x.blockSize], src[:x.blockSize])
|
||||||
|
subtle.XORBytes(dst[:x.blockSize], dst[:x.blockSize], iv)
|
||||||
|
|
||||||
|
copy(iv, nextIV)
|
||||||
|
src = src[x.blockSize:]
|
||||||
|
dst = dst[x.blockSize:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the iv for the next CryptBlocks call.
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *bcDecrypter) SetIV(iv []byte) {
|
||||||
|
if len(iv) != len(x.iv) {
|
||||||
|
panic("cipher: incorrect length IV")
|
||||||
|
}
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
74
cipher/bc_test.go
Normal file
74
cipher/bc_test.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package cipher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/cipher"
|
||||||
|
"github.com/emmansun/gmsm/sm4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var bcSM4TestVectors = []struct {
|
||||||
|
key string
|
||||||
|
iv string
|
||||||
|
plaintext string
|
||||||
|
ciphertext string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"2B7E151628AED2A6ABF7158809CF4F3C",
|
||||||
|
"000102030405060708090A0B0C0D0E0F",
|
||||||
|
"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
|
||||||
|
"AC529AF989A62FCE9CDDC5FFB84125CAFB8CDE77339FFE481D113C40BBD5B6786FFC9916F98F94FF12D78319707E240428718707605BC1EAC503153EBAA0FB1D",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBC(t *testing.T) {
|
||||||
|
for i, test := range bcSM4TestVectors {
|
||||||
|
key, _ := hex.DecodeString(test.key)
|
||||||
|
iv, _ := hex.DecodeString(test.iv)
|
||||||
|
plaintext, _ := hex.DecodeString(test.plaintext)
|
||||||
|
ciphertext, _ := hex.DecodeString(test.ciphertext)
|
||||||
|
got := make([]byte, len(plaintext))
|
||||||
|
c, err := sm4.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypter := cipher.NewBCEncrypter(c, iv)
|
||||||
|
encrypter.CryptBlocks(got, plaintext)
|
||||||
|
if !bytes.Equal(got, ciphertext) {
|
||||||
|
t.Fatalf("%v case encrypt failed, got %x\n", i+1, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypter := cipher.NewBCDecrypter(c, iv)
|
||||||
|
decrypter.CryptBlocks(got, ciphertext)
|
||||||
|
if !bytes.Equal(got, plaintext) {
|
||||||
|
t.Fatalf("%v case decrypt failed, got %x\n", i+1, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSM4BCRandom(t *testing.T) {
|
||||||
|
key, _ := hex.DecodeString(bcSM4TestVectors[0].key)
|
||||||
|
iv := []byte("0123456789ABCDEF")
|
||||||
|
c, err := sm4.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
encrypter := cipher.NewBCEncrypter(c, iv)
|
||||||
|
decrypter := cipher.NewBCDecrypter(c, iv)
|
||||||
|
for i := 1; i <= 50; i++ {
|
||||||
|
plaintext := make([]byte, i*16)
|
||||||
|
ciphertext := make([]byte, i*16)
|
||||||
|
got := make([]byte, i*16)
|
||||||
|
io.ReadFull(rand.Reader, plaintext)
|
||||||
|
encrypter.CryptBlocks(ciphertext, plaintext)
|
||||||
|
decrypter.CryptBlocks(got, ciphertext)
|
||||||
|
if !bytes.Equal(got, plaintext) {
|
||||||
|
t.Errorf("test %v blocks failed", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,40 @@ import (
|
|||||||
"github.com/emmansun/gmsm/sm4"
|
"github.com/emmansun/gmsm/sm4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func BenchmarkSM4BCEncrypt1K(b *testing.B) {
|
||||||
|
var key [16]byte
|
||||||
|
c, _ := sm4.NewCipher(key[:])
|
||||||
|
benchmarkBCEncrypt1K(b, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkBCEncrypt1K(b *testing.B, block cipher.Block) {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
b.SetBytes(int64(len(buf)))
|
||||||
|
|
||||||
|
var iv [16]byte
|
||||||
|
bc := smcipher.NewBCEncrypter(block, iv[:])
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bc.CryptBlocks(buf, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSM4BCDecrypt1K(b *testing.B) {
|
||||||
|
var key [16]byte
|
||||||
|
c, _ := sm4.NewCipher(key[:])
|
||||||
|
benchmarkBCDecrypt1K(b, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkBCDecrypt1K(b *testing.B, block cipher.Block) {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
b.SetBytes(int64(len(buf)))
|
||||||
|
|
||||||
|
var iv [16]byte
|
||||||
|
bc := smcipher.NewBCDecrypter(block, iv[:])
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bc.CryptBlocks(buf, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkSM4HCTREncrypt1K(b *testing.B) {
|
func BenchmarkSM4HCTREncrypt1K(b *testing.B) {
|
||||||
var key [16]byte
|
var key [16]byte
|
||||||
var tweak [32]byte
|
var tweak [32]byte
|
||||||
|
144
cipher/ofbnlf.go
Normal file
144
cipher/ofbnlf.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Output feedback with a nonlinear function operation mode (OFBNLF mode) in Chinese national standard GB/T 17964-2021.
|
||||||
|
// See GB/T 17964-2021 Chapter 13.
|
||||||
|
|
||||||
|
package cipher
|
||||||
|
|
||||||
|
import (
|
||||||
|
_cipher "crypto/cipher"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/internal/alias"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ofbnlf struct {
|
||||||
|
cipherFunc CipherCreator
|
||||||
|
b _cipher.Block
|
||||||
|
blockSize int
|
||||||
|
iv []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOFBNLF(cipherFunc CipherCreator, key, iv []byte) (*ofbnlf, error) {
|
||||||
|
c := &ofbnlf{
|
||||||
|
cipherFunc: cipherFunc,
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
c.b, err = cipherFunc(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.blockSize = c.b.BlockSize()
|
||||||
|
if len(iv) != c.blockSize {
|
||||||
|
return nil, errors.New("cipher: IV length must equal block size")
|
||||||
|
}
|
||||||
|
c.iv = make([]byte, c.blockSize)
|
||||||
|
copy(c.iv, iv)
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ofbnlfEncrypter ofbnlf
|
||||||
|
|
||||||
|
// NewOFBNLFEncrypter returns a BlockMode which encrypts in Output feedback
|
||||||
|
// with a nonlinear function operation mode, using the given Block.
|
||||||
|
// The length of iv must be the same as the Block's block size.
|
||||||
|
func NewOFBNLFEncrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) {
|
||||||
|
c, err := newOFBNLF(cipherFunc, key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return (*ofbnlfEncrypter)(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ofbnlfEncrypter) BlockSize() int { return x.blockSize }
|
||||||
|
|
||||||
|
func (x *ofbnlfEncrypter) CryptBlocks(dst, src []byte) {
|
||||||
|
if len(src)%x.blockSize != 0 {
|
||||||
|
panic("cipher: input not full blocks")
|
||||||
|
}
|
||||||
|
if len(dst) < len(src) {
|
||||||
|
panic("cipher: output smaller than input")
|
||||||
|
}
|
||||||
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
|
panic("cipher: invalid buffer overlap")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := x.iv
|
||||||
|
k := make([]byte, x.blockSize)
|
||||||
|
|
||||||
|
for len(src) > 0 {
|
||||||
|
x.b.Encrypt(k, iv)
|
||||||
|
c, err := x.cipherFunc(k)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
c.Encrypt(dst, src)
|
||||||
|
src = src[x.blockSize:]
|
||||||
|
dst = dst[x.blockSize:]
|
||||||
|
copy(iv, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the iv for the next CryptBlocks call.
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ofbnlfEncrypter) SetIV(iv []byte) {
|
||||||
|
if len(iv) != len(x.iv) {
|
||||||
|
panic("cipher: incorrect length IV")
|
||||||
|
}
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ofbnlfDecrypter ofbnlf
|
||||||
|
|
||||||
|
// NewOFBNLFDecrypter returns a BlockMode which decrypts in Output feedback
|
||||||
|
// with a nonlinear function operation mode, using the given Block.
|
||||||
|
// The length of iv must be the same as the Block's block size and must match
|
||||||
|
// the iv used to encrypt the data.
|
||||||
|
func NewOFBNLFDecrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) {
|
||||||
|
c, err := newOFBNLF(cipherFunc, key, iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return (*ofbnlfDecrypter)(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ofbnlfDecrypter) BlockSize() int { return x.blockSize }
|
||||||
|
|
||||||
|
func (x *ofbnlfDecrypter) CryptBlocks(dst, src []byte) {
|
||||||
|
if len(src)%x.blockSize != 0 {
|
||||||
|
panic("cipher: input not full blocks")
|
||||||
|
}
|
||||||
|
if len(dst) < len(src) {
|
||||||
|
panic("cipher: output smaller than input")
|
||||||
|
}
|
||||||
|
if alias.InexactOverlap(dst[:len(src)], src) {
|
||||||
|
panic("cipher: invalid buffer overlap")
|
||||||
|
}
|
||||||
|
if len(src) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := x.iv
|
||||||
|
k := make([]byte, x.blockSize)
|
||||||
|
|
||||||
|
for len(src) > 0 {
|
||||||
|
x.b.Encrypt(k, iv)
|
||||||
|
c, err := x.cipherFunc(k)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
c.Decrypt(dst, src)
|
||||||
|
src = src[x.blockSize:]
|
||||||
|
dst = dst[x.blockSize:]
|
||||||
|
copy(iv, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the iv for the next CryptBlocks call.
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ofbnlfDecrypter) SetIV(iv []byte) {
|
||||||
|
if len(iv) != len(x.iv) {
|
||||||
|
panic("cipher: incorrect length IV")
|
||||||
|
}
|
||||||
|
copy(x.iv, iv)
|
||||||
|
}
|
71
cipher/ofbnlf_test.go
Normal file
71
cipher/ofbnlf_test.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package cipher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/emmansun/gmsm/cipher"
|
||||||
|
"github.com/emmansun/gmsm/sm4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ofbnlfSM4TestVectors = []struct {
|
||||||
|
key string
|
||||||
|
iv string
|
||||||
|
plaintext string
|
||||||
|
ciphertext string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"2B7E151628AED2A6ABF7158809CF4F3C",
|
||||||
|
"000102030405060708090A0B0C0D0E0F",
|
||||||
|
"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
|
||||||
|
"00A5B5C9E645557C20CE7F267736F308A18037828850B9D78883CA622851F86CB7CAEFDFB6D4CABA6AE2D2FCE369CEB31001DD71FDDA9341F8D221CB720FF27B",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOFBNLF(t *testing.T) {
|
||||||
|
for i, test := range ofbnlfSM4TestVectors {
|
||||||
|
key, _ := hex.DecodeString(test.key)
|
||||||
|
iv, _ := hex.DecodeString(test.iv)
|
||||||
|
plaintext, _ := hex.DecodeString(test.plaintext)
|
||||||
|
ciphertext, _ := hex.DecodeString(test.ciphertext)
|
||||||
|
got := make([]byte, len(plaintext))
|
||||||
|
encrypter, err := cipher.NewOFBNLFEncrypter(sm4.NewCipher, key, iv)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
encrypter.CryptBlocks(got, plaintext)
|
||||||
|
if !bytes.Equal(got, ciphertext) {
|
||||||
|
t.Fatalf("%v case encrypt failed, got %x\n", i+1, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypter, err := cipher.NewOFBNLFDecrypter(sm4.NewCipher, key, iv)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
decrypter.CryptBlocks(got, ciphertext)
|
||||||
|
if !bytes.Equal(got, plaintext) {
|
||||||
|
t.Fatalf("%v case decrypt failed, got %x\n", i+1, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSM4OFBNLFRandom(t *testing.T) {
|
||||||
|
key, _ := hex.DecodeString(ofbnlfSM4TestVectors[0].key)
|
||||||
|
iv := []byte("0123456789ABCDEF")
|
||||||
|
encrypter, _ := cipher.NewOFBNLFEncrypter(sm4.NewCipher, key, iv)
|
||||||
|
decrypter, _ := cipher.NewOFBNLFDecrypter(sm4.NewCipher, key, iv)
|
||||||
|
for i := 1; i <= 50; i++ {
|
||||||
|
plaintext := make([]byte, i*16)
|
||||||
|
ciphertext := make([]byte, i*16)
|
||||||
|
got := make([]byte, i*16)
|
||||||
|
io.ReadFull(rand.Reader, plaintext)
|
||||||
|
encrypter.CryptBlocks(ciphertext, plaintext)
|
||||||
|
decrypter.CryptBlocks(got, ciphertext)
|
||||||
|
if !bytes.Equal(got, plaintext) {
|
||||||
|
t.Errorf("test %v blocks failed", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user