mirror of
https://github.com/luxfi/blst.git
synced 2026-10-30 17:01:37 +00:00
826 lines
34 KiB
Plaintext
Executable File
826 lines
34 KiB
Plaintext
Executable File
#!/usr/bin/env python3
|
|
# Copyright Supranational LLC
|
|
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
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;
|
|
|
|
#if NET5_0_OR_GREATER
|
|
using System.Runtime.Loader;
|
|
using System.Reflection;
|
|
using System.IO;
|
|
#endif
|
|
|
|
namespace supranational { public static class blst {
|
|
|
|
#if NET5_0_OR_GREATER
|
|
private static readonly string dll;
|
|
|
|
static blst()
|
|
{
|
|
if (String.IsNullOrEmpty(dll)) {
|
|
var name = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "blst.dll"
|
|
: RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "libblst.dll.dylib"
|
|
: "libblst.dll.so";
|
|
|
|
var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
var arch = RuntimeInformation.ProcessArchitecture switch {
|
|
Architecture.X64 => "x64",
|
|
Architecture.Arm64 => "arm64",
|
|
_ => "unsupported"
|
|
};
|
|
|
|
#if NET8_0_OR_GREATER
|
|
// RuntimeInformation.RuntimeIdentifier changed between .NET 7 and 8
|
|
// and only aligns to the nuget layout in 8+
|
|
var rid = RuntimeInformation.RuntimeIdentifier;
|
|
#else
|
|
// Mimic pre-8 RuntimeInformation.RuntimeIdentifier as
|
|
// "win-x64", "linux-x64", "linux-arm64", "osx-x64", etc.
|
|
var os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win"
|
|
: RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx"
|
|
: RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD) ? "freebsd"
|
|
: "linux";
|
|
var rid = $"{os}-{arch}";
|
|
#endif
|
|
|
|
// first look for the file in the standard locations for a nuget installed native lib
|
|
dll = Path.Combine(dir, "runtimes", rid, "native", name);
|
|
|
|
if (!File.Exists(dll))
|
|
dll = Path.Combine(dir, arch, name); // try the original non-standard location
|
|
|
|
if (!File.Exists(dll))
|
|
dll = Path.Combine(Environment.CurrentDirectory, name);
|
|
|
|
if (File.Exists(dll)) {
|
|
AssemblyLoadContext.Default.ResolvingUnmanagedDll += (asm, needs) =>
|
|
(needs == "blst.dll" ? NativeLibrary.Load(dll) : IntPtr.Zero);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
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 readonly 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_keygen_v4_5([Out] byte[] key, [In] byte[] IKM, size_t IKM_len,
|
|
[In] byte[] salt, size_t salt_len,
|
|
[In] byte[] info, size_t info_len);
|
|
[DllImport("blst.dll", CallingConvention = CallingConvention.Cdecl)]
|
|
static extern
|
|
void blst_keygen_v5([Out] byte[] key, [In] byte[] IKM, size_t IKM_len,
|
|
[In] byte[] salt, size_t salt_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 keygen_v4_5(byte[] IKM, string salt, string info="")
|
|
{ if (key == null) key = new byte[32];
|
|
byte[] salt_bytes = Encoding.UTF8.GetBytes(salt);
|
|
byte[] info_bytes = Encoding.UTF8.GetBytes(info);
|
|
blst_keygen_v4_5(key, IKM, (size_t)IKM.Length,
|
|
salt_bytes, (size_t)salt_bytes.Length,
|
|
info_bytes, (size_t)info_bytes.Length);
|
|
}
|
|
public void keygen_v5(byte[] IKM, byte[] salt, string info="")
|
|
{ if (key == null) key = new byte[32];
|
|
byte[] info_bytes = Encoding.UTF8.GetBytes(info);
|
|
blst_keygen_v5(key, IKM, (size_t)IKM.Length,
|
|
salt, (size_t)salt.Length,
|
|
info_bytes, (size_t)info_bytes.Length);
|
|
}
|
|
public void keygen_v5(byte[] IKM, string salt, string info="")
|
|
{ keygen_v5(IKM, Encoding.UTF8.GetBytes(salt), info); }
|
|
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 readonly 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 readonly 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 readonly 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<add_len; i++)
|
|
ctx[sz+i] = BitConverter.ToInt64(dst, i*sizeof(long));
|
|
|
|
GCHandle h = GCHandle.Alloc(ctx, GCHandleType.Pinned);
|
|
blst_pairing_init(ctx, hash_or_encode, ref ctx[sz], (size_t)dst_len);
|
|
h.Free();
|
|
}
|
|
|
|
public ERROR aggregate(P1_Affine pk, Nullable<P2_Affine> 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<P1_Affine> 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'
|
|
|
|
|
|
def newer(files):
|
|
if len(files) == 1:
|
|
return True
|
|
rh = files[-1]
|
|
if not os.path.exists(rh):
|
|
return True
|
|
for lh in files[:-1]:
|
|
if os.stat(lh).st_ctime > os.stat(rh).st_ctime:
|
|
return True
|
|
return False
|
|
|
|
|
|
fname = "supranational.blst.cs"
|
|
if newer([here[-1], fname]):
|
|
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'((?<!f)[pgPG])([12])', xchg_1vs2, middle), file=fd)
|
|
print(bottom, file=fd)
|
|
fd.close()
|
|
|
|
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)
|