github.com/iDigitalFlame/xmt@v0.5.4/c2/wrapper/crypto.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package wrapper
    18  
    19  import (
    20  	"crypto/cipher"
    21  	"io"
    22  
    23  	"github.com/iDigitalFlame/xmt/data/crypto"
    24  	"github.com/iDigitalFlame/xmt/util/xerr"
    25  )
    26  
    27  // CBK is the crypto.CBK implementation of a Wrapper. This instance will create
    28  // a new CBK instance with these supplied values and size.
    29  type CBK [5]byte
    30  
    31  // XOR is the crypto.XOR implementation of a Wrapper. This instance will create
    32  // a XOR key stream with IV based on the supplied values.
    33  type XOR struct {
    34  	_  [0]func()
    35  	k  crypto.XOR
    36  	iv []byte
    37  }
    38  
    39  // Block is the cipher.Block implementation of a Wrapper. This instance will create
    40  // a Block based Wrapper with ciphers such as AES.
    41  type Block struct {
    42  	_ [0]func()
    43  	b cipher.Block
    44  	v []byte
    45  }
    46  type nopCloser struct {
    47  	io.Reader
    48  }
    49  
    50  // NewXOR is a function that is an alias for 'Stream(crypto.XOR(k), crypto.XOR(k))'
    51  //
    52  // This wil return a Stream-backed XOR Wrapper.
    53  func NewXOR(k []byte) XOR {
    54  	x := XOR{k: k, iv: make([]byte, len(k))}
    55  	for i := range k {
    56  		x.iv[i] = (k[i] + byte(i)) ^ 2
    57  	}
    58  	return x
    59  }
    60  func (nopCloser) Close() error {
    61  	return nil
    62  }
    63  
    64  // NewCBK creates a special type of Wrapper for CBK-based encryptors.
    65  //
    66  // NOTE: This function will prevent CBK from using its index based block
    67  // functions, not sure if there's a way to work around this.
    68  func NewCBK(a, b, c, d, size byte) CBK {
    69  	var e CBK
    70  	e[0], e[1], e[2], e[3], e[4] = a, b, c, d, size
    71  	return e
    72  }
    73  
    74  // Unwrap fulfils the Wrapper interface.
    75  func (c CBK) Unwrap(r io.Reader) (io.Reader, error) {
    76  	e, err := crypto.NewCBKSource(c[0], c[1], c[2], c[3], c[4])
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	return crypto.NewCBKReader(e, r), nil
    81  }
    82  
    83  // Unwrap fulfils the Wrapper interface.
    84  func (x XOR) Unwrap(r io.Reader) (io.Reader, error) {
    85  	return nopCloser{&cipher.StreamReader{R: r, S: cipher.NewCFBDecrypter(x.k, x.iv)}}, nil
    86  }
    87  
    88  // Unwrap fulfils the Wrapper interface.
    89  func (b Block) Unwrap(r io.Reader) (io.Reader, error) {
    90  	return &cipher.StreamReader{R: r, S: cipher.NewCFBDecrypter(b.b, b.v)}, nil
    91  }
    92  
    93  // NewBlock returns a Wrapper based on a Block Cipher, such as AES.
    94  func NewBlock(b cipher.Block, v []byte) (Block, error) {
    95  	if b == nil || len(v) == 0 {
    96  		return Block{}, xerr.Sub("arguments cannot be nil or empty", 0x6E)
    97  	}
    98  	if len(v) != b.BlockSize() {
    99  		return Block{}, xerr.Sub("block size must equal IV size", 0x29)
   100  	}
   101  	return Block{v: v, b: b}, nil
   102  }
   103  
   104  // Wrap fulfils the Wrapper interface.
   105  func (c CBK) Wrap(w io.WriteCloser) (io.WriteCloser, error) {
   106  	e, err := crypto.NewCBKSource(c[0], c[1], c[2], c[3], c[4])
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return crypto.NewCBKWriter(e, w), nil
   111  }
   112  
   113  // Wrap fulfils the Wrapper interface.
   114  func (x XOR) Wrap(w io.WriteCloser) (io.WriteCloser, error) {
   115  	return &cipher.StreamWriter{W: w, S: cipher.NewCFBEncrypter(x.k, x.iv)}, nil
   116  }
   117  
   118  // Wrap fulfils the Wrapper interface.
   119  func (b Block) Wrap(w io.WriteCloser) (io.WriteCloser, error) {
   120  	return &cipher.StreamWriter{W: w, S: cipher.NewCFBEncrypter(b.b, b.v)}, nil
   121  }