aboutsummaryrefslogtreecommitdiffstats
path: root/ffi/cs/bls.cs
blob: 0afb9caa9f511ca7afeb4161a13ef65c5075f765 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
þ½Ž¿using System;
using System.Text;
using System.Runtime.InteropServices;

namespace mcl
{
    class BLS
    {
        public const int BN254 = 0;
        public const int BLS12_381 = 5;

        const int IoEcComp = 512; // fixed byte representation
        public const int FR_UNIT_SIZE = 4;
        public const int FP_UNIT_SIZE = 6; // 4 if bls256.dll is used
        public const int COMPILED_TIME_VAR = FR_UNIT_SIZE * 10 + FP_UNIT_SIZE;

        public const int ID_UNIT_SIZE = FR_UNIT_SIZE;
        public const int SECRETKEY_UNIT_SIZE = FR_UNIT_SIZE;
        public const int PUBLICKEY_UNIT_SIZE = FP_UNIT_SIZE * 3 * 2;
        public const int SIGNATURE_UNIT_SIZE = FP_UNIT_SIZE * 3;

        public const int ID_SERIALIZE_SIZE = FR_UNIT_SIZE * 8;
        public const int SECRETKEY_SERIALIZE_SIZE = FR_UNIT_SIZE * 8;
        public const int PUBLICKEY_SERIALIZE_SIZE = FP_UNIT_SIZE * 8 * 2;
        public const int SIGNATURE_SERIALIZE_SIZE = FP_UNIT_SIZE * 8;

        public const string dllName = FP_UNIT_SIZE == 4 ? "bls256.dll" : "bls384_256.dll";
        [DllImport(dllName)]
        public static extern int blsInit(int curveType, int compiledTimeVar);

        [DllImport(dllName)] public static extern void blsIdSetInt(ref Id id, int x);
        [DllImport(dllName)] public static extern int blsIdSetDecStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        [DllImport(dllName)] public static extern int blsIdSetHexStr(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsIdGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in Id id);
        [DllImport(dllName)] public static extern ulong blsIdGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Id id);

