Skip to content

Commit

Permalink
Finish BN hash to G1 (one RO hash only) and test it
Browse files Browse the repository at this point in the history
  • Loading branch information
rheitjoh committed May 11, 2021
1 parent ea0b456 commit ed4d8da
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class BarretoNaehrigBilinearGroupImpl implements BilinearGroupImpl {
@Represented
private BarretoNaehrigTargetGroupImpl gtimpl;
@Represented
private BarretoNaehrigPointEncoding hashIntoG1impl;
private BarretoNaehrigHashToG1Impl hashIntoG1impl;
@Represented
private BarretoNaehrigPointEncoding hashIntoG2impl;

Expand Down Expand Up @@ -140,7 +140,8 @@ public BarretoNaehrigBilinearGroupImpl(BarretoNaehrigParameterSpec spec) {
default:
throw new IllegalArgumentException("Unknown hash function " + spec.hash);
}
hashIntoG1impl = new BarretoNaehrigPointEncoding(hash, g1impl);
// Why does the spec supply the hash function?
hashIntoG1impl = new BarretoNaehrigHashToG1Impl(g1impl);
hashIntoG2impl = new BarretoNaehrigPointEncoding(hash, g2impl);

/* construct new bilinearMap based on its name */
Expand Down Expand Up @@ -200,7 +201,7 @@ public BilinearMapImpl getBilinearMap() {
}

@Override
public HashIntoGroupImpl getHashIntoG1() throws UnsupportedOperationException {
public HashIntoGroupImpl getHashIntoG1() {
return this.hashIntoG1impl;
}

Expand Down Expand Up @@ -417,7 +418,7 @@ private void init(BarretoNaehrigGroup1ElementImpl P1, BarretoNaehrigGroup2Elemen
gtimpl = gT;

bilinearMapImpl = new BarretoNaehrigTatePairing(g1impl, g2impl, gT, u);
hashIntoG1impl = new BarretoNaehrigPointEncoding(g1impl);
hashIntoG1impl = new BarretoNaehrigHashToG1Impl(g1impl);
hashIntoG2impl = new BarretoNaehrigPointEncoding(g2impl);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.cryptimeleon.math.structures.groups.elliptic.type3.bn;

import org.cryptimeleon.math.hash.ByteAccumulator;
import org.cryptimeleon.math.hash.HashFunction;
import org.cryptimeleon.math.hash.impl.ByteArrayAccumulator;
import org.cryptimeleon.math.hash.impl.VariableOutputLengthHashFunction;
import org.cryptimeleon.math.serialization.Representation;
import org.cryptimeleon.math.serialization.annotations.ReprUtil;
import org.cryptimeleon.math.serialization.annotations.Represented;
import org.cryptimeleon.math.structures.groups.GroupElementImpl;
import org.cryptimeleon.math.structures.groups.mappings.impl.HashIntoGroupImpl;
import org.cryptimeleon.math.structures.rings.Field;
Expand All @@ -13,27 +13,41 @@
import org.cryptimeleon.math.structures.rings.zn.Zn;

import java.math.BigInteger;
import java.util.Objects;

/**
* Indifferentiable encoding, that is, an encoding that can be used to implement a hash function that can be used
* to replace a ROM. More general than Boneh-Franklin admissible in that regard.
*/
public class BarretoNaehrigHashToG1Impl implements HashIntoGroupImpl {
class BarretoNaehrigHashToG1Impl implements HashIntoGroupImpl {

private final BarretoNaehrigGroup1Impl group1Impl;
private final Field baseField;
private final FieldElement b;
@Represented
public BarretoNaehrigGroup1Impl group1Impl;
private Field baseField;
private FieldElement b;

private final FieldElement c1;
private final FieldElement c2;
private FieldElement c1;
private FieldElement c2;

private final HashFunction hashFunction;
private HashFunction hashFunction1;
private HashFunction hashFunction2;

public BarretoNaehrigHashToG1Impl(BarretoNaehrigGroup1Impl group1Impl) {
this.group1Impl = group1Impl;
init();
}

public BarretoNaehrigHashToG1Impl(Representation repr) {
new ReprUtil(this).deserialize(repr);
init();
}

public void init() {
b = group1Impl.getA6();
baseField = group1Impl.getFieldOfDefinition();
hashFunction = new VariableOutputLengthHashFunction((baseField.size().bitLength() - 1) / 8);
hashFunction1 = new VariableOutputLengthHashFunction((baseField.size().bitLength() - 1) / 8);
// TODO: Need an independent hash function. Using the same two functions does not fulfill that.
hashFunction2 = new VariableOutputLengthHashFunction((baseField.size().bitLength() - 1) / 8);
// c1 = sqrt{-3}
c1 = FiniteFieldTools.sqrt(baseField.getElement(-3));
// c2 = (-1 + sqrt{-3})/2
Expand All @@ -43,11 +57,18 @@ public BarretoNaehrigHashToG1Impl(BarretoNaehrigGroup1Impl group1Impl) {
@Override
public GroupElementImpl hashIntoGroupImpl(byte[] x) {
// Hashes given bytes to field element and applies SW encoding to it
ByteAccumulator accumulator = new ByteArrayAccumulator();
accumulator.append(x);
byte[] h = hashFunction.hash(accumulator.extractBytes());
BigInteger b = new BigInteger(h);
return SWEncode(baseField.getElement(b));
// Don't need any cofactor multiplication since the cofactor is always 1 for G1
// To get indifferentiability (Fouque and Tibouchi, Section 5), we need to
// calculate f(h1(m)) + f(h2(m)),
// where f is the SW encoding and h1 and h2 are independent random oracles to F_q.
byte[] h1 = hashFunction1.hash(x);
BigInteger i1 = new BigInteger(h1);
byte[] h2 = hashFunction2.hash(x);
BigInteger i2 = new BigInteger(h2);

GroupElementImpl result = SWEncode(baseField.getElement(i1)).op(SWEncode(baseField.getElement(i2)));
System.out.println(result.pow(group1Impl.getCofactor()));
return result;
}

/**
Expand All @@ -60,6 +81,10 @@ public GroupElementImpl hashIntoGroupImpl(byte[] x) {
* @param t the input
*/
private GroupElementImpl SWEncode(FieldElement t) {
if (t.isZero()) {
// f(0) = ((-1 + \sqrt{-3})/2, \sqrt{1+b}) as suggested by Fouque and Tibouchi, Section 3
return group1Impl.getElement(c2, FiniteFieldTools.sqrt(baseField.getOneElement().add(b)));
}
// w = sqrt{-3} * t/(1+b+t^2)
FieldElement w = baseField.getOneElement().add(group1Impl.getA6().add(t.pow(2))).inv().mul(t).mul(c1);
// x_1 = (-1 + sqrt{-3})/2 - tw
Expand Down Expand Up @@ -111,8 +136,21 @@ private int chi(FieldElement t) {
}
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BarretoNaehrigHashToG1Impl that = (BarretoNaehrigHashToG1Impl) o;
return Objects.equals(group1Impl, that.group1Impl);
}

@Override
public int hashCode() {
return Objects.hash(group1Impl, hashFunction1, hashFunction2);
}

@Override
public Representation getRepresentation() {
return null;
return ReprUtil.serialize(this);
}
}

0 comments on commit ed4d8da

Please sign in to comment.