19
19
import supranational .blst .BLST_ERROR ;
20
20
import supranational .blst .P1 ;
21
21
import supranational .blst .P1_Affine ;
22
+ import supranational .blst .P2 ;
22
23
import supranational .blst .P2_Affine ;
24
+ import supranational .blst .PT ;
25
+ import supranational .blst .Scalar ;
23
26
24
27
public class BLS12381 {
25
28
private static final String dst = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_" ;
@@ -33,15 +36,16 @@ public static P1 identity() {
33
36
34
37
/**
35
38
* Returns aggregation of prevAgg and values.
39
+ *
36
40
* @param prevAgg previous aggregation. null if there is no previous
37
41
* aggregation.
38
- * @param values values to be aggregated.
42
+ * @param values values to be aggregated.
39
43
* @return aggregated value.
40
44
*/
41
45
public static byte [] aggregateG1Values (byte [] prevAgg , byte [] values ) {
42
46
try {
43
47
P1 res ;
44
- if (prevAgg != null ) {
48
+ if (prevAgg != null ) {
45
49
res = new P1 (prevAgg );
46
50
if (!res .in_group ()) {
47
51
throw new IllegalArgumentException ("prevAgg is not in group" );
@@ -51,8 +55,8 @@ public static byte[] aggregateG1Values(byte[] prevAgg, byte[] values) {
51
55
}
52
56
var nValues = values .length / G1_LEN ;
53
57
byte [] pk = new byte [G1_LEN ];
54
- for (int i = 0 ; i < nValues ; i ++) {
55
- System .arraycopy (values , i * G1_LEN , pk , 0 , G1_LEN );
58
+ for (int i = 0 ; i < nValues ; i ++) {
59
+ System .arraycopy (values , i * G1_LEN , pk , 0 , G1_LEN );
56
60
var p1a = new P1_Affine (pk );
57
61
if (!p1a .in_group ()) {
58
62
throw new IllegalArgumentException ("a value is not in group" );
@@ -79,4 +83,88 @@ public static boolean verifyG2Signature(byte[] pubKey, byte[] sig, byte[] msg) {
79
83
throw new IllegalArgumentException (e );
80
84
}
81
85
}
86
+
87
+ public static byte [] g1Add (byte [] data , boolean compressed ) {
88
+ P1 acc = new P1 ();
89
+ int size = compressed ? G1_LEN : 2 * G1_LEN ;
90
+ if (data .length == 0 || data .length % size != 0 ) {
91
+ throw new IllegalArgumentException ("BLS12-381: g1Add: invalid data layout: expected a multiple of " + size
92
+ + " bytes, got " + data .length );
93
+ }
94
+ byte [] buf = new byte [size ];
95
+ for (int i = 0 ; i < data .length ; i += size ) {
96
+ System .arraycopy (data , i , buf , 0 , size );
97
+ acc = acc .add (new P1 (buf ));
98
+ }
99
+ return compressed ? acc .compress () : acc .serialize ();
100
+ }
101
+
102
+ public static byte [] g2Add (byte [] data , boolean compressed ) {
103
+ P2 acc = new P2 ();
104
+ int size = compressed ? G2_LEN : 2 * G2_LEN ;
105
+ if (data .length == 0 || data .length % size != 0 ) {
106
+ throw new IllegalArgumentException ("BLS12-381: g2Add: invalid data layout: expected a multiple of " + size
107
+ + " bytes, got " + data .length );
108
+ }
109
+ byte [] buf = new byte [size ];
110
+ for (int i = 0 ; i < data .length ; i += size ) {
111
+ System .arraycopy (data , i , buf , 0 , size );
112
+ acc = acc .add (new P2 (buf ));
113
+ }
114
+ return compressed ? acc .compress () : acc .serialize ();
115
+ }
116
+
117
+ public static byte [] g1ScalarMul (byte [] scalarBytes , byte [] data , boolean compressed ) {
118
+ int size = compressed ? G1_LEN : 2 * G1_LEN ;
119
+ Scalar scalar = new Scalar ().from_bendian (scalarBytes );
120
+ if (data .length != size ) {
121
+ throw new IllegalArgumentException (
122
+ "BLS12-381: g1ScalarMul: invalid data layout: expected " + size + " bytes, got " + data .length );
123
+ }
124
+ P1 p = new P1 (data );
125
+ p = p .mult (scalar );
126
+ return compressed ? p .compress () : p .serialize ();
127
+ }
128
+
129
+ public static byte [] g2ScalarMul (byte [] scalarBytes , byte [] data , boolean compressed ) {
130
+ int size = compressed ? G2_LEN : 2 * G2_LEN ;
131
+ Scalar scalar = new Scalar ().from_bendian (scalarBytes );
132
+ if (data .length != size ) {
133
+ throw new IllegalArgumentException (
134
+ "BLS12-381: g2ScalarMul: invalid data layout: expected " + size + " bytes, got " + data .length );
135
+ }
136
+ P2 p = new P2 (data );
137
+ p = p .mult (scalar );
138
+ return compressed ? p .compress () : p .serialize ();
139
+ }
140
+
141
+ public static boolean pairingCheck (byte [] data , boolean compressed ) {
142
+ int g1Size = compressed ? G1_LEN : 2 * G1_LEN ;
143
+ int g2Size = compressed ? G2_LEN : 2 * G2_LEN ;
144
+ int size = g1Size + g2Size ;
145
+
146
+ if (data .length == 0 || data .length % size != 0 ) {
147
+ throw new IllegalArgumentException ("BLS12-381: pairingCheck: invalid data layout: expected a multiple of "
148
+ + size + " bytes, got " + data .length );
149
+ }
150
+
151
+ PT acc = PT .one ();
152
+ byte [] p1buf = new byte [g1Size ];
153
+ byte [] p2buf = new byte [g2Size ];
154
+ for (int i = 0 ; i < data .length ; i += size ) {
155
+ System .arraycopy (data , i , p1buf , 0 , g1Size );
156
+ System .arraycopy (data , i + g1Size , p2buf , 0 , g2Size );
157
+ P1 p1 = new P1 (p1buf );
158
+ P2 p2 = new P2 (p2buf );
159
+ if (!p1 .in_group () || !p2 .in_group ()) {
160
+ throw new IllegalArgumentException ("G1 or G2 point not in subgroup!" );
161
+ }
162
+ if (p1 .is_inf () || p2 .is_inf ()) {
163
+ continue ;
164
+ }
165
+ acc = acc .mul (new PT (p1 , p2 ));
166
+ }
167
+
168
+ return acc .final_exp ().is_one ();
169
+ }
82
170
}
0 commit comments