github.com/emmansun/gmsm@v0.29.1/cipher/ofbnlf.go (about) 1 // Output feedback with a nonlinear function operation mode (OFBNLF mode) in Chinese national standard GB/T 17964-2021. 2 // See GB/T 17964-2021 Chapter 13. 3 4 package cipher 5 6 import ( 7 _cipher "crypto/cipher" 8 "errors" 9 ) 10 11 type ofbnlf struct { 12 cipherFunc CipherCreator 13 b _cipher.Block 14 blockSize int 15 iv []byte 16 } 17 18 func newOFBNLF(cipherFunc CipherCreator, key, iv []byte) (*ofbnlf, error) { 19 c := &ofbnlf{ 20 cipherFunc: cipherFunc, 21 } 22 var err error 23 c.b, err = cipherFunc(key) 24 if err != nil { 25 return nil, err 26 } 27 c.blockSize = c.b.BlockSize() 28 if len(iv) != c.blockSize { 29 return nil, errors.New("cipher: IV length must equal block size") 30 } 31 c.iv = make([]byte, c.blockSize) 32 copy(c.iv, iv) 33 return c, nil 34 } 35 36 type ofbnlfEncrypter ofbnlf 37 38 // NewOFBNLFEncrypter returns a BlockMode which encrypts in Output feedback 39 // with a nonlinear function operation mode, using the given Block. 40 // The length of iv must be the same as the Block's block size. 41 func NewOFBNLFEncrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) { 42 c, err := newOFBNLF(cipherFunc, key, iv) 43 if err != nil { 44 return nil, err 45 } 46 return (*ofbnlfEncrypter)(c), nil 47 } 48 49 func (x *ofbnlfEncrypter) BlockSize() int { return x.blockSize } 50 51 func (x *ofbnlfEncrypter) CryptBlocks(dst, src []byte) { 52 validate(x.blockSize, dst, src) 53 54 iv := x.iv 55 k := make([]byte, x.blockSize) 56 57 for len(src) > 0 { 58 x.b.Encrypt(k, iv) 59 c, err := x.cipherFunc(k) 60 if err != nil { 61 panic(err) 62 } 63 c.Encrypt(dst, src) 64 src = src[x.blockSize:] 65 dst = dst[x.blockSize:] 66 copy(iv, k) 67 } 68 69 // Save the iv for the next CryptBlocks call. 70 copy(x.iv, iv) 71 } 72 73 func (x *ofbnlfEncrypter) SetIV(iv []byte) { 74 if len(iv) != len(x.iv) { 75 panic("cipher: incorrect length IV") 76 } 77 copy(x.iv, iv) 78 } 79 80 type ofbnlfDecrypter ofbnlf 81 82 // NewOFBNLFDecrypter returns a BlockMode which decrypts in Output feedback 83 // with a nonlinear function operation mode, using the given Block. 84 // The length of iv must be the same as the Block's block size and must match 85 // the iv used to encrypt the data. 86 func NewOFBNLFDecrypter(cipherFunc CipherCreator, key, iv []byte) (_cipher.BlockMode, error) { 87 c, err := newOFBNLF(cipherFunc, key, iv) 88 if err != nil { 89 return nil, err 90 } 91 return (*ofbnlfDecrypter)(c), nil 92 } 93 94 func (x *ofbnlfDecrypter) BlockSize() int { return x.blockSize } 95 96 func (x *ofbnlfDecrypter) CryptBlocks(dst, src []byte) { 97 validate(x.blockSize, dst, src) 98 99 if len(src) == 0 { 100 return 101 } 102 103 iv := x.iv 104 k := make([]byte, x.blockSize) 105 106 for len(src) > 0 { 107 x.b.Encrypt(k, iv) 108 c, err := x.cipherFunc(k) 109 if err != nil { 110 panic(err) 111 } 112 c.Decrypt(dst, src) 113 src = src[x.blockSize:] 114 dst = dst[x.blockSize:] 115 copy(iv, k) 116 } 117 118 // Save the iv for the next CryptBlocks call. 119 copy(x.iv, iv) 120 } 121 122 func (x *ofbnlfDecrypter) SetIV(iv []byte) { 123 if len(iv) != len(x.iv) { 124 panic("cipher: incorrect length IV") 125 } 126 copy(x.iv, iv) 127 }