| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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. |
| */ |
| |
| /* BLS API Functions */ |
| |
| var BLS256 = function(ctx) { |
| "use strict"; |
| |
| /** |
| * Creates an instance of BLS256 |
| * |
| * @constructor |
| * @this {BLS256} |
| */ |
| var BLS256 = { |
| BLS_OK: 0, |
| BLS_FAIL: -1, |
| |
| BFS: ctx.BIG.MODBYTES, |
| BGS: ctx.BIG.MODBYTES, |
| |
| /** |
| * Convert byte array to string |
| * |
| * @this {BLS192} |
| * @parameter b byte array |
| * @return string |
| */ |
| bytestostring: function(b) { |
| var s = "", |
| len = b.length, |
| ch, i; |
| |
| for (i = 0; i < len; i++) { |
| ch = b[i]; |
| s += ((ch >>> 4) & 15).toString(16); |
| s += (ch & 15).toString(16); |
| |
| } |
| |
| return s; |
| }, |
| |
| /** |
| * Convert string to byte array |
| * |
| * @this {BLS192} |
| * @parameter s string |
| * @return byte array |
| */ |
| stringtobytes: function(s) { |
| var b = [], |
| i; |
| |
| for (i = 0; i < s.length; i++) { |
| b.push(s.charCodeAt(i)); |
| } |
| |
| return b; |
| }, |
| |
| /** |
| * hash a message to an ECP point, using SHA3 |
| * |
| * @this {BLS192} |
| * @parameter m message to be hashedstring |
| * @return ECP point |
| */ |
| bls_hashit: function(m) { |
| var sh = new ctx.SHA3(ctx.SHA3.SHAKE256); |
| var hm = []; |
| var t=this.stringtobytes(m); |
| for (var i=0;i<t.length;i++) |
| sh.process(t[i]); |
| sh.shake(hm,this.BFS); |
| var P=ctx.ECP.mapit(hm); |
| return P; |
| }, |
| |
| /** |
| * Generate key pair |
| * |
| * @this {BLS192} |
| * @parameter rng Cryptographically Secure Random Number Generator |
| * @parameter S Private key |
| * @parameter W Public key |
| * @return Error code |
| */ |
| KeyPairGenerate(rng,S,W) { |
| var G=ctx.ECP8.generator(); |
| var q=new ctx.BIG(0); |
| q.rcopy(ctx.ROM_CURVE.CURVE_Order); |
| var s=ctx.BIG.randomnum(q,rng); |
| s.toBytes(S); |
| G = ctx.PAIR256.G2mul(G,s); |
| G.toBytes(W); // To use point compression on public keys, change to true |
| return this.BLS_OK; |
| |
| }, |
| |
| /** |
| * Sign message |
| * |
| * @this {BLS192} |
| * @parameter SIG Singature |
| * @parameter m Message to sign |
| * @parameter S Private key |
| * @return Error code |
| */ |
| sign(SIG,m,S) { |
| var D=this.bls_hashit(m); |
| var s=ctx.BIG.fromBytes(S); |
| D=ctx.PAIR256.G1mul(D,s); |
| D.toBytes(SIG,true); |
| return this.BLS_OK; |
| }, |
| |
| /** |
| * Verify message |
| * |
| * @this {BLS192} |
| * @parameter SIG Signature |
| * @parameter m Message to sign |
| * @parameter W Public key |
| * @return Error code |
| */ |
| verify(SIG,m,W) { |
| var HM=this.bls_hashit(m); |
| var D=ctx.ECP.fromBytes(SIG); |
| var G=ctx.ECP8.generator(); |
| var PK=ctx.ECP8.fromBytes(W); |
| D.neg(); |
| |
| // Use new multi-pairing mechanism |
| var r=ctx.PAIR256.initmp(); |
| ctx.PAIR256.another(r,G,D); |
| ctx.PAIR256.another(r,PK,HM); |
| var v=ctx.PAIR256.miller(r); |
| |
| //.. or alternatively |
| // var v=ctx.PAIR256.ate2(G,D,PK,HM); |
| |
| v=ctx.PAIR256.fexp(v); |
| if (v.isunity()) |
| return this.BLS_OK; |
| return this.BLS_FAIL; |
| }, |
| |
| |
| /** |
| * R=R1+R2 in group G1 |
| * |
| * @this {BLS192} |
| * @parameter R1 G1 Point |
| * @parameter R2 G1 Point |
| * @parameter R G1 Point |
| * @return Error code |
| */ |
| add_G1(R1, R2, R) { |
| var P = ctx.ECP.fromBytes(R1), |
| Q = ctx.ECP.fromBytes(R2); |
| |
| if (P.is_infinity() || Q.is_infinity()) { |
| return this.INVALID_POINT; |
| } |
| |
| P.add(Q); |
| |
| P.toBytes(R,true); |
| |
| return 0; |
| }, |
| |
| /** |
| * W=W1+W2 in group G2 |
| * |
| * @this {BLS192} |
| * @parameter W1 G2 Point |
| * @parameter W2 G2 Point |
| * @parameter R G2 Point |
| * @return Error code |
| */ |
| add_G2(W1, W2, W) { |
| var P = ctx.ECP8.fromBytes(W1), |
| Q = ctx.ECP8.fromBytes(W2); |
| |
| if (P.is_infinity() || Q.is_infinity()) { |
| return this.INVALID_POINT; |
| } |
| |
| P.add(Q); |
| |
| P.toBytes(W); |
| |
| return 0; |
| } |
| |
| }; |
| |
| return BLS256; |
| }; |
| |
| if (typeof module !== "undefined" && typeof module.exports !== "undefined") { |
| module.exports = { |
| BLS256: BLS256 |
| }; |
| } |
| |
| |