Git Product home page Git Product logo

core's Introduction

The MIRACL Core Cryptographic Library

Build Status

The original contribution to the Apache Milagro Cryptographic Library (AMCL) has now been extended and is being re-released as MIRACL Core.

MIRACL Core is a multi-lingual and architecturally agnostic cryptographic library that supports elliptic curve cryptography, pairing-friendly curve cryptography, RSA, AES symmetric encryption and hash functions. It is designed from the ground up with side-channel attack resistance in mind. Multiple curves can be supported in a single application.

All code is entirely in the supported high-level languages. No assembly language and no third party code is required - these libraries are completely self-contained. MIRACL Core is currently available in the C, C++, Go, Rust, Python, Java, Javascript and Swift programming languages. Via code translators it can be easily translated to other languages (like WebAssembly and C#). It is particularly suitable for smaller devices such as those supported by Arduino infrastructure.

MIRACL Core features several extensions over the stock Milagro Cryptographic Library.

  • Easy to use and flexible Threshold Secret Sharing module added (see share.c, share.cpp, SHARE.java etc.)

  • Example program to track test vectors from https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/

  • Curves SM2, BN462, BLS48581, C13318, JUBJUB, X448, SECP160R1, C1174, BLS48286, TWEEDLEDUM, TWEEDLEDEE

  • Support for precomputation for pairings (see BLS API)

  • Performance and security improvements

  • New HMAC message authentication module (KDFs, HMAC, HKDF_Extract/Expand, XOF_Expand, XMD_Expand)

  • Improved side-channel resistance

  • Deterministic hashing to curve points map2point (Elligator, SVDW, SSWU)

  • Point compression in G2

  • Demonstrated support for low-powered IoT processor nodes (ARM Cortex-M0/M4, MIPS32, RISC-V, ESP32)

  • Emerging-standards-compliant implementation of BLS signature

  • Emerging-standards-compliant implementation of HPKE (Hybrid Public Key Encryption)

  • Emerging-standards-compliant implementation of deterministic Hash-To-Curve

Doxygen generated documentation for the C version of the library can be created by simply executing doxygen inside of the C directory. The C++ code is probably the best commented.

Install Python 3 and suitable compilers for each language of interest to you. Python 3 scripts are used to build the libraries from the command line for each of the supported languages. If using windows, set a command alias via

DOSKEY python3 = py $*

For a quick start, try out the Python version of the library, and run our sample programs

core's People

Contributors

arvvai avatar bitdivine avatar blynn avatar burkh4rt avatar cryptomathician avatar daniel-bloom-dfinity avatar douganderson444 avatar felix avatar kwvg avatar lovesh avatar mcarrickscott avatar rillian avatar toranova avatar vigneswaran avatar wip-abramson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

core's Issues

Adding support for more curves with different security levels

Hi,

I have been going through the code and wanted to add more curves but saw that it would require a lot of files which could clutter up soon, is that a good approach or did I get it wrong?
Do the authors of the library plan to add more curves too?

FP256BN Plus and math.MaxInt64

The following test

import (
	"math"
	"math/rand"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestMaxInt(t *testing.T) {
	r1 := int(rand.Int63())
	r2 := int(rand.Int63())

	i1 := FP256BN.NewBIGint(math.MaxInt64 - r1)
	i2 := FP256BN.NewBIGint(r1)
	i3 := FP256BN.NewBIGint(math.MaxInt64 - r2)
	i4 := FP256BN.NewBIGint(r2)
	i5 := FP256BN.NewBIGint(2)

	i6 := i1.Plus(i2).Plus(i3).Plus(i4).Plus(i5)

	zero := FP256BN.NewBIGint(0)

	assert.NotEqual(t, zero, i6)
}

fails whereas it looks like it should be succeeding. The test was conducted with go version go1.14.4 linux/amd64 against the curve

32. FP256BN

generated by config64.py (git revision 5387e6a895243dde0).

JS library doesn't compile

I noticed there is no CI running for JavaScript, and the code there doesn't compile.

Most of the errors are easy to fix, but I don't know the right fix for islarger function in fp.js. (fx doesn't exist)

--- a/javascript/src/bls.js
+++ b/javascript/src/bls.js
@@ -56,7 +56,7 @@ var BLS = function(ctx) {
             return b;
         },

-        stringtobytes: function(str) {
+        stringtobytes: function(s) {
             var b = [],
                 i;
--- a/javascript/src/ecp2.js
+++ b/javascript/src/ecp2.js
@@ -179,7 +179,7 @@ var ECP2 = function(ctx) {
             W.affine();
                    W.x.toBytes(t);

-            if ((ctx.FP.MODBITS-1)%8<=4 && ECP.ALLOW_ALT_COMPRESS) alt=true;
+            if ((ctx.FP.MODBITS-1)%8<=4 && ctx.ECP.ALLOW_ALT_COMPRESS) alt=true;
@@ -628,7 +628,7 @@ var ECP2 = function(ctx) {
         var typ= b[0];
         var P = new ECP2();

-        if ((ctx.FP.MODBITS-1)%8<=4 && ECP.ALLOW_ALT_COMPRESS) alt=true;
+        if ((ctx.FP.MODBITS-1)%8<=4 && ctx.ECP.ALLOW_ALT_COMPRESS) alt=true;
--- a/javascript/src/fp2.js
+++ b/javascript/src/fp2.js
@@ -55,9 +55,9 @@ var FP2 = function(ctx) {

         islarger: function() {
             if (this.iszilch()) return 0;
-            var cmp=this.b.larger();
+            var cmp=this.b.islarger();
             if (cmp!=0) return cmp;
-            return this.a.larger();
+            return this.a.islarger();
         },

ECP2 multiply by FP in golang?

Hi there,

I'm looking through ECP2.go, we need a way to multiply ECP2 struct with a FP. What is the general way to do this?

Already tried this and it didn't work: func (E *ECP2) mul(e *BIG) *ECP2 { along with a GetBIG getter:

func (F *FP) GetBIG() *BIG {
	F.reduce()
	return F.redc()
}

I'm willing to contribute the code for it as long as I can see it'll be straightforward.

Can not build in cpp

i created a hole new folder and copy cpp to it, run python3 config32.py, and then follow the instruction. when i run g++ -O2 testall.cpp core.a -o testall. the error shows:testall.cpp:43:10:
fatal error: mpin_BLS12383.h: No such file or directory
43 | #include "mpin_BLS12383.h"
| ^~~~~~~~~~~~~~~~~

pow(0) crash

Raising an element of bls12381::FP12 to the power of 0 crashes.

For example:

extern crate core;
use core::bls12381::fp12::FP12;
use core::bls12381::big::BIG;

fn main() {
    let mut g = FP12::new();
    g.one();
    let mut z = BIG::new();
    z.one();
    println!("{}", g.pow(&z).tostring());
    z.zero();
    println!("{}", g.pow(&z).tostring());
}

crashes on the last line with:

thread 'main' panicked at 'index out of bounds: the len is 7 but the index is 318047311615681924', src/bls12381/big.rs:526:13

Reporting security issues

I noticed several side channels in the Rust version of the code during an audit. There is no indication in the readme how such issues should be reported. Should I just create an issue or would you prefer some form of private communication?

Rust: incorrect normalization for 1*1 in FP12.

Computing 1*1 in FP12 results in something that tests equal to 1, but is incorrectly normalized.

extern crate core;
use core::bls12381::fp12::FP12;

fn main() {
    let mut x = FP12::new();
    x.one();
    println!("x: {}", x.tostring());

    let mut y = FP12::new();
    y.one();
    y.mul(&x);
    println!("y: {}", y.tostring());

    // Returns true, as expected.
    println!("{}", y.equals(&x));

    // Should return true, but returns false.
    println!("{}", y.tostring() == x.tostring());
}

Output:

x: [[[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000],[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]],[[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000],[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]],[[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000],[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]]]
y: [[[000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB],[1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB]],[[1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB],[1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB]],[[1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB],[1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB,1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB]]]
true
false

Fused sqrt and invsqrt

I've noticed that you integrated hash-to-G2 from the H2C draft and are computing sqrt and invsqrt in a separate manner here:

core/c/fp2.c

Lines 456 to 458 in bed0047

FP_YYY_sqrt(&(w->a),&w2,&hint); // a=sqrt(w2)
FP_YYY_inv(&w3,&w2,&hint); // w3=1/w2
FP_YYY_mul(&w3,&w3,&(w->a)); // w3=1/sqrt(w2)

Instead you can compute sqrt and invsqrt in a fused manner by modifying your Tonelli Shanks algorithm by not multiplying Line 799

core/c/fp.c

Lines 782 to 817 in bed0047

void FP_YYY_sqrt(FP_YYY *r, FP_YYY *a, FP_YYY *h)
{
int i,j,k,u,e=PM1D2_YYY;
FP_YYY v,g,t,b;
BIG_XXX m;
if (h==NULL)
FP_YYY_progen(&g,a);
else
FP_YYY_copy(&g,h);
BIG_XXX_rcopy(m,ROI_YYY);
FP_YYY_nres(&v,m);
FP_YYY_sqr(&t,&g);
FP_YYY_mul(&t,&t,a);
FP_YYY_mul(r,&g,a);
FP_YYY_copy(&b,&t);
for (k=e;k>1;k--)
{
for (j=1;j<k-1;j++)
FP_YYY_sqr(&b,&b);
u=1-FP_YYY_isunity(&b);
FP_YYY_mul(&g,r,&v);
FP_YYY_cmove(r,&g,u);
FP_YYY_sqr(&v,&v);
FP_YYY_mul(&g,&t,&v);
FP_YYY_cmove(&t,&g,u);
FP_YYY_copy(&b,&t);
}
// always return +ve square root
k=FP_YYY_sign(r);
FP_YYY_neg(&v,r); FP_YYY_norm(&v);
FP_YYY_cmove(r,&v,k);
}

Then r will hold invsqrt(a) at the end of the Tonelli Shanks, and you can multiply that by a and return both sqrt and invsqrt in a fused manner.

My own implementation (in Nim):
https://github.com/mratsim/constantine/blob/0effd66d/constantine/arithmetic/finite_fields_square_root.nim#L147-L180

func sqrt_invsqrt_tonelli_shanks[C](
       sqrt, invsqrt: var Fp[C],
       a, a_pre_exp: Fp[C]) =
  ## Compute the square_root and inverse_square_root
  ## of `a` via constant-time Tonelli-Shanks
  ##
  ## a_pre_exp is a precomputation a^((p-1-2^e)/(2*2^e))
  template z: untyped = a_pre_exp
  template r: untyped = invsqrt
  var t {.noInit.}: Fp[C]
  const e = C.tonelliShanks(twoAdicity)

  t.square(z)
  t *= a
  r = z
  var b = t
  var root = C.tonelliShanks(root_of_unity)

  var buf {.noInit.}: Fp[C]

  for i in countdown(e, 2, 1):
    for j in 1 .. i-2:
      b.square()

    let bNotOne = not b.isOne()
    buf.prod(r, root)
    r.ccopy(buf, bNotOne)
    root.square()
    buf.prod(t, root)
    t.ccopy(buf, bNotOne)
    b = t

  sqrt.prod(invsqrt, a)

Sage script for BLS12-377
https://github.com/mratsim/constantine/blob/0effd66d/sage/square_root_bls12_377.sage

def sqrt_inv_sqrt_tonelli_shanks_impl(a, a_pre_exp, s, e, root_of_unity):
    ## Square root and inverse square root for any `a` in a field of prime characteristic p
    ##
    ## a_pre_exp = a^((q-1-2^e)/(2*2^e))
    ## with
    ##  s and e, precomputed values
    ##  such as q == s * 2^e + 1

    # Implementation
    # 1/โˆša * a = โˆša
    # Notice that in Tonelli Shanks, the result `r` is bootstrapped by "z*a"
    # We bootstrap it instead by just z to get invsqrt for free

    z = a_pre_exp
    t = z*z*a
    r = z
    b = t
    root = root_of_unity
    for i in range(e, 1, -1):   # e .. 2
        for j in range(1, i-1): # 1 .. i-2
            b *= b
        doCopy = b != 1
        r = ccopy(r, r * root, doCopy)
        root *= root
        t = ccopy(t, t * root, doCopy)
        b = t
    return r*a, r

select indepentent generator with node js

Hey,

I need to select two independent generators from the curve.
How can I select them? If I use the generator function from ecp I always get the same points.
I this maybe e bug or i miss an initialisation?

This is the code i used.

let g = ctx.ECP.generator(); const g_Bytes = []; g.toBytes(g_Bytes, true);

For the second one i used:

let u = ctx.ECP.generator(); const u_Bytes = []; u.toBytes(u_Bytes, true);

ECP::muln() bug?

I may be using the API wrongly, but I think the 3 print statements in the following program should agree:

extern crate core;
use core::bls12381::ecp::ECP;
use core::bls12381::big::BIG;
use std::vec::Vec;

fn main() {
    let g1 = ECP::generator();
    let x = BIG::new_int(1);

    let mut ps = Vec::new();
    ps.push(g1.clone());

    let mut xs = Vec::new();
    xs.push(x.clone());

    println!("g1: {}", g1.tostring());
    println!("mul: {}", g1.mul(&x).tostring());
    println!("muln: {}", ECP::muln(1, &ps, &xs).tostring());
}

However, I got:

g1: (17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB,08B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1)
mul: (17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB,08B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1)
muln: (0572CBEA904D67468808C8EB50A9450C9721DB309128012543902D0AC358A62AE28F75BB8F1C7C42C39A8C5529BF0F4E,166A9D8CABC673A322FDA673779D8E3822BA3ECB8670E461F73BB9021D5FD76A4C56D9D4CD16BD1BBA86881979749D28)

BLS: bug in Rust implementation?

I am trying to verify the following signature with BLS12381 and domain separator BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_, without the multi-pairing mechanism and enabling ALLOW_ALT_COMPRESS.

The same test passed in C, but I get BLS_FAIL in Rust.

#[test]
fn bls_verify() {
    use bls12381::bls::{core_verify, init, BLS_OK};
    let pk = hex::decode("a7623a93cdb56c4d23d99c14216afaab3dfd6d4f9eb3db23d038280b6d5cb2caaee2a19dd92c9df7001dede23bf036bc0f33982dfb41e8fa9b8e96b5dc3e83d55ca4dd146c7eb2e8b6859cb5a5db815db86810b8d12cee1588b5dbf34a4dc9a5").unwrap();
    let sig = hex::decode("b89e13a212c830586eaa9ad53946cd968718ebecc27eda849d9232673dcd4f440e8b5df39bf14a88048c15e16cbcaabe").unwrap();
    let msg = "hello".to_owned().into_bytes();
    assert_eq!(init(), BLS_OK);
    assert_eq!(core_verify(&sig, &msg, &pk), BLS_OK);
}

Here is how I generate the library: https://github.com/dfinity/agent-rs/blob/6831121ce0963348346059a98d39c57786a8e9ca/ic-agent/src/bls/README.md

I think I'm patching the right code (see my last item in the README.md above), but the test still fails. Maybe something wrong in the Rust implementation of ALLOW_ALT_COMPRESS?

Attack against M-PIN

I believe I have a potential security attack against M-PIN. Since I don't want to post here, where should I post it to discuss?

Compiling for Cortex-A9

Hello, when I try to compile for Cortex-A9 with the following toolchain arm-linux-gnueabihf-gcc as:
arm-linux-gnueabihf-gcc -mcpu=cortex-a9 -static -O2 testecc.c core.a -o testecc
I have an error like this:

/usr/lib/gcc-cross/arm-linux-gnueabihf/9/../../../../arm-linux-gnueabihf/bin/ld: core.a: error adding symbols: file format not recognized
collect2: error: ld returned 1 exit status

Any suggestion to solve this issue?

BLS domain separator wrong?

I created the bls code I am using by selecting BLS12381 (option 31 in the config), but in order for this to work with another implementation of BLS, I had to make the following change

@@ -67,7 +67,7 @@ static void BLS_HASH_TO_POINT(ECP_BLS12381 *P, octet *M)
     char dst[50];
     octet DST = {0,sizeof(dst),dst};
 
-    OCT_jstring(&DST,(char *)"BLS_SIG_BLS12381G1_XMD:SHA256-SVDW-RO-_NUL_");
+    OCT_jstring(&DST,(char *)"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_");
     hash_to_field(MC_SHA2,HASH_TYPE_BLS12381,u,&DST,M,2);
 
     ECP_BLS12381_map2point(P,&u[0]);

I donโ€™t fully know what that means, only that https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04 mentions the later form (underscores instead of dashes, a dash in SHA-256, SSWU onstead of SVDW).

modmul may not be working correctly in 32 bit mode

When I run BIG::modmul in 64 bit mode and 32 bit mode I get two completely different answers when using the same inputs. I'm using the BLS12-381 curve. I'm using the Rust language but I don't think it will matter since all the code is the same across any of the languages.

Code

let a = BIG::fromstring("03164AC7F227DEDC0EDD67E176F3545F8494809650112DD9A3D6267DF473F75B67DA3490BADA63B1E35AC5FAC2164FCB".to_string());

let b = BIG::fromstring("0793154FD85631D966EF2470460C78F6A928AE9F5BDBFAC21DF3D753AA278BA751CDFCF95A84188E29D670675E4C9C7C".to_string());

let MODULUS = BIG::fromstring("1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB".to_string());

let mut x = BIG::modmul(&a, &b, &MODULUS);
println!("x = {}", x.to_hex());

In 64-bit mode I get x=05015FA6469760BFA6D7899FF58062B3CD2BDEDE551B237EA06E49EA2528AEE6F3BF2AB340785206041A56B17E6C317F

In 32-bit mode I get
x=1782F7D00F6793C274488FF042468F7ACDE8B3971718756AB101076FBDCDDA4CB8EB7225425F243B24D059882A6D2DFC

Am I doing something wrong here? The only difference is the architecture I'm targeting.

Javascript ecp2 toBytes functions gives not the same bytes as in the Java implementation

Hi,

I have an ECP2 object in Java which is represented by the following string

([136bcbb1223d222a31d2f061371bfdb3c767eab89bc93891a05c20f553b0760c2338c488510403d0c79246325a11b4f1d7c7ba7d5ca511e45a0f,0aa14639fa52f98d0086b171ecd57308243d4576629bc251f470a4fba78b443516e78b3c3ebab0763eec0497f82e67aac35ff4920aef1c90ccb7],[076f7c78c7965f9a723eed6cd0e4961c612147ee0951967a3a444a8cb899dbbd48471e08578ae8b79526d37abaf4a75b40495be81233328346e6,141b1164820f78687ff9ed73b3667955ff3a81b7951774a559295d72dd62a0ea8c3c626f100fec2c2a2010c8d459b293d5c0c2dbf3565d19f099])

Another ECP2 Object in JavaScript is represented by the same string. From my understanding now it should be the same object, also the internal structure is maybe a bit different?!
However, I get not the same byte array out of the object when I use the toBytes method.
I get the following byte arrays:

[19, 107, -53, -79, 34, 61, 34, 42, 49, -46, -16, 97, 55, 27, -3, -77, -57, 103, -22, -72, -101, -55, 56, -111, -96, 92, 32, -11, 83, -80, 118, 12, 35, 56, -60, -120, 81, 4, 3, -48, -57, -110, 70, 50, 90, 17, -76, -15, -41, -57, -70, 125, 92, -91, 17, -28, 90, 15, 10, -95, 70, 57, -6, 82, -7, -115, 0, -122, -79, 113, -20, -43, 115, 8, 36, 61, 69, 118, 98, -101, -62, 81, -12, 112, -92, -5, -89, -117, 68, 53, 22, -25, -117, 60, 62, -70, -80, 118, 62, -20, 4, -105, -8, 46, 103, -86, -61, 95, -12, -110, 10, -17, 28, -112, -52, -73, 7, 111, 124, 120, -57, -106, 95, -102, 114, 62, -19, 108, -48, -28, -106, 28, 97, 33, 71, -18, 9, 81, -106, 122, 58, 68, 74, -116, -72, -103, -37, -67, 72, 71, 30, 8, 87, -118, -24, -73, -107, 38, -45, 122, -70, -12, -89, 91, 64, 73, 91, -24, 18, 51, 50, -125, 70, -26, 20, 27, 17, 100, -126, 15, 120, 104, 127, -7, -19, 115, -77, 102, 121, 85, -1, 58, -127, -73, -107, 23, 116, -91, 89, 41, 93, 114, -35, 98, -96, -22, -116, 60, 98, 111, 16, 15, -20, 44, 42, 32, 16, -56, -44, 89, -78, -109, -43, -64, -62, -37, -13, 86, 93, 25, -16, -103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

and as an Array in JavaScript

[4,10,161,70,57,250,82,249,141,0,134,177,113,236,213,115,8,36,61,69,118,98,155,194,81,244,112,164,251,167,139,68,53,22,231,139,60,62,186,176,118,62,236,4,151,248,46,103,170,195,95,244,146,10,239,28,144,204,183,19,107,203,177,34,61,34,42,49,210,240,97,55,27,253,179,199,103,234,184,155,201,56,145,160,92,32,245,83,176,118,12,35,56,196,136,81,4,3,208,199,...]

As an Int8Array I get:

{
  "0": 4,
  "1": 10,
  "2": -95,
  "3": 70,
  "4": 57,
  "5": -6,
  "6": 82,
  "7": -7,
  "8": -115,
  "9": 0,
  "10": -122,
  "11": -79,
  "12": 113,
  "13": -20,
  "14": -43,
  "15": 115,
  "16": 8,
  "17": 36,
  "18": 61,
  "19": 69,
  "20": 118,
  ...
}

This seems to me a bit weird if I assume that both objects are the "same" in the sense that both objects represents the same ECP2 object x. I tried the following code in JavaScript:

let rawBytes = new Array(12*ctx.BIG.MODBYTES);
x.toBytes(rawBytes)

In Java the same code is:

byte[] rawBytes = new byte[CONFIG_BIG.MODBYTES*12];
x.toBytes(rawBytes);

with x is of type ECP2.
Is there a chance that these objects are not the same or is there any bug in the toBytes() function in JavaScript? Or maybe I missed something else?

Thank you in advance!

Support go modules

As new releases of Go enable by default Go modules, it would be good to migrate current Go library to go mod specification

Bug with BIG.mod in Java?

Hello, I am using the Java version of the library (in particular, selecting only curve BLS461 for compilation) and I am having trouble with modular arithmetic.

The "mod" operation in BIG crashes (infinte loop) when using it on a "negative" BIG. For example, the following test will not finish:

public void test(){
        BIG b=new BIG(1);
        b.sub(new BIG(20));
        b.mod(new BIG(ROM.CURVE_Order));
}

Using debugger, it seems to be stuck in the loop:

            do {
                m.fshl(1);
                ++k;
            } while(comp(this, m) >= 0);

in mod method of (decompiled) class org\miracl\core\BLS12461\BIG.class

I think this falls within normal use, but in any case getting an infinite loop seems like a weird occurence even if something is wrong.

golang: Signature Recover function using FP, ECP

Hello, got the Recover code working. This is what it looks like!

Just trying to be helpful. Totally fine if you want to close this issue immediately. Or maybe I did it wrong, I should've done another way of sharing with you the port of herumi/bls we did?

func (sig *Sign) Recover(shares []Sign, from []ID) error {
	if len(shares) == 0 {
		return errors.New("Need at least one share.")
	}

	if len(shares) == 1 {
		sig.v.Copy(shares[0].v)
		return nil
	}

	a := from[0]
	for i := 1; i < len(from); i++ {
		a.Modmul(&from[i])
	}

	// TODO: Return error if 'id' is 0.

	r := BN254.NewECP() // 'r' is the ECP to recover.
	for i := 0; i < len(shares); i++ {
		b := from[i].v.GetBIG()
		for j := 0; j < len(from); j++ {
			if i != j {
				sj := from[j].v.GetBIG()
				si := from[i].v.GetBIG()

				var x, y *BN254.BIG
				c := BN254.Comp(sj, si)
				if c > 0 {
					x = sj
					y = si
				} else if c < 0 {
					x = si
					y = sj
				} else if c == 0 {
					return errors.New("Can't recover signature.")
				}

				// IMPORTANT NOTE: this Sub operation MUST return a positive BIG, or
				// else in the "Modmul", miracl/core gets stuck in an infinite loop.
				// That is why we did the earlier "Comp" to make sure x > y
				//
				// Generally, miracl/core makes the assumption that results are
				// positive.
				x.Sub(y)

				b = Modmul(b, x)
			}
		}

		_a := a.v.GetBIG()
		_a.Div(b)
		t := BN254.G1mul(shares[i].v, _a) // G::mul(shares[i], a/b)
		r.Add(t) // G::add(r, t) // r += t
	}

	sig.v = r

	return nil
}

AMCL JS ECDSA Key data structure and signing procedure

Hi,
in my example I want to create a key pair for ECDSA from a given byte seed and was searching for a data structure which holds the key pair and the keys in the library.
I am not sure, but it seems that it don't exist such a data structure right?
Should it not exist is it possible to add a data structure for it like for the RSA keys in rsa.js?
I was thinking about an object like KeyPair (Java) or something similar.

Thank you in advance!

Pascal

AMCL JS create rsa_public_key from ASN1 formatted X.509 public key.

I want to create a RSA public key from a X.509 formatted RSA public key.

Is it possible to use the ASN.1/X.509 format directly to create a rsa_public_key?
If that shouldn't be the case (it seems that it isn't the case), is it possible to set the modulus properly? I think that should be possible, but I am not sure how it will works, cause of the FF and BIG prototype/class which I am maybe not fully understand in detail yet (or I have missed something). Could you help me to understand how I can set the modulus in the correct way? Or better to say to create a proper n to set it correctly

If possible to create a proper n it would be nice to do something like:

var pub = new ctx.rsa_public_key(ctx.FF.FFLEN);
pub.n.copy(n);
pub.e.copy(65537);

Cause I want to create a public key with known e and n.

Thank you in advance!

Pascal

G2mul for ECP? (Golang)

Hi, so sorry to trouble you again with another question.

It's possible I might have missed something. I frequently make these kinds of mistake when looking at unfamiliar code.

Right now the G2mul function in PAIR.go is for ECP2

I don't think I see a corresponding one for ECP?

This is to implement "Recover" (core/SHARE.go), which is Lagrange interpolation over FP and ECP.

The corresponding source in herumi/bls is: https://github.com/herumi/mcl/blob/0114a3029f74829e79dc51de6dfb28f5da580632/include/mcl/lagrange.hpp#L11 where "F" is FP and "G" is ECP.

BLS: ZCash-style curve point encodings?

I noticed that miracl encodes BLS public keys and signatures using the SEC-style compressed format (leading 0x02 or 0x03 depending on parity of y coordinate, followed by x coordinate). The RFC draft for BLS, however, suggests a different encoding, using the spare top 3 bits of the 48/96 bytes, according to the scheme described at https://github.com/zkcrypto/bls12_381/blob/bc1706f6426aca52b9a99e5f100bdb7d119305d3/src/notes/serialization.rs.

Do you have plans to support that encoding in miracl, too?

core/java: ECP compression

I am using ED25519 from core/java.
When an ECP point P = (x,y) is encoded into bytes (toBytes(byte[] b, boolean compress)) with compress set to true, it does not always decompress into an ECP with the same y value, i.e., it gives P' = (x, y'). A sample of ECP compression/decompression I have:

Original P: 
(40ccd876746fb401023a49469c0b7f52725ec08e2b6e3ed15af0a90f445dc129,6e313f6097112eefbeeefc4ab187e32f0a00a963332a695540be983cd4798e92)

Compressed and decompressed P: 
(40ccd876746fb401023a49469c0b7f52725ec08e2b6e3ed15af0a90f445dc129,ee313f6097112eefbeeefc4ab187e32f0a00a963332a695540be983cd4798e7f)

where only the first byte and the last byte of y and y' are different.

However, I noticed the point multiplication for both gives the same R = rP = rP'.
My workaround is to call mul(new BIG(1)) so the decompressed ECP always returns the same P.

May I know if is this the supposed way to perform point compression/decompression?
Clarification is appreciated, thanks!

Node.js support

Hello,
I wanted to use the Javascript part of the library for my project in React and did some exports of the function to bundle them into a Node.js package, including index.js and package.json, to import them into my React project as a Node.js package. Is there any chance that this could be useful in this repository or is there any planing for a Node.js package for this library which will be maintained?
I saw a version of the old library in npm, but this isn't maintained anymore.

In the time were I added the exports, I found some minor bugs.

Minor Bugs:
In the file fp2.js in row 137: should be ctx.FP.BIG_ENDIAN_SIGN instead of FP.BIG_ENDIAN_SIGN.
In the file fp.js in row 32: should be x instanceof ctx.BIG instead of x instanceof BIG.

I don't know why Javascript don't say anything about it, but Node.js told me that the ctx part is necessary.

Thank you in advance!

Pairing Example with JS

Hello folks,
I miss an example for paring of two groups with the miracl javascript version or isnt it implemented in this version?
In the src code of the js variante I found three classes I guess.

Thanks for your answers and best regrets!

secp256r1

Hey, is secp256r1 supported? I dont find it defined in config64.py

core/python could be structured more like a Python module

After running config.py to configure the curves you want to use, if you want to build a module that relies on any of the curves and then write any code depending on that module, the dependencies are currently a little clunky.

In my case, I ended up copying each of the curve directories created by config.py to my project and put an __init__.py file inside each of the folders so that I could install each curve as a Python module. I also had to copy the constants.py file to any folder with code that relied on any of the configured elliptic curves. The example structure below is what I used. In the example, assume that module_code.py depends on bn254 and that test.py relies on module_code.py.

project
|       bn254
|       |        __init__.py
|       |        big.py
...
|       module
|       |       __init__.py
|       |       module_code.py
...
|       test
|       |       constants.py
|       |       test.py

If config.py could allow you to install the curves and any necessary constants as modules, it would be much easier to use in combination with other projects.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.