        [DllImport(dllName)] public static extern ulong blsIdSerialize([Out]byte[] buf, ulong maxBufSize, in Id id);
        [DllImport(dllName)] public static extern ulong blsSecretKeySerialize([Out]byte[] buf, ulong maxBufSize, in SecretKey sec);
        [DllImport(dllName)] public static extern ulong blsPublicKeySerialize([Out]byte[] buf, ulong maxBufSize, in PublicKey pub);
        [DllImport(dllName)] public static extern ulong blsSignatureSerialize([Out]byte[] buf, ulong maxBufSize, in Signature sig);
        [DllImport(dllName)] public static extern ulong blsIdDeserialize(ref Id id, [In]byte[] buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsSecretKeyDeserialize(ref SecretKey sec, [In]byte[] buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsPublicKeyDeserialize(ref PublicKey pub, [In]byte[] buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsSignatureDeserialize(ref Signature sig, [In]byte[] buf, ulong bufSize);

        [DllImport(dllName)] public static extern int blsIdIsEqual(in Id lhs, in Id rhs);
        [DllImport(dllName)] public static extern int blsSecretKeyIsEqual(in SecretKey lhs, in SecretKey rhs);
        [DllImport(dllName)] public static extern int blsPublicKeyIsEqual(in PublicKey lhs, in PublicKey rhs);
        [DllImport(dllName)] public static extern int blsSignatureIsEqual(in Signature lhs, in Signature rhs);
        // add
        [DllImport(dllName)] public static extern void blsSecretKeyAdd(ref SecretKey sec, in SecretKey rhs);
        [DllImport(dllName)] public static extern void blsPublicKeyAdd(ref PublicKey pub, in PublicKey rhs);
        [DllImport(dllName)] public static extern void blsSignatureAdd(ref Signature sig, in Signature rhs);
        //  hash buf and set
        [DllImport(dllName)] public static extern int blsHashToSecretKey(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        /*
            set secretKey if system has /dev/urandom or CryptGenRandom
            return 0 if success else -1
        */
        [DllImport(dllName)] public static extern int blsSecretKeySetByCSPRNG(ref SecretKey sec);

        [DllImport(dllName)] public static extern void blsGetPublicKey(ref PublicKey pub, in SecretKey sec);
        [DllImport(dllName)] public static extern void blsGetPop(ref Signature sig, in SecretKey sec);

        // return 0 if success
        [DllImport(dllName)] public static extern int blsSecretKeyShare(ref SecretKey sec, in SecretKey msk, ulong k, in Id id);
        [DllImport(dllName)] public static extern int blsPublicKeyShare(ref PublicKey pub, in PublicKey mpk, ulong k, in Id id);


        [DllImport(dllName)] public static extern int blsSecretKeyRecover(ref SecretKey sec, in SecretKey secVec, in Id idVec, ulong n);
        [DllImport(dllName)] public static extern int blsPublicKeyRecover(ref PublicKey pub, in PublicKey pubVec, in Id idVec, ulong n);
        [DllImport(dllName)] public static extern int blsSignatureRecover(ref Signature sig, in Signature sigVec, in Id idVec, ulong n);

        [DllImport(dllName)] public static extern void blsSign(ref Signature sig, in SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);

        // return 1 if valid
        [DllImport(dllName)] public static extern int blsVerify(in Signature sig, in PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string m, ulong size);
        [DllImport(dllName)] public static extern int blsVerifyPop(in Signature sig, in PublicKey pub);

        //////////////////////////////////////////////////////////////////////////
        // the following apis will be removed

        // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
        [DllImport(dllName)] public static extern int blsIdSetLittleEndian(ref Id id, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        /*
            return written byte size if success else 0
        */
        [DllImport(dllName)] public static extern ulong blsIdGetLittleEndian([Out]StringBuilder buf, ulong maxBufSize, in Id id);

        // return 0 if success
        // mask buf with (1 << (bitLen(r) - 1)) - 1 if buf >= r
        [DllImport(dllName)] public static extern int blsSecretKeySetLittleEndian(ref SecretKey sec, [In]byte[] buf, ulong bufSize);
        [DllImport(dllName)] public static extern int blsSecretKeySetDecStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        [DllImport(dllName)] public static extern int blsSecretKeySetHexStr(ref SecretKey sec, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        /*
            return written byte size if success else 0
        */
        [DllImport(dllName)] public static extern ulong blsSecretKeyGetLittleEndian([Out]byte[] buf, ulong maxBufSize, in SecretKey sec);
        /*
            return strlen(buf) if success else 0
            buf is '\0' terminated
        */
        [DllImport(dllName)] public static extern ulong blsSecretKeyGetDecStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec);
        [DllImport(dllName)] public static extern ulong blsSecretKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in SecretKey sec);
        [DllImport(dllName)] public static extern int blsPublicKeySetHexStr(ref PublicKey pub, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsPublicKeyGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in PublicKey pub);
        [DllImport(dllName)] public static extern int blsSignatureSetHexStr(ref Signature sig, [In][MarshalAs(UnmanagedType.LPStr)] string buf, ulong bufSize);
        [DllImport(dllName)] public static extern ulong blsSignatureGetHexStr([Out]StringBuilder buf, ulong maxBufSize, in Signature sig);

        public static void Init(int curveType = BN254) {
            if (!System.Environment.Is64BitProcess) {
                throw new PlatformNotSupportedException("not 64-bit system");
            }
            int err = blsInit(curveType, COMPILED_TIME_VAR);
            if (err != 0) {
                throw new ArgumentException("blsInit");
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct Id
        {
            private fixed ulong v[ID_UNIT_SIZE];
            public byte[] Serialize() {
                byte[] buf = new byte[ID_SERIALIZE_SIZE];
                ulong n = blsIdSerialize(buf, (ulong)buf.Length, this);
                if (n == 0) {
                    throw new ArithmeticException("blsIdSerialize");
                }
                return buf;
            }
            public void Deserialize(byte[] buf) {
                ulong n = blsIdDeserialize(ref this, buf, (ulong)buf.Length);
                if (n == 0) {
                    throw new ArithmeticException("blsIdDeserialize");
                }
            }
            public bool IsEqual(in Id rhs) {
                return blsIdIsEqual(this, rhs) != 0;
            }
            public void SetDecStr(string s) {
                if (blsIdSetDecStr(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsIdSetDecSt:" + s);
                }
            }
            public void SetHexStr(string s) {
                if (blsIdSetHexStr(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsIdSetHexStr:" + s);
                }
            }
            public void SetInt(int x) {
                blsIdSetInt(ref this, x);
            }
            public string GetDecStr() {
                StringBuilder sb = new StringBuilder(1024);
                ulong size = blsIdGetDecStr(sb, (ulong)sb.Capacity, this);
                if (size == 0) {
                    throw new ArgumentException("blsIdGetDecStr");
                }
                return sb.ToString(0, (int)size);
            }
            public string GetHexStr() {
                StringBuilder sb = new StringBuilder(1024);
                ulong size = blsIdGetHexStr(sb, (ulong)sb.Capacity, this);
                if (size == 0) {
                    throw new ArgumentException("blsIdGetHexStr");
                }
                return sb.ToString(0, (int)size);
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct SecretKey
        {
            private fixed ulong v[SECRETKEY_UNIT_SIZE];
            public byte[] Serialize() {
                byte[] buf = new byte[SECRETKEY_SERIALIZE_SIZE];
                ulong n = blsSecretKeySerialize(buf, (ulong)buf.Length, this);
                if (n == 0) {
                    throw new ArithmeticException("blsSecretKeySerialize");
                }
                return buf;
            }
            public void Deserialize(byte[] buf) {
                ulong n = blsSecretKeyDeserialize(ref this, buf, (ulong)buf.Length);
                if (n == 0) {
                    throw new ArithmeticException("blsSecretKeyDeserialize");
                }
            }
            public bool IsEqual(in SecretKey rhs) {
                return blsSecretKeyIsEqual(this, rhs) != 0;
            }
            public void SetHexStr(string s) {
                if (blsSecretKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsSecretKeySetHexStr:" + s);
                }
            }
            public string GetHexStr() {
                StringBuilder sb = new StringBuilder(1024);
                ulong size = blsSecretKeyGetHexStr(sb, (ulong)sb.Capacity, this);
                if (size == 0) {
                    throw new ArgumentException("mclBnFr_getStr");
                }
                return sb.ToString(0, (int)size);
            }
            public void Add(in SecretKey rhs) {
                blsSecretKeyAdd(ref this, rhs);
            }
            public void SetByCSPRNG() {
                blsSecretKeySetByCSPRNG(ref this);
            }
            public void SetHashOf(string s) {
                if (blsHashToSecretKey(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsHashToSecretKey");
                }
            }
            public PublicKey GetPublicKey() {
                PublicKey pub = new PublicKey();
                blsGetPublicKey(ref pub, this);
                return pub;
            }
            public Signature Signature(string m) {
                Signature Signature = new Signature();
                blsSign(ref Signature, this, m, (ulong)m.Length);
                return Signature;
            }
        }
        // secretKey = sum_{i=0}^{msk.Length - 1} msk[i] * id^i
        public static SecretKey ShareSecretKey(in SecretKey[] msk, in Id id) {
            SecretKey sec = new SecretKey();
            if (blsSecretKeyShare(ref sec, msk[0], (ulong)msk.Length, id) != 0) {
                throw new ArgumentException("GetSecretKeyForId:" + id.ToString());
            }
            return sec;
        }
        public static SecretKey RecoverSecretKey(in SecretKey[] secs, in Id[] ids) {
            SecretKey sec = new SecretKey();
            if (blsSecretKeyRecover(ref sec, secs[0], ids[0], (ulong)secs.Length) != 0) {
                throw new ArgumentException("Recover");
            }
            return sec;
        }
        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct PublicKey
        {
            private fixed ulong v[PUBLICKEY_UNIT_SIZE];
            public byte[] Serialize() {
                byte[] buf = new byte[PUBLICKEY_SERIALIZE_SIZE];
                ulong n = blsPublicKeySerialize(buf, (ulong)buf.Length, this);
                if (n == 0) {
                    throw new ArithmeticException("blsPublicKeySerialize");
                }
                return buf;
            }
            public void Deserialize(byte[] buf) {
                ulong n = blsPublicKeyDeserialize(ref this, buf, (ulong)buf.Length);
                if (n == 0) {
                    throw new ArithmeticException("blsPublicKeyDeserialize");
                }
            }
            public bool IsEqual(in PublicKey rhs) {
                return blsPublicKeyIsEqual(this, rhs) != 0;
            }
            public void SetStr(string s) {
                if (blsPublicKeySetHexStr(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsPublicKeySetStr:" + s);
                }
            }
            public string GetHexStr() {
                StringBuilder sb = new StringBuilder(1024);
                ulong size = blsPublicKeyGetHexStr(sb, (ulong)sb.Capacity, this);
                if (size == 0) {
                    throw new ArgumentException("blsPublicKeyGetStr");
                }
                return sb.ToString(0, (int)size);
            }
            public void Add(in PublicKey rhs) {
                blsPublicKeyAdd(ref this, rhs);
            }
            public bool Verify(in Signature sig, string m) {
                return blsVerify(sig, this, m, (ulong)m.Length) == 1;
            }
        }
        // publicKey = sum_{i=0}^{mpk.Length - 1} mpk[i] * id^i
        public static PublicKey SharePublicKey(in PublicKey[] mpk, in Id id) {
            PublicKey pub = new PublicKey();
            if (blsPublicKeyShare(ref pub, mpk[0], (ulong)mpk.Length, id) != 0) {
                throw new ArgumentException("GetPublicKeyForId:" + id.ToString());
            }
            return pub;
        }
        public static PublicKey RecoverPublicKey(in PublicKey[] pubs, in Id[] ids) {
            PublicKey pub = new PublicKey();
            if (blsPublicKeyRecover(ref pub, pubs[0], ids[0], (ulong)pubs.Length) != 0) {
                throw new ArgumentException("Recover");
            }
            return pub;
        }
        [StructLayout(LayoutKind.Sequential)]
        public unsafe struct Signature
        {
            private fixed ulong v[SIGNATURE_UNIT_SIZE];
            public byte[] Serialize() {
                byte[] buf = new byte[SIGNATURE_SERIALIZE_SIZE];
                ulong n = blsSignatureSerialize(buf, (ulong)buf.Length, this);
                if (n == 0) {
                    throw new ArithmeticException("blsSignatureSerialize");
                }
                return buf;
            }
            public void Deserialize(byte[] buf) {
                ulong n = blsSignatureDeserialize(ref this, buf, (ulong)buf.Length);
                if (n == 0) {
                    throw new ArithmeticException("blsSignatureDeserialize");
                }
            }
            public bool IsEqual(in Signature rhs) {
                return blsSignatureIsEqual(this, rhs) != 0;
            }
            public void SetStr(string s) {
                if (blsSignatureSetHexStr(ref this, s, (ulong)s.Length) != 0) {
                    throw new ArgumentException("blsSignatureSetStr:" + s);
                }
            }
            public string GetHexStr() {
                StringBuilder sb = new StringBuilder(1024);
                ulong size = blsSignatureGetHexStr(sb, (ulong)sb.Capacity, this);
                if (size == 0) {
                    throw new ArgumentException("blsSignatureGetStr");
                }
                return sb.ToString(0, (int)size);
            }
            public void Add(in Signature rhs) {
                blsSignatureAdd(ref this, rhs);
            }
        }
        public static Signature RecoverSign(in Signature[] signs, in Id[] ids) {
            Signature Signature = new Signature();
            if (blsSignatureRecover(ref Signature, signs[0], ids[0], (ulong)signs.Length) != 0) {
                throw new ArgumentException("Recover");
            }
            return Signature;
        }
    }
}