github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/encrypt/crypto/option.go (about)

     1  package crypto
     2  
     3  import (
     4  	"encoding/base32"
     5  	"encoding/base64"
     6  )
     7  
     8  type options struct {
     9  	// encode will be called to transform the encrypted data
    10  	encoder func([]byte) ([]byte, error)
    11  
    12  	// decode will be called before data being decrypted
    13  	decoder func([]byte) ([]byte, error)
    14  
    15  	// use custom nonce size for AES GCM mode, default: 12
    16  	nonceSize int
    17  
    18  	// key size of new key for AES GCM mode, must be 16, 24 or 32, default: 32
    19  	keySize int
    20  
    21  	// specify additional data for AES GCM mode, default: nil
    22  	additionalData []byte
    23  }
    24  
    25  // Option may be used to customize the encrypt and decrypt functions behavior.
    26  type Option func(opt *options)
    27  
    28  func (p *options) apply(opts ...Option) *options {
    29  	for _, opt := range opts {
    30  		opt(p)
    31  	}
    32  	return p
    33  }
    34  
    35  func (p *options) encode(data []byte) ([]byte, error) {
    36  	if p.encoder != nil {
    37  		return p.encoder(data)
    38  	}
    39  	return data, nil
    40  }
    41  
    42  func (p *options) decode(data []byte) ([]byte, error) {
    43  	if p.decoder != nil {
    44  		return p.decoder(data)
    45  	}
    46  	return data, nil
    47  }
    48  
    49  // NonceSize optionally specifies the size of nonce, it returns an Option.
    50  func NonceSize(size int) Option {
    51  	return func(opt *options) { opt.nonceSize = size }
    52  }
    53  
    54  // KeySize optionally specifies a key size to use with GCMEncryptNewKey,
    55  // it returns an Option.
    56  func KeySize(size int) Option {
    57  	return func(opt *options) { opt.keySize = size }
    58  }
    59  
    60  // AdditionalData optionally specifies the additional data to use with
    61  // GCM mode, it returns an Option.
    62  func AdditionalData(data []byte) Option {
    63  	return func(opt *options) { opt.additionalData = data }
    64  }
    65  
    66  // Encoder optionally specifies an encoder function to encode the encrypted
    67  // ciphertext, it returns an Option.
    68  //
    69  // The encoder function may transform arbitrary bytes to a new byte slice
    70  // of some form.
    71  func Encoder(f func([]byte) ([]byte, error)) Option {
    72  	return func(opt *options) { opt.encoder = f }
    73  }
    74  
    75  // Decoder optionally specifies a decoder function to decode the encrypted
    76  // ciphertext, it returns an Option.
    77  //
    78  // The decoder function should transform bytes returned by the corresponding
    79  // encoder function to its original bytes.
    80  func Decoder(f func([]byte) ([]byte, error)) Option {
    81  	return func(opt *options) { opt.decoder = f }
    82  }
    83  
    84  // Base64 specifies the encoder and decoder to use the provided base64
    85  // encoding, it returns an Option.
    86  //
    87  // If enc is nil, it uses base64.StdEncoding.
    88  func Base64(enc *base64.Encoding) Option {
    89  	if enc == nil {
    90  		enc = base64.StdEncoding
    91  	}
    92  	return func(opt *options) {
    93  		opt.encoder = func(src []byte) ([]byte, error) {
    94  			dst := make([]byte, enc.EncodedLen(len(src)))
    95  			enc.Encode(dst, src)
    96  			return dst, nil
    97  		}
    98  		opt.decoder = func(src []byte) ([]byte, error) {
    99  			dst := make([]byte, enc.DecodedLen(len(src)))
   100  			n, err := enc.Decode(dst, src)
   101  			if err != nil {
   102  				return nil, err
   103  			}
   104  			return dst[:n], nil
   105  		}
   106  	}
   107  }
   108  
   109  // Base32 specifies the encoder and decoder to use the provided base32
   110  // encoding, it returns an Option.
   111  //
   112  // If enc is nil, it uses base32.StdEncoding.
   113  func Base32(enc *base32.Encoding) Option {
   114  	if enc == nil {
   115  		enc = base32.StdEncoding
   116  	}
   117  	return func(opt *options) {
   118  		opt.encoder = func(src []byte) ([]byte, error) {
   119  			dst := make([]byte, enc.EncodedLen(len(src)))
   120  			enc.Encode(dst, src)
   121  			return dst, nil
   122  		}
   123  		opt.decoder = func(src []byte) ([]byte, error) {
   124  			dst := make([]byte, enc.DecodedLen(len(src)))
   125  			n, err := enc.Decode(dst, src)
   126  			if err != nil {
   127  				return nil, err
   128  			}
   129  			return dst[:n], nil
   130  		}
   131  	}
   132  }