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 }