diff --git a/.gitignore b/.gitignore index 5feea268..6b3934a5 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,6 @@ bindings/rust/blst bindings/python bindings/java bindings/node.js + +bin/ +obj/ diff --git a/.lgtm.yml b/.lgtm.yml index 0eb7550f..134dcc7a 100644 --- a/.lgtm.yml +++ b/.lgtm.yml @@ -13,3 +13,8 @@ extraction: build_command: - (cd bindings/go; go test -c) + csharp: + index: + buildless: true + nuget_restore: false + diff --git a/bindings/c#/poc.cs b/bindings/c#/poc.cs new file mode 100644 index 00000000..6c4b75e6 --- /dev/null +++ b/bindings/c#/poc.cs @@ -0,0 +1,79 @@ +using System; +using System.Text; +using supranational; + +class PoC { + private static void Main(string[] args) + { + var msg = Encoding.UTF8.GetBytes("assertion"); + var DST = "MY-DST"; + + var SK = new blst.SecretKey(); + SK.keygen(Encoding.UTF8.GetBytes(new string('*', 32))); + + // generate public key and serialize it... + var pk_for_wire = new blst.P1(SK).serialize(); + + // sign |msg| and serialize the signature... + var sig_for_wire = new blst.P2().hash_to(msg, DST, pk_for_wire) + .sign_with(SK) + .serialize(); + + // now on "receiving" side, start with deserialization... + var _sig = new blst.P2_Affine(sig_for_wire); + var _pk = new blst.P1_Affine(pk_for_wire); + if (!_pk.in_group()) + throw new blst.Exception(blst.ERROR.POINT_NOT_IN_GROUP); + var ctx = new blst.Pairing(true, DST); + var err = ctx.aggregate(_pk, _sig, msg, pk_for_wire); + if (err != blst.ERROR.SUCCESS) + throw new blst.Exception(err); + ctx.commit(); + if (!ctx.finalverify()) + throw new blst.Exception(blst.ERROR.VERIFY_FAIL); + Console.WriteLine("OK"); + + // exercise .as_fp12 by performing equivalent of ctx.finalverify above + var C1 = new blst.PT(_sig); + var C2 = ctx.as_fp12(); + if (!blst.PT.finalverify(C1, C2)) + throw new blst.Exception(blst.ERROR.VERIFY_FAIL); + + // test integers as scalar multiplicands + var p = blst.G1(); + var q = p.dup().dbl().dbl().add(p); + if (!p.mult(5).is_equal(q)) + throw new ApplicationException("disaster"); + if (!blst.G1().mult(-5).is_equal(q.neg())) + throw new ApplicationException("disaster"); + + // low-order sanity check + var p11 = new blst.P1(fromHexString("80803f0d09fec09a95f2ee7495323c15c162270c7cceaffa8566e941c66bcf206e72955d58b3b32e564de3209d672ca5")); + if (p11.in_group()) + throw new ApplicationException("disaster"); + if (!p11.mult(11).is_inf()) + throw new ApplicationException("disaster"); + } + + private static int fromHexChar(char c) + { + if (c>='0' && c<='9') return c - '0'; + else if (c>='a' && c<='f') return c - 'a' + 10; + else if (c>='A' && c<='F') return c - 'A' + 10; + throw new ArgumentOutOfRangeException("non-hex character"); + } + + private static byte[] fromHexString(string str) + { + if (str.Length%2 != 0) + throw new ArgumentException("odd number of characters in hex string"); + + char[] hex = str.ToCharArray(); + byte[] ret = new byte[hex.Length/2]; + + for (int i=0; i + + + Exe + netcoreapp3.1 + + + diff --git a/bindings/c#/run.me b/bindings/c#/run.me new file mode 100755 index 00000000..ffc5ad19 --- /dev/null +++ b/bindings/c#/run.me @@ -0,0 +1,741 @@ +#!/usr/bin/env python3 + +import os +import re +import sys +import glob +import subprocess + +top = """ +using System; +using System.Text; +using System.Numerics; +using System.Runtime.InteropServices; +using size_t = System.UIntPtr; + +namespace supranational { public static class blst { + +public enum ERROR { + SUCCESS = 0, + BAD_ENCODING, + POINT_NOT_ON_CURVE, + POINT_NOT_IN_GROUP, + AGGR_TYPE_MISMATCH, + VERIFY_FAIL, + PK_IS_INFINITY, + BAD_SCALAR, +} + +public class Exception : ApplicationException { + private ERROR code; + + public Exception(ERROR err) { code = err; } + public override string Message + { get + { switch(code) { + case ERROR.BAD_ENCODING: return "bad encoding"; + case ERROR.POINT_NOT_ON_CURVE: return "point not on curve"; + case ERROR.POINT_NOT_IN_GROUP: return "point not in group"; + case ERROR.AGGR_TYPE_MISMATCH: return "aggregate type mismatch"; + case ERROR.VERIFY_FAIL: return "verify failure"; + case ERROR.PK_IS_INFINITY: return "public key is infinity"; + case ERROR.BAD_SCALAR: return "bad scalar"; + default: return null; + } + } + } +} + +public enum ByteOrder { + BigEndian, + LittleEndian, +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_keygen([Out] byte[] key, [In] byte[] IKM, size_t IKM_len, + [In] byte[] info, size_t info_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_keygen_v3([Out] byte[] key, [In] byte[] IKM, size_t IKM_len, + [In] byte[] info, size_t info_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_derive_master_eip2333([Out] byte[] key, + [In] byte[] IKM, size_t IKM_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_derive_child_eip2333([Out] byte[] key, + [In] byte[] master, uint child_index); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_bendian([Out] byte[] ret, [In] byte[] key); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_bendian_from_scalar([Out] byte[] ret, [In] byte[] key); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_check([In] byte[] key); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_lendian([Out] byte[] key, [In] byte[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_lendian_from_scalar([Out] byte[] key, [In] byte[] inp); + +public struct SecretKey { + internal byte[] key; + + //public SecretKey() { key = new byte[32]; } + public SecretKey(byte[] IKM, string info) + { key = new byte[32]; keygen(IKM, info); } + public SecretKey(byte[] inp, ByteOrder order=ByteOrder.BigEndian) + { key = new byte[32]; + switch(order) { + case ByteOrder.BigEndian: from_bendian(inp); break; + case ByteOrder.LittleEndian: from_lendian(inp); break; + } + } + + public void keygen(byte[] IKM, string info="") + { if (key == null) key = new byte[32]; + byte[] info_bytes = Encoding.UTF8.GetBytes(info); + blst_keygen(key, IKM, (size_t)IKM.Length, + info_bytes, (size_t)info_bytes.Length); + } + public void keygen_v3(byte[] IKM, string info="") + { if (key == null) key = new byte[32]; + byte[] info_bytes = Encoding.UTF8.GetBytes(info); + blst_keygen_v3(key, IKM, (size_t)IKM.Length, + info_bytes, (size_t)info_bytes.Length); + } + public void derive_master_eip2333(byte[] IKM) + { if (key == null) key = new byte[32]; + blst_derive_master_eip2333(key, IKM, (size_t)IKM.Length); + } + public SecretKey(SecretKey master, uint child_index) + { key = new byte[32]; + blst_derive_child_eip2333(key, master.key, child_index); + } + + public void from_bendian(byte[] inp) + { if (inp.Length != 32) + throw new Exception(ERROR.BAD_ENCODING); + if (key == null) key = new byte[32]; + blst_scalar_from_bendian(key, inp); + if (!blst_sk_check(key)) + throw new Exception(ERROR.BAD_ENCODING); + } + public void from_lendian(byte[] inp) + { if (inp.Length != 32) + throw new Exception(ERROR.BAD_ENCODING); + if (key == null) key = new byte[32]; + blst_scalar_from_lendian(key, inp); + if (!blst_sk_check(key)) + throw new Exception(ERROR.BAD_ENCODING); + } + + public byte[] to_bendian() + { byte[] ret = new byte[32]; + blst_bendian_from_scalar(ret, key); + return ret; + } + public byte[] to_lendian() + { byte[] ret = new byte[32]; + blst_lendian_from_scalar(ret, key); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_be_bytes([Out] byte[] ret, [In] byte[] inp, + size_t inp_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_le_bytes([Out] byte[] ret, [In] byte[] inp, + size_t inp_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_add_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_sub_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_mul_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_sk_inverse([Out] byte[] ret, [In] byte[] a); + +public struct Scalar { + internal byte[] val; + + //public Scalar() { val = new byte[32]; } + public Scalar(byte[] inp, ByteOrder order=ByteOrder.BigEndian) + { val = new byte[32]; + switch(order) { + case ByteOrder.BigEndian: from_bendian(inp); break; + case ByteOrder.LittleEndian: from_lendian(inp); break; + } + } + private Scalar(bool _) { val = new byte[32]; } + private Scalar(Scalar orig) { val = (byte[])orig.val.Clone(); } + + public Scalar dup() { return new Scalar(this); } + + public void from_bendian(byte[] inp) + { if (val == null) val = new byte[32]; + blst_scalar_from_be_bytes(val, inp, (size_t)inp.Length); + } + public void from_lendian(byte[] inp) + { if (val == null) val = new byte[32]; + blst_scalar_from_le_bytes(val, inp, (size_t)inp.Length); + } + + public byte[] to_bendian() + { byte[] ret = new byte[32]; + blst_bendian_from_scalar(ret, val); + return ret; + } + public byte[] to_lendian() + { byte[] ret = new byte[32]; + blst_lendian_from_scalar(ret, val); + return ret; + } + + public Scalar add(SecretKey a) + { if (!blst_sk_add_n_check(val, val, a.key)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar add(Scalar a) + { if (!blst_sk_add_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar sub(Scalar a) + { if (!blst_sk_sub_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar mul(Scalar a) + { if (!blst_sk_mul_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar inverse() + { blst_sk_inverse(val, val); return this; } + + public static Scalar operator+(Scalar a, Scalar b) + { return a.dup().add(b); } + public static Scalar operator-(Scalar a, Scalar b) + { return a.dup().sub(b); } + public static Scalar operator*(Scalar a, Scalar b) + { return a.dup().mul(b); } + public static Scalar operator/(Scalar a, Scalar b) + { return b.dup().inverse().mul(a); } +} + +private const int P1_COMPRESSED_SZ = 384/8; +private const int P2_COMPRESSED_SZ = 2*P1_COMPRESSED_SZ; +""" +middle = """ +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p1_affine_sizeof(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_p1_deserialize([Out] long[] ret, [In] byte[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_affine_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_affine_compress([Out] byte[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_to_affine([Out] long[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_in_g1([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_p1_generator(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_core_verify_pk_in_g2([In] long[] pk, [In] long[] sig, + bool hash_or_encode, + [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); + +public struct P1_Affine { + internal long[] point; + + private static readonly int sz = (int)blst_p1_affine_sizeof()/sizeof(long); + + //public P1_Affine() { point = new long[sz]; } + private P1_Affine(bool _) { point = new long[sz]; } + private P1_Affine(P1_Affine p) { point = (long[])p.point.Clone(); } + + public P1_Affine(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P1_COMPRESSED_SZ + : 2*P1_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p1_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + } + public P1_Affine(P1 jacobian) : this(true) + { blst_p1_to_affine(point, jacobian.point); } + + public P1_Affine dup() { return new P1_Affine(this); } + public P1 to_jacobian() { return new P1(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P1_COMPRESSED_SZ]; + blst_p1_affine_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P1_COMPRESSED_SZ]; + blst_p1_affine_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p1_affine_on_curve(point); } + public bool in_group() { return blst_p1_affine_in_g1(point); } + public bool is_inf() { return blst_p1_affine_is_inf(point); } + public bool is_equal(P1_Affine p) + { return blst_p1_affine_is_equal(point, p.point); } + + ERROR core_verify(P2_Affine pk, bool hash_or_encode, + byte[] msg, string DST = "", byte[] aug = null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + return blst_core_verify_pk_in_g2(pk.point, point, + hash_or_encode, + msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + + public static P1_Affine generator() + { var ret = new P1_Affine(true); + Marshal.Copy(blst_p1_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p1_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_compress([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_from_affine([Out] long[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_in_g1([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_sk_to_pk_in_g1([Out] long[] ret, [In] byte[] SK); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_encode_to_g1([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_hash_to_g1([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_sign_pk_in_g2([Out] long[] ret, [In] long[] hash, [In] byte[] SK); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_mult([Out] long[] ret, [In] long[] a, + [In] byte[] scalar, size_t nbits); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_cneg([Out] long[] ret, bool cbit); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_add_or_double([Out] long[] ret, [In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_add_or_double_affine([Out] long[] ret, [In] long[] a, + [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_double([Out] long[] ret, [In] long[] a); + +public struct P1 { + internal long[] point; + + private static readonly int sz = (int)blst_p1_sizeof()/sizeof(long); + + //public P1() { point = new long[sz]; } + private P1(bool _) { point = new long[sz]; } + private P1(P1 p) { point = (long[])p.point.Clone(); } + private long[] self() + { if (point==null) point = new long[sz]; return point; } + + public P1(SecretKey sk) : this(true) + { blst_sk_to_pk_in_g1(point, sk.key); } + public P1(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P1_COMPRESSED_SZ + : 2*P1_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p1_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + blst_p1_from_affine(point, point); + } + public P1(P1_Affine affine) : this(true) + { blst_p1_from_affine(point, affine.point); } + + public P1 dup() { return new P1(this); } + public P1_Affine to_affine() { return new P1_Affine(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P1_COMPRESSED_SZ]; + blst_p1_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P1_COMPRESSED_SZ]; + blst_p1_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p1_on_curve(point); } + public bool in_group() { return blst_p1_in_g1(point); } + public bool is_inf() { return blst_p1_is_inf(point); } + public bool is_equal(P1 p) { return blst_p1_is_equal(point, p.point); } + + public P1 hash_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_hash_to_g1(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + public P1 encode_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_encode_to_g1(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + + public P1 sign_with(SecretKey sk) + { blst_sign_pk_in_g2(point, point, sk.key); return this; } + public P1 sign_with(Scalar scalar) + { blst_sign_pk_in_g2(point, point, scalar.val); return this; } + + public void aggregate(P1_Affine inp) + { if (blst_p1_affine_in_g1(inp.point)) + blst_p1_add_or_double_affine(point, point, inp.point); + else + throw new Exception(ERROR.POINT_NOT_IN_GROUP); + } + + public P1 mult(byte[] scalar) + { blst_p1_mult(point, point, scalar, (size_t)(scalar.Length*8)); + return this; + } + public P1 mult(Scalar scalar) + { blst_p1_mult(point, point, scalar.val, (size_t)255); + return this; + } + public P1 mult(BigInteger scalar) + { byte[] val; + if (scalar.Sign < 0) { + val = BigInteger.Negate(scalar).ToByteArray(); + blst_p1_cneg(point, true); + } else { + val = scalar.ToByteArray(); + } + int len = val.Length; + if (val[len-1]==0) len--; + blst_p1_mult(point, point, val, (size_t)(len*8)); + return this; + } + public P1 cneg(bool flag) { blst_p1_cneg(point, flag); return this; } + public P1 neg() { blst_p1_cneg(point, true); return this; } + public P1 add(P1 a) + { blst_p1_add_or_double(point, point, a.point); return this; } + public P1 add(P1_Affine a) + { blst_p1_add_or_double_affine(point, point, a.point); return this; } + public P1 dbl() + { blst_p1_double(point, point); return this; } + + public static P1 generator() + { var ret = new P1(true); + Marshal.Copy(blst_p1_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +public static P1 G1() { return P1.generator(); } + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_aggregated_in_g1([Out] long[] fp12, [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_aggregate_pk_in_g1([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_mul_n_aggregate_pk_in_g1([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] scalar, size_t nbits, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); +""" +bottom = """ +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_fp12_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_miller_loop([Out] long[] fp12, [In] long[] q, + [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_is_one([In] long[] fp12); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_is_equal([In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_fp12_sqr([Out] long[] ret, [In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_fp12_mul([Out] long[] ret, [In] long[] a, + [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_final_exp([Out] long[] ret, [In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_finalverify([In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_fp12_one(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_in_group([In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_bendian_from_fp12([Out] byte[] ret, [In] long[] a); + +public struct PT { + internal long[] fp12; + + private static readonly int sz = (int)blst_fp12_sizeof()/sizeof(long); + + internal PT(bool _) { fp12 = new long[sz]; } + private PT(PT orig) { fp12 = (long[])orig.fp12.Clone(); } + + public PT(P1_Affine p) : this(true) + { blst_aggregated_in_g1(fp12, p.point); } + public PT(P1 p) : this(true) + { blst_aggregated_in_g1(fp12, (new P1_Affine(p)).point); } + public PT(P2_Affine q) : this(true) + { blst_aggregated_in_g2(fp12, q.point); } + public PT(P2 q) : this(true) + { blst_aggregated_in_g2(fp12, (new P2_Affine(q)).point); } + public PT(P2_Affine q, P1_Affine p) : this(true) + { blst_miller_loop(fp12, q.point, p.point); } + public PT(P1_Affine p, P2_Affine q) : this(q, p) {} + public PT(P2 q, P1 p) : this(true) + { blst_miller_loop(fp12, (new P2_Affine(q)).point, + (new P1_Affine(p)).point); + } + public PT(P1 p, P2 q) : this(q, p) {} + + public PT dup() { return new PT(this); } + public bool is_one() { return blst_fp12_is_one(fp12); } + public bool is_equal(PT p) + { return blst_fp12_is_equal(fp12, p.fp12); } + public PT sqr() { blst_fp12_sqr(fp12, fp12); return this; } + public PT mul(PT p) { blst_fp12_mul(fp12, fp12, p.fp12); return this; } + public PT final_exp() { blst_final_exp(fp12, fp12); return this; } + public bool in_group() { return blst_fp12_in_group(fp12); } + public byte[] to_bendian() + { byte[] ret = new byte[12*P1_COMPRESSED_SZ]; + blst_bendian_from_fp12(ret, fp12); + return ret; + } + + public static bool finalverify(PT gt1, PT gt2) + { return blst_fp12_finalverify(gt1.fp12, gt2.fp12); } + + public static PT one() + { var ret = new PT(true); + Marshal.Copy(blst_fp12_one(), ret.fp12, 0, ret.fp12.Length); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_pairing_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_pairing_init([In, Out] long[] ctx, bool hash_or_encode, + [In] ref long dst, size_t dst_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_pairing_commit([In, Out] long[] ctx); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_merge([In, Out] long[] ctx, [In] long[] ctx1); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_pairing_finalverify([In] long[] ctx, [In] long[] sig); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_pairing_raw_aggregate([In, Out] long[] ctx, [In] long[] q, + [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_pairing_as_fp12([In] long[] ctx); + +public struct Pairing { + private long[] ctx; + + private static readonly int sz = (int)blst_pairing_sizeof()/sizeof(long); + + public Pairing(bool hash_or_encode=false, string DST="") + { + byte[] dst = Encoding.UTF8.GetBytes(DST); + int dst_len = dst.Length; + int add_len = dst_len!=0 ? (dst_len+sizeof(long)-1)/sizeof(long) : 1; + Array.Resize(ref dst, add_len*sizeof(long)); + + ctx = new long[sz+add_len]; + + for (int i=0; i sig, + byte[] msg, byte[] aug=null) + { return blst_pairing_aggregate_pk_in_g1(ctx, pk.point, + sig.HasValue ? sig.Value.point : null, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR aggregate(P2_Affine pk, Nullable sig, + byte[] msg, byte[] aug=null) + { return blst_pairing_aggregate_pk_in_g2(ctx, pk.point, + sig.HasValue ? sig.Value.point : null, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR mul_n_aggregate(P2_Affine pk, P1_Affine sig, + byte[] scalar, int nbits, + byte[] msg, byte[] aug=null) + { return blst_pairing_mul_n_aggregate_pk_in_g2(ctx, pk.point, sig.point, + scalar, (size_t)nbits, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR mul_n_aggregate(P1_Affine pk, P2_Affine sig, + byte[] scalar, int nbits, + byte[] msg, byte[] aug=null) + { return blst_pairing_mul_n_aggregate_pk_in_g1(ctx, pk.point, sig.point, + scalar, (size_t)nbits, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + + public void commit() { blst_pairing_commit(ctx); } + public void merge(Pairing a) + { var err = blst_pairing_merge(ctx, a.ctx); + if (err != ERROR.SUCCESS) + throw new Exception(err); + } + public bool finalverify(PT sig=new PT()) + { return blst_pairing_finalverify(ctx, sig.fp12); } + + public void raw_aggregate(P2_Affine q, P1_Affine p) + { blst_pairing_raw_aggregate(ctx, q.point, p.point); } + public void raw_aggregate(P1_Affine p, P2_Affine q) + { raw_aggregate(q, p); } + public void raw_aggregate(P2 q, P1 p) + { blst_pairing_raw_aggregate(ctx, (new P2_Affine(q)).point, + (new P1_Affine(p)).point); + } + public void raw_aggregate(P1 p, P2 q) + { raw_aggregate(q, p); } + public PT as_fp12() + { var ret = new PT(true); + GCHandle h = GCHandle.Alloc(ctx, GCHandleType.Pinned); + Marshal.Copy(blst_pairing_as_fp12(ctx), ret.fp12, 0, ret.fp12.Length); + h.Free(); + return ret; + } +} +}}""" + +here = re.split(r'[/\\](?=[^/\\]*$)', sys.argv[0]) +if len(here) > 1: + os.chdir(here[0]) + + +def xchg_1vs2(matchobj): + if matchobj.group(2) == '1': + return matchobj.group(1) + '2' + else: + return matchobj.group(1) + '1' + + +fname = "supranational.blst.cs" +fd = open(fname, "w") +print("//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", file=fd) +print("// DO NOT EDIT THIS FILE!!!", file=fd) +print("// The file is auto-generated by " + here[-1], file=fd) +print("//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", file=fd) +print("\n\n", file=fd) +print(top, file=fd) +print(middle, file=fd) +print(re.sub(r'((? os.stat(rh).st_ctime: + return True + return False + + +try: # mono-devel on Linux ["-language:5" corresponds to latest ECMA/ISO] + subprocess.check_call(["mcs", "-langversion:5", "-optimize+", + "poc.cs", fname, "-r:System.Numerics.dll"]) + if newer(["../blst.h"] + glob.glob("libblst.dll.*")): + print("building libblst.dll...") or sys.stdout.flush() + subprocess.check_call(["../../build.sh", "-dll"] + sys.argv[1:]) + subprocess.check_call(["mono", "poc.exe"]) + sys.exit(0) +except OSError as e: + if e.errno != 2: # not "no such file or directory" + raise e + +try: # Visual Studio Developer Command Prompt + subprocess.check_call(["csc", "-langversion:5", "-optimize+", + "poc.cs", fname, "-r:System.Numerics.dll"]) + if newer([os.path.normpath("../blst.h"), "blst.dll"]): + print("building blst.dll...") or sys.stdout.flush() + subprocess.check_call([os.path.normpath("../../build.bat"), "-shared"] + + sys.argv[1:]) + subprocess.check_call(os.path.normpath("./poc.exe")) + sys.exit(0) +except OSError as e: + if e.errno != 2: # not "no such file or directory" + raise e + +# env = os.environ.copy() +# env["PATH"] = os.getcwd() + os.path.pathsep + env["PATH"] +# env["DYLD_FALLBACK_LIBRARY_PATH"] = os.getcwd() +# env["LD_LIBRARY_PATH"] = os.getcwd() +# subprocess.check_call(["dotnet", "run"], env=env) diff --git a/bindings/c#/supranational.blst.cs b/bindings/c#/supranational.blst.cs new file mode 100644 index 00000000..c2a60810 --- /dev/null +++ b/bindings/c#/supranational.blst.cs @@ -0,0 +1,934 @@ +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// DO NOT EDIT THIS FILE!!! +// The file is auto-generated by run.me +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + + + +using System; +using System.Text; +using System.Numerics; +using System.Runtime.InteropServices; +using size_t = System.UIntPtr; + +namespace supranational { public static class blst { + +public enum ERROR { + SUCCESS = 0, + BAD_ENCODING, + POINT_NOT_ON_CURVE, + POINT_NOT_IN_GROUP, + AGGR_TYPE_MISMATCH, + VERIFY_FAIL, + PK_IS_INFINITY, + BAD_SCALAR, +} + +public class Exception : ApplicationException { + private ERROR code; + + public Exception(ERROR err) { code = err; } + public override string Message + { get + { switch(code) { + case ERROR.BAD_ENCODING: return "bad encoding"; + case ERROR.POINT_NOT_ON_CURVE: return "point not on curve"; + case ERROR.POINT_NOT_IN_GROUP: return "point not in group"; + case ERROR.AGGR_TYPE_MISMATCH: return "aggregate type mismatch"; + case ERROR.VERIFY_FAIL: return "verify failure"; + case ERROR.PK_IS_INFINITY: return "public key is infinity"; + case ERROR.BAD_SCALAR: return "bad scalar"; + default: return null; + } + } + } +} + +public enum ByteOrder { + BigEndian, + LittleEndian, +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_keygen([Out] byte[] key, [In] byte[] IKM, size_t IKM_len, + [In] byte[] info, size_t info_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_keygen_v3([Out] byte[] key, [In] byte[] IKM, size_t IKM_len, + [In] byte[] info, size_t info_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_derive_master_eip2333([Out] byte[] key, + [In] byte[] IKM, size_t IKM_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_derive_child_eip2333([Out] byte[] key, + [In] byte[] master, uint child_index); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_bendian([Out] byte[] ret, [In] byte[] key); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_bendian_from_scalar([Out] byte[] ret, [In] byte[] key); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_check([In] byte[] key); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_lendian([Out] byte[] key, [In] byte[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_lendian_from_scalar([Out] byte[] key, [In] byte[] inp); + +public struct SecretKey { + internal byte[] key; + + //public SecretKey() { key = new byte[32]; } + public SecretKey(byte[] IKM, string info) + { key = new byte[32]; keygen(IKM, info); } + public SecretKey(byte[] inp, ByteOrder order=ByteOrder.BigEndian) + { key = new byte[32]; + switch(order) { + case ByteOrder.BigEndian: from_bendian(inp); break; + case ByteOrder.LittleEndian: from_lendian(inp); break; + } + } + + public void keygen(byte[] IKM, string info="") + { if (key == null) key = new byte[32]; + byte[] info_bytes = Encoding.UTF8.GetBytes(info); + blst_keygen(key, IKM, (size_t)IKM.Length, + info_bytes, (size_t)info_bytes.Length); + } + public void keygen_v3(byte[] IKM, string info="") + { if (key == null) key = new byte[32]; + byte[] info_bytes = Encoding.UTF8.GetBytes(info); + blst_keygen_v3(key, IKM, (size_t)IKM.Length, + info_bytes, (size_t)info_bytes.Length); + } + public void derive_master_eip2333(byte[] IKM) + { if (key == null) key = new byte[32]; + blst_derive_master_eip2333(key, IKM, (size_t)IKM.Length); + } + public SecretKey(SecretKey master, uint child_index) + { key = new byte[32]; + blst_derive_child_eip2333(key, master.key, child_index); + } + + public void from_bendian(byte[] inp) + { if (inp.Length != 32) + throw new Exception(ERROR.BAD_ENCODING); + if (key == null) key = new byte[32]; + blst_scalar_from_bendian(key, inp); + if (!blst_sk_check(key)) + throw new Exception(ERROR.BAD_ENCODING); + } + public void from_lendian(byte[] inp) + { if (inp.Length != 32) + throw new Exception(ERROR.BAD_ENCODING); + if (key == null) key = new byte[32]; + blst_scalar_from_lendian(key, inp); + if (!blst_sk_check(key)) + throw new Exception(ERROR.BAD_ENCODING); + } + + public byte[] to_bendian() + { byte[] ret = new byte[32]; + blst_bendian_from_scalar(ret, key); + return ret; + } + public byte[] to_lendian() + { byte[] ret = new byte[32]; + blst_lendian_from_scalar(ret, key); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_be_bytes([Out] byte[] ret, [In] byte[] inp, + size_t inp_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_scalar_from_le_bytes([Out] byte[] ret, [In] byte[] inp, + size_t inp_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_add_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_sub_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_sk_mul_n_check([Out] byte[] ret, [In] byte[] a, + [In] byte[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_sk_inverse([Out] byte[] ret, [In] byte[] a); + +public struct Scalar { + internal byte[] val; + + //public Scalar() { val = new byte[32]; } + public Scalar(byte[] inp, ByteOrder order=ByteOrder.BigEndian) + { val = new byte[32]; + switch(order) { + case ByteOrder.BigEndian: from_bendian(inp); break; + case ByteOrder.LittleEndian: from_lendian(inp); break; + } + } + private Scalar(bool _) { val = new byte[32]; } + private Scalar(Scalar orig) { val = (byte[])orig.val.Clone(); } + + public Scalar dup() { return new Scalar(this); } + + public void from_bendian(byte[] inp) + { if (val == null) val = new byte[32]; + blst_scalar_from_be_bytes(val, inp, (size_t)inp.Length); + } + public void from_lendian(byte[] inp) + { if (val == null) val = new byte[32]; + blst_scalar_from_le_bytes(val, inp, (size_t)inp.Length); + } + + public byte[] to_bendian() + { byte[] ret = new byte[32]; + blst_bendian_from_scalar(ret, val); + return ret; + } + public byte[] to_lendian() + { byte[] ret = new byte[32]; + blst_lendian_from_scalar(ret, val); + return ret; + } + + public Scalar add(SecretKey a) + { if (!blst_sk_add_n_check(val, val, a.key)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar add(Scalar a) + { if (!blst_sk_add_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar sub(Scalar a) + { if (!blst_sk_sub_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar mul(Scalar a) + { if (!blst_sk_mul_n_check(val, val, a.val)) + throw new Exception(ERROR.BAD_SCALAR); + return this; + } + public Scalar inverse() + { blst_sk_inverse(val, val); return this; } + + public static Scalar operator+(Scalar a, Scalar b) + { return a.dup().add(b); } + public static Scalar operator-(Scalar a, Scalar b) + { return a.dup().sub(b); } + public static Scalar operator*(Scalar a, Scalar b) + { return a.dup().mul(b); } + public static Scalar operator/(Scalar a, Scalar b) + { return b.dup().inverse().mul(a); } +} + +private const int P1_COMPRESSED_SZ = 384/8; +private const int P2_COMPRESSED_SZ = 2*P1_COMPRESSED_SZ; + + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p1_affine_sizeof(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_p1_deserialize([Out] long[] ret, [In] byte[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_affine_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_affine_compress([Out] byte[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_to_affine([Out] long[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_in_g1([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_affine_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_p1_generator(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_core_verify_pk_in_g2([In] long[] pk, [In] long[] sig, + bool hash_or_encode, + [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); + +public struct P1_Affine { + internal long[] point; + + private static readonly int sz = (int)blst_p1_affine_sizeof()/sizeof(long); + + //public P1_Affine() { point = new long[sz]; } + private P1_Affine(bool _) { point = new long[sz]; } + private P1_Affine(P1_Affine p) { point = (long[])p.point.Clone(); } + + public P1_Affine(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P1_COMPRESSED_SZ + : 2*P1_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p1_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + } + public P1_Affine(P1 jacobian) : this(true) + { blst_p1_to_affine(point, jacobian.point); } + + public P1_Affine dup() { return new P1_Affine(this); } + public P1 to_jacobian() { return new P1(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P1_COMPRESSED_SZ]; + blst_p1_affine_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P1_COMPRESSED_SZ]; + blst_p1_affine_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p1_affine_on_curve(point); } + public bool in_group() { return blst_p1_affine_in_g1(point); } + public bool is_inf() { return blst_p1_affine_is_inf(point); } + public bool is_equal(P1_Affine p) + { return blst_p1_affine_is_equal(point, p.point); } + + ERROR core_verify(P2_Affine pk, bool hash_or_encode, + byte[] msg, string DST = "", byte[] aug = null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + return blst_core_verify_pk_in_g2(pk.point, point, + hash_or_encode, + msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + + public static P1_Affine generator() + { var ret = new P1_Affine(true); + Marshal.Copy(blst_p1_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p1_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_compress([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_from_affine([Out] long[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_in_g1([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p1_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_sk_to_pk_in_g1([Out] long[] ret, [In] byte[] SK); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_encode_to_g1([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_hash_to_g1([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_sign_pk_in_g2([Out] long[] ret, [In] long[] hash, [In] byte[] SK); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_mult([Out] long[] ret, [In] long[] a, + [In] byte[] scalar, size_t nbits); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_cneg([Out] long[] ret, bool cbit); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_add_or_double([Out] long[] ret, [In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p1_add_or_double_affine([Out] long[] ret, [In] long[] a, + [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p1_double([Out] long[] ret, [In] long[] a); + +public struct P1 { + internal long[] point; + + private static readonly int sz = (int)blst_p1_sizeof()/sizeof(long); + + //public P1() { point = new long[sz]; } + private P1(bool _) { point = new long[sz]; } + private P1(P1 p) { point = (long[])p.point.Clone(); } + private long[] self() + { if (point==null) point = new long[sz]; return point; } + + public P1(SecretKey sk) : this(true) + { blst_sk_to_pk_in_g1(point, sk.key); } + public P1(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P1_COMPRESSED_SZ + : 2*P1_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p1_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + blst_p1_from_affine(point, point); + } + public P1(P1_Affine affine) : this(true) + { blst_p1_from_affine(point, affine.point); } + + public P1 dup() { return new P1(this); } + public P1_Affine to_affine() { return new P1_Affine(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P1_COMPRESSED_SZ]; + blst_p1_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P1_COMPRESSED_SZ]; + blst_p1_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p1_on_curve(point); } + public bool in_group() { return blst_p1_in_g1(point); } + public bool is_inf() { return blst_p1_is_inf(point); } + public bool is_equal(P1 p) { return blst_p1_is_equal(point, p.point); } + + public P1 hash_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_hash_to_g1(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + public P1 encode_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_encode_to_g1(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + + public P1 sign_with(SecretKey sk) + { blst_sign_pk_in_g2(point, point, sk.key); return this; } + public P1 sign_with(Scalar scalar) + { blst_sign_pk_in_g2(point, point, scalar.val); return this; } + + public void aggregate(P1_Affine inp) + { if (blst_p1_affine_in_g1(inp.point)) + blst_p1_add_or_double_affine(point, point, inp.point); + else + throw new Exception(ERROR.POINT_NOT_IN_GROUP); + } + + public P1 mult(byte[] scalar) + { blst_p1_mult(point, point, scalar, (size_t)(scalar.Length*8)); + return this; + } + public P1 mult(Scalar scalar) + { blst_p1_mult(point, point, scalar.val, (size_t)255); + return this; + } + public P1 mult(BigInteger scalar) + { byte[] val; + if (scalar.Sign < 0) { + val = BigInteger.Negate(scalar).ToByteArray(); + blst_p1_cneg(point, true); + } else { + val = scalar.ToByteArray(); + } + int len = val.Length; + if (val[len-1]==0) len--; + blst_p1_mult(point, point, val, (size_t)(len*8)); + return this; + } + public P1 cneg(bool flag) { blst_p1_cneg(point, flag); return this; } + public P1 neg() { blst_p1_cneg(point, true); return this; } + public P1 add(P1 a) + { blst_p1_add_or_double(point, point, a.point); return this; } + public P1 add(P1_Affine a) + { blst_p1_add_or_double_affine(point, point, a.point); return this; } + public P1 dbl() + { blst_p1_double(point, point); return this; } + + public static P1 generator() + { var ret = new P1(true); + Marshal.Copy(blst_p1_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +public static P1 G1() { return P1.generator(); } + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_aggregated_in_g1([Out] long[] fp12, [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_aggregate_pk_in_g1([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_mul_n_aggregate_pk_in_g1([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] scalar, size_t nbits, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); + + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p2_affine_sizeof(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_p2_deserialize([Out] long[] ret, [In] byte[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_affine_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_affine_compress([Out] byte[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_to_affine([Out] long[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_affine_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_affine_in_g2([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_affine_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_affine_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_p2_generator(); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_core_verify_pk_in_g1([In] long[] pk, [In] long[] sig, + bool hash_or_encode, + [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); + +public struct P2_Affine { + internal long[] point; + + private static readonly int sz = (int)blst_p2_affine_sizeof()/sizeof(long); + + //public P2_Affine() { point = new long[sz]; } + private P2_Affine(bool _) { point = new long[sz]; } + private P2_Affine(P2_Affine p) { point = (long[])p.point.Clone(); } + + public P2_Affine(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P2_COMPRESSED_SZ + : 2*P2_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p2_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + } + public P2_Affine(P2 jacobian) : this(true) + { blst_p2_to_affine(point, jacobian.point); } + + public P2_Affine dup() { return new P2_Affine(this); } + public P2 to_jacobian() { return new P2(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P2_COMPRESSED_SZ]; + blst_p2_affine_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P2_COMPRESSED_SZ]; + blst_p2_affine_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p2_affine_on_curve(point); } + public bool in_group() { return blst_p2_affine_in_g2(point); } + public bool is_inf() { return blst_p2_affine_is_inf(point); } + public bool is_equal(P2_Affine p) + { return blst_p2_affine_is_equal(point, p.point); } + + ERROR core_verify(P1_Affine pk, bool hash_or_encode, + byte[] msg, string DST = "", byte[] aug = null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + return blst_core_verify_pk_in_g1(pk.point, point, + hash_or_encode, + msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + + public static P2_Affine generator() + { var ret = new P2_Affine(true); + Marshal.Copy(blst_p2_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_p2_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_serialize([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_compress([Out] byte[] ret, [In] long[] inp); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_from_affine([Out] long[] ret, [In] long[] inp); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_on_curve([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_in_g2([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_is_inf([In] long[] point); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_p2_is_equal([In] long[] a, [In] long[] b); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_sk_to_pk_in_g2([Out] long[] ret, [In] byte[] SK); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_encode_to_g2([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_hash_to_g2([Out] long[] ret, [In] byte[] msg, size_t msg_len, + [In] byte[] dst, size_t dst_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_sign_pk_in_g1([Out] long[] ret, [In] long[] hash, [In] byte[] SK); + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p2_mult([Out] long[] ret, [In] long[] a, + [In] byte[] scalar, size_t nbits); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_cneg([Out] long[] ret, bool cbit); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p2_add_or_double([Out] long[] ret, [In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_p2_add_or_double_affine([Out] long[] ret, [In] long[] a, + [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_p2_double([Out] long[] ret, [In] long[] a); + +public struct P2 { + internal long[] point; + + private static readonly int sz = (int)blst_p2_sizeof()/sizeof(long); + + //public P2() { point = new long[sz]; } + private P2(bool _) { point = new long[sz]; } + private P2(P2 p) { point = (long[])p.point.Clone(); } + private long[] self() + { if (point==null) point = new long[sz]; return point; } + + public P2(SecretKey sk) : this(true) + { blst_sk_to_pk_in_g2(point, sk.key); } + public P2(byte[] inp) : this(true) + { int len = inp.Length; + if (len == 0 || len != ((inp[0]&0x80) == 0x80 ? P2_COMPRESSED_SZ + : 2*P2_COMPRESSED_SZ)) + throw new Exception(ERROR.BAD_ENCODING); + ERROR err = blst_p2_deserialize(point, inp); + if (err != ERROR.SUCCESS) + throw new Exception(err); + blst_p2_from_affine(point, point); + } + public P2(P2_Affine affine) : this(true) + { blst_p2_from_affine(point, affine.point); } + + public P2 dup() { return new P2(this); } + public P2_Affine to_affine() { return new P2_Affine(this); } + public byte[] serialize() + { byte[] ret = new byte[2*P2_COMPRESSED_SZ]; + blst_p2_serialize(ret, point); + return ret; + } + public byte[] compress() + { byte[] ret = new byte[P2_COMPRESSED_SZ]; + blst_p2_compress(ret, point); + return ret; + } + + public bool on_curve() { return blst_p2_on_curve(point); } + public bool in_group() { return blst_p2_in_g2(point); } + public bool is_inf() { return blst_p2_is_inf(point); } + public bool is_equal(P2 p) { return blst_p2_is_equal(point, p.point); } + + public P2 hash_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_hash_to_g2(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + public P2 encode_to(byte[] msg, string DST="", byte[] aug=null) + { byte[] dst = Encoding.UTF8.GetBytes(DST); + blst_encode_to_g2(self(), msg, (size_t)msg.Length, + dst, (size_t)dst.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + return this; + } + + public P2 sign_with(SecretKey sk) + { blst_sign_pk_in_g1(point, point, sk.key); return this; } + public P2 sign_with(Scalar scalar) + { blst_sign_pk_in_g1(point, point, scalar.val); return this; } + + public void aggregate(P2_Affine inp) + { if (blst_p2_affine_in_g2(inp.point)) + blst_p2_add_or_double_affine(point, point, inp.point); + else + throw new Exception(ERROR.POINT_NOT_IN_GROUP); + } + + public P2 mult(byte[] scalar) + { blst_p2_mult(point, point, scalar, (size_t)(scalar.Length*8)); + return this; + } + public P2 mult(Scalar scalar) + { blst_p2_mult(point, point, scalar.val, (size_t)255); + return this; + } + public P2 mult(BigInteger scalar) + { byte[] val; + if (scalar.Sign < 0) { + val = BigInteger.Negate(scalar).ToByteArray(); + blst_p2_cneg(point, true); + } else { + val = scalar.ToByteArray(); + } + int len = val.Length; + if (val[len-1]==0) len--; + blst_p2_mult(point, point, val, (size_t)(len*8)); + return this; + } + public P2 cneg(bool flag) { blst_p2_cneg(point, flag); return this; } + public P2 neg() { blst_p2_cneg(point, true); return this; } + public P2 add(P2 a) + { blst_p2_add_or_double(point, point, a.point); return this; } + public P2 add(P2_Affine a) + { blst_p2_add_or_double_affine(point, point, a.point); return this; } + public P2 dbl() + { blst_p2_double(point, point); return this; } + + public static P2 generator() + { var ret = new P2(true); + Marshal.Copy(blst_p2_generator(), ret.point, 0, ret.point.Length); + return ret; + } +} + +public static P2 G2() { return P2.generator(); } + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_aggregated_in_g2([Out] long[] fp12, [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_aggregate_pk_in_g2([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_mul_n_aggregate_pk_in_g2([In, Out] long[] fp12, + [In] long[] pk, [In] long[] sig, + [In] byte[] scalar, size_t nbits, + [In] byte[] msg, size_t msg_len, + [In] byte[] aug, size_t aug_len); + + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_fp12_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_miller_loop([Out] long[] fp12, [In] long[] q, + [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_is_one([In] long[] fp12); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_is_equal([In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_fp12_sqr([Out] long[] ret, [In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_fp12_mul([Out] long[] ret, [In] long[] a, + [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_final_exp([Out] long[] ret, [In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_finalverify([In] long[] a, [In] long[] b); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_fp12_one(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_fp12_in_group([In] long[] a); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_bendian_from_fp12([Out] byte[] ret, [In] long[] a); + +public struct PT { + internal long[] fp12; + + private static readonly int sz = (int)blst_fp12_sizeof()/sizeof(long); + + internal PT(bool _) { fp12 = new long[sz]; } + private PT(PT orig) { fp12 = (long[])orig.fp12.Clone(); } + + public PT(P1_Affine p) : this(true) + { blst_aggregated_in_g1(fp12, p.point); } + public PT(P1 p) : this(true) + { blst_aggregated_in_g1(fp12, (new P1_Affine(p)).point); } + public PT(P2_Affine q) : this(true) + { blst_aggregated_in_g2(fp12, q.point); } + public PT(P2 q) : this(true) + { blst_aggregated_in_g2(fp12, (new P2_Affine(q)).point); } + public PT(P2_Affine q, P1_Affine p) : this(true) + { blst_miller_loop(fp12, q.point, p.point); } + public PT(P1_Affine p, P2_Affine q) : this(q, p) {} + public PT(P2 q, P1 p) : this(true) + { blst_miller_loop(fp12, (new P2_Affine(q)).point, + (new P1_Affine(p)).point); + } + public PT(P1 p, P2 q) : this(q, p) {} + + public PT dup() { return new PT(this); } + public bool is_one() { return blst_fp12_is_one(fp12); } + public bool is_equal(PT p) + { return blst_fp12_is_equal(fp12, p.fp12); } + public PT sqr() { blst_fp12_sqr(fp12, fp12); return this; } + public PT mul(PT p) { blst_fp12_mul(fp12, fp12, p.fp12); return this; } + public PT final_exp() { blst_final_exp(fp12, fp12); return this; } + public bool in_group() { return blst_fp12_in_group(fp12); } + public byte[] to_bendian() + { byte[] ret = new byte[12*P1_COMPRESSED_SZ]; + blst_bendian_from_fp12(ret, fp12); + return ret; + } + + public static bool finalverify(PT gt1, PT gt2) + { return blst_fp12_finalverify(gt1.fp12, gt2.fp12); } + + public static PT one() + { var ret = new PT(true); + Marshal.Copy(blst_fp12_one(), ret.fp12, 0, ret.fp12.Length); + return ret; + } +} + +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern size_t blst_pairing_sizeof(); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_pairing_init([In, Out] long[] ctx, bool hash_or_encode, + [In] ref long dst, size_t dst_len); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern void blst_pairing_commit([In, Out] long[] ctx); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern ERROR blst_pairing_merge([In, Out] long[] ctx, [In] long[] ctx1); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern bool blst_pairing_finalverify([In] long[] ctx, [In] long[] sig); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern +void blst_pairing_raw_aggregate([In, Out] long[] ctx, [In] long[] q, + [In] long[] p); +[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)] +static extern IntPtr blst_pairing_as_fp12([In] long[] ctx); + +public struct Pairing { + private long[] ctx; + + private static readonly int sz = (int)blst_pairing_sizeof()/sizeof(long); + + public Pairing(bool hash_or_encode=false, string DST="") + { + byte[] dst = Encoding.UTF8.GetBytes(DST); + int dst_len = dst.Length; + int add_len = dst_len!=0 ? (dst_len+sizeof(long)-1)/sizeof(long) : 1; + Array.Resize(ref dst, add_len*sizeof(long)); + + ctx = new long[sz+add_len]; + + for (int i=0; i sig, + byte[] msg, byte[] aug=null) + { return blst_pairing_aggregate_pk_in_g1(ctx, pk.point, + sig.HasValue ? sig.Value.point : null, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR aggregate(P2_Affine pk, Nullable sig, + byte[] msg, byte[] aug=null) + { return blst_pairing_aggregate_pk_in_g2(ctx, pk.point, + sig.HasValue ? sig.Value.point : null, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR mul_n_aggregate(P2_Affine pk, P1_Affine sig, + byte[] scalar, int nbits, + byte[] msg, byte[] aug=null) + { return blst_pairing_mul_n_aggregate_pk_in_g2(ctx, pk.point, sig.point, + scalar, (size_t)nbits, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + public ERROR mul_n_aggregate(P1_Affine pk, P2_Affine sig, + byte[] scalar, int nbits, + byte[] msg, byte[] aug=null) + { return blst_pairing_mul_n_aggregate_pk_in_g1(ctx, pk.point, sig.point, + scalar, (size_t)nbits, + msg, (size_t)msg.Length, + aug, (size_t)(aug!=null ? aug.Length : 0)); + } + + public void commit() { blst_pairing_commit(ctx); } + public void merge(Pairing a) + { var err = blst_pairing_merge(ctx, a.ctx); + if (err != ERROR.SUCCESS) + throw new Exception(err); + } + public bool finalverify(PT sig=new PT()) + { return blst_pairing_finalverify(ctx, sig.fp12); } + + public void raw_aggregate(P2_Affine q, P1_Affine p) + { blst_pairing_raw_aggregate(ctx, q.point, p.point); } + public void raw_aggregate(P1_Affine p, P2_Affine q) + { raw_aggregate(q, p); } + public void raw_aggregate(P2 q, P1 p) + { blst_pairing_raw_aggregate(ctx, (new P2_Affine(q)).point, + (new P1_Affine(p)).point); + } + public void raw_aggregate(P1 p, P2 q) + { raw_aggregate(q, p); } + public PT as_fp12() + { var ret = new PT(true); + GCHandle h = GCHandle.Alloc(ctx, GCHandleType.Pinned); + Marshal.Copy(blst_pairing_as_fp12(ctx), ret.fp12, 0, ret.fp12.Length); + h.Free(); + return ret; + } +} +}}