github.com/cloudflare/circl@v1.5.0/abe/cpabe/tkn20/internal/tkn/matrixG2.go (about)

     1  package tkn
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  
     8  	pairing "github.com/cloudflare/circl/ecc/bls12381"
     9  )
    10  
    11  // matrixG2 represents a matrix of G2 elements. They are stored in row-major order.
    12  type matrixG2 struct {
    13  	rows    int
    14  	cols    int
    15  	entries []pairing.G2
    16  }
    17  
    18  func (m *matrixG2) marshalBinary() ([]byte, error) {
    19  	ret := make([]byte, 4+pairing.G2Size*m.rows*m.cols)
    20  	binary.LittleEndian.PutUint16(ret[0:], uint16(m.rows))
    21  	binary.LittleEndian.PutUint16(ret[2:], uint16(m.cols))
    22  	for i := 0; i < m.rows*m.cols; i++ {
    23  		pt := m.entries[i].Bytes()
    24  		if len(pt) != pairing.G2Size {
    25  			return nil, errBadMatrixSize
    26  		}
    27  		copy(ret[pairing.G2Size*i+4:], pt)
    28  	}
    29  	return ret, nil
    30  }
    31  
    32  func (m *matrixG2) unmarshalBinary(data []byte) error {
    33  	if len(data) < 4 {
    34  		return fmt.Errorf("matrixG2 deserialization failure: input too short")
    35  	}
    36  	m.rows = int(binary.LittleEndian.Uint16(data[0:]))
    37  	m.cols = int(binary.LittleEndian.Uint16(data[2:]))
    38  	data = data[4:]
    39  	if len(data) != pairing.G2Size*m.rows*m.cols {
    40  		return fmt.Errorf("matrixG2 deserialization failure: invalid entries length: expected %d, actual %d",
    41  			pairing.G2Size*m.cols*m.rows,
    42  			len(data))
    43  	}
    44  	m.entries = make([]pairing.G2, m.rows*m.cols)
    45  	var err error
    46  	for i := 0; i < m.rows*m.cols; i++ {
    47  		err = m.entries[i].SetBytes(data[pairing.G2Size*i : pairing.G2Size*(i+1)])
    48  		if err != nil {
    49  			return fmt.Errorf("matrixG2 deserialization failure: error from bytes %v: %w",
    50  				data[pairing.G2Size*i:pairing.G2Size*(i+1)],
    51  				err)
    52  		}
    53  	}
    54  	return nil
    55  }
    56  
    57  // exp computes the naive matrix exponential of a with respect to the basepoint.
    58  func (m *matrixG2) exp(a *matrixZp) {
    59  	basepoint := pairing.G2Generator()
    60  	m.resize(a.rows, a.cols)
    61  	for i := 0; i < m.rows*m.cols; i++ {
    62  		m.entries[i].ScalarMult(&a.entries[i], basepoint)
    63  	}
    64  }
    65  
    66  // clear sets m to the zero matrix
    67  func (m *matrixG2) clear() {
    68  	for i := 0; i < len(m.entries); i++ {
    69  		m.entries[i].SetIdentity()
    70  	}
    71  }
    72  
    73  // resize only changes the matrix if we have to
    74  func (m *matrixG2) resize(r int, c int) {
    75  	if m.rows != r || m.cols != c {
    76  		m.rows = r
    77  		m.cols = c
    78  		m.entries = make([]pairing.G2, m.rows*m.cols)
    79  	}
    80  }
    81  
    82  // conformal returns true iff m and a have the same dimensions.
    83  func (m *matrixG2) conformal(a *matrixG2) bool {
    84  	return a.rows == m.rows && a.cols == m.cols
    85  }
    86  
    87  // Equal returns true if m == b.
    88  func (m *matrixG2) Equal(b *matrixG2) bool {
    89  	if !m.conformal(b) {
    90  		return false
    91  	}
    92  	for i := 0; i < m.rows; i++ {
    93  		for j := 0; j < m.cols; j++ {
    94  			if !m.entries[i*m.cols+j].IsEqual(&b.entries[i*b.cols+j]) {
    95  				return false
    96  			}
    97  		}
    98  	}
    99  	return true
   100  }
   101  
   102  // set sets m to a.
   103  func (m *matrixG2) set(a *matrixG2) {
   104  	m.resize(a.rows, a.cols)
   105  	for i := 0; i < m.rows*m.cols; i++ {
   106  		m.entries[i] = a.entries[i]
   107  	}
   108  }
   109  
   110  // add sets m to a+b.
   111  func (m *matrixG2) add(a *matrixG2, b *matrixG2) {
   112  	if !a.conformal(b) {
   113  		panic(errBadMatrixSize)
   114  	}
   115  	m.resize(a.rows, a.cols)
   116  	for i := 0; i < m.rows*m.cols; i++ {
   117  		m.entries[i].Add(&a.entries[i], &b.entries[i])
   118  	}
   119  }
   120  
   121  // leftMult multiples a*b with a matrixZp, b matrixG2.
   122  func (m *matrixG2) leftMult(a *matrixZp, b *matrixG2) {
   123  	if a.cols != b.rows {
   124  		panic(errBadMatrixSize)
   125  	}
   126  	if m == b {
   127  		c := newMatrixG2(b.rows, b.cols)
   128  		c.set(b)
   129  		b = c
   130  	}
   131  	m.resize(a.rows, b.cols)
   132  	m.clear()
   133  	var tmp pairing.G2
   134  	for i := 0; i < m.rows; i++ {
   135  		for j := 0; j < m.cols; j++ {
   136  			for k := 0; k < a.cols; k++ {
   137  				tmp.ScalarMult(&a.entries[i*a.cols+k], &b.entries[k*b.cols+j])
   138  				m.entries[i*m.cols+j].Add(&m.entries[i*m.cols+j], &tmp)
   139  			}
   140  		}
   141  	}
   142  }
   143  
   144  // rightMult multiplies a*b with a matrixG1, b matrixZp.
   145  func (m *matrixG2) rightMult(a *matrixG2, b *matrixZp) {
   146  	if a.cols != b.rows {
   147  		panic(errBadMatrixSize)
   148  	}
   149  	if m == a {
   150  		c := newMatrixG2(a.rows, a.cols)
   151  		c.set(a)
   152  		a = c
   153  	}
   154  	m.resize(a.rows, b.cols)
   155  	m.clear()
   156  	var tmp pairing.G2
   157  	for i := 0; i < m.rows; i++ {
   158  		for j := 0; j < m.cols; j++ {
   159  			for k := 0; k < a.cols; k++ {
   160  				tmp.ScalarMult(&b.entries[k*b.cols+j], &a.entries[i*a.cols+k])
   161  				m.entries[i*m.cols+j].Add(&m.entries[i*m.cols+j], &tmp)
   162  			}
   163  		}
   164  	}
   165  }
   166  
   167  func newMatrixG2(r int, c int) *matrixG2 {
   168  	ret := new(matrixG2)
   169  	ret.resize(r, c)
   170  	ret.clear()
   171  	return ret
   172  }
   173  
   174  func randomMatrixG2(rand io.Reader, r int, c int) (*matrixG2, error) {
   175  	a, err := randomMatrixZp(rand, r, c)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  	ret := newMatrixG2(r, c)
   180  	ret.exp(a)
   181  	return ret, nil
   182  }