/* * Copyright (c) 2012-2020 MIRACL UK Ltd. * * This file is part of MIRACL Core * (see https://github.com/miracl/core). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Boneh-Lynn-Shacham signature 256-bit API Functions */ /* Loosely (for now) following https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-02 */ // Minimal-signature-size variant package bls48581 import "source.quilibrium.com/quilibrium/ceremonyclient/ec/bls48581/core" //import "fmt" const BFS int = int(MODBYTES) const BGS int = int(MODBYTES) const BLS_OK int = 0 const BLS_FAIL int = -1 var G2_TAB []*FP16 func ceil(a int, b int) int { return (((a)-1)/(b) + 1) } /* output u \in F_p */ func hash_to_field(hash int, hlen int, DST []byte, M []byte, ctr int) []*FP { q := NewBIGints(Modulus) nbq := q.nbits() L := ceil(nbq+AESKEY*8, 8) var u []*FP var fd = make([]byte, L) OKM := core.XMD_Expand(hash, hlen, L*ctr, DST, M) for i := 0; i < ctr; i++ { for j := 0; j < L; j++ { fd[j] = OKM[i*L+j] } u = append(u, NewFPbig(DBIG_fromBytes(fd).ctmod(q, uint(8*L-nbq)))) } return u } /* hash a message to an ECP point, using SHA2, random oracle method */ func bls256_hash_to_point(M []byte) *ECP { DST := []byte("BLS_SIG_BLS48581G1_XMD:SHA-512_SVDW_RO_NUL_") u := hash_to_field(core.MC_SHA2, HASH_TYPE, DST, M, 2) P := ECP_map2point(u[0]) P1 := ECP_map2point(u[1]) P.Add(P1) P.Cfp() P.Affine() return P } func Init() int { G := ECP8_generator() if G.Is_infinity() { return BLS_FAIL } G2_TAB = precomp(G) return BLS_OK } /* generate key pair, private key S, public key W */ func KeyPairGenerate(IKM []byte, S []byte, W []byte) int { r := NewBIGints(CURVE_Order) nbr := r.nbits() L := ceil(3*ceil(nbr, 8), 2) LEN := core.InttoBytes(L, 2) AIKM := make([]byte, len(IKM)+1) for i := 0; i < len(IKM); i++ { AIKM[i] = IKM[i] } AIKM[len(IKM)] = 0 G := ECP8_generator() if G.Is_infinity() { return BLS_FAIL } SALT := []byte("BLS-SIG-KEYGEN-SALT-") PRK := core.HKDF_Extract(core.MC_SHA2, HASH_TYPE, SALT, AIKM) OKM := core.HKDF_Expand(core.MC_SHA2, HASH_TYPE, L, PRK, LEN) dx := DBIG_fromBytes(OKM[:]) s := dx.ctmod(r, uint(8*L-nbr)) s.ToBytes(S) // SkToPk G = G2mul(G, s) G.ToBytes(W, true) return BLS_OK } /* Sign message m using private key S to produce signature SIG */ func Core_Sign(SIG []byte, M []byte, S []byte) int { D := bls256_hash_to_point(M) s := FromBytes(S) D = G1mul(D, s) D.ToBytes(SIG, true) return BLS_OK } /* Verify signature given message M, the signature SIG, and the public key W */ func Core_Verify(SIG []byte, M []byte, W []byte) int { HM := bls256_hash_to_point(M) D := ECP_fromBytes(SIG) if !G1member(D) { return BLS_FAIL } D.Neg() PK := ECP8_fromBytes(W) if !G2member(PK) { return BLS_FAIL } // Use new multi-pairing mechanism r := Initmp() Another_pc(r, G2_TAB, D) Another(r, PK, HM) v := Miller(r) //.. or alternatively // G := ECP8_generator() // if G.Is_infinity() {return BLS_FAIL} // v := Ate2(G, D, PK, HM) v = Fexp(v) if v.Isunity() { return BLS_OK } else { return BLS_FAIL } }