All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hyperledger.fabric.sdk.idemix.IdemixIssuerPublicKey Maven / Gradle / Ivy

There is a newer version: 2.2.26
Show newest version
/*
 *
 *  Copyright 2017, 2018 IBM Corp. All Rights Reserved.
 *
 *  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.
 *
 */

package org.hyperledger.fabric.sdk.idemix;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import com.google.protobuf.ByteString;
import org.apache.milagro.amcl.FP256BN.BIG;
import org.apache.milagro.amcl.FP256BN.ECP;
import org.apache.milagro.amcl.FP256BN.ECP2;
import org.apache.milagro.amcl.RAND;
import org.hyperledger.fabric.protos.idemix.Idemix;

/**
 * IdemixIssuerPublicKey represents the idemix public key of an issuer (Certificate Authority).
 */
public class IdemixIssuerPublicKey {

    private final String[] AttributeNames;
    private final ECP Hsk;
    private final ECP HRand;
    private final ECP[] HAttrs;
    private final ECP2 W;
    private final ECP BarG1;
    private final ECP BarG2;
    private final BIG ProofC;
    private final BIG ProofS;
    private byte[] Hash = new byte[0];

    /**
     * Constructor
     *
     * @param attributeNames the names of attributes as String array (must not contain duplicates)
     * @param isk            the issuer secret key
     */
     IdemixIssuerPublicKey(String[] attributeNames, BIG isk) {
        // check null input
        if (attributeNames == null || isk == null) {
            throw new IllegalArgumentException("Cannot create IdemixIssuerPublicKey from null input");
        }

        // Checking if attribute names are unique
        Set map = new HashSet<>();
        for (String item : attributeNames) {
            if (!map.add(item)) {
                throw new IllegalArgumentException("Attribute " + item + " appears multiple times in attributeNames");
            }
        }
        final RAND rng = IdemixUtils.getRand();
        // Attaching Attribute Names array correctly
        AttributeNames = attributeNames;

        // Computing W value
        W = IdemixUtils.genG2.mul(isk);

        // Filling up HAttributes correctly in Issuer Public Key, length
        // preserving
        HAttrs = new ECP[attributeNames.length];

        for (int i = 0; i < attributeNames.length; i++) {
            HAttrs[i] = IdemixUtils.genG1.mul(IdemixUtils.randModOrder(rng));
        }

        // Generating Hsk value
        Hsk = IdemixUtils.genG1.mul(IdemixUtils.randModOrder(rng));

        // Generating HRand value
        HRand = IdemixUtils.genG1.mul(IdemixUtils.randModOrder(rng));

        // Generating BarG1 value
        BarG1 = IdemixUtils.genG1.mul(IdemixUtils.randModOrder(rng));

        // Generating BarG2 value
        BarG2 = BarG1.mul(isk);

        // Zero Knowledge Proofs

        // Computing t1 and t2 values with random local variable r for later use
        BIG r = IdemixUtils.randModOrder(rng);
        ECP2 t1 = IdemixUtils.genG2.mul(r);
        ECP t2 = BarG1.mul(r);

        // Generating proofData that will contain 3 elements in G1 (of size 2*FIELD_BYTES+1)and 3 elements in G2 (of size 4 * FIELD_BYTES)
        byte[] proofData = new byte[0];
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(t1));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(t2));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(IdemixUtils.genG2));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(BarG1));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(W));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(BarG2));

        // Hashing proofData to proofC
        ProofC = IdemixUtils.hashModOrder(proofData);

        // Computing ProofS = (ProofC*isk) + r mod GROUP_ORDER
        ProofS = BIG.modmul(ProofC, isk, IdemixUtils.GROUP_ORDER).plus(r);
        ProofS.mod(IdemixUtils.GROUP_ORDER);

        // Compute Hash of IdemixIssuerPublicKey
        byte[] serializedIpk = toProto().toByteArray();
        Hash = IdemixUtils.bigToBytes(IdemixUtils.hashModOrder(serializedIpk));
    }

    /**
     * Construct an IdemixIssuerPublicKey from a serialized issuer public key
     *
     * @param proto a protobuf representation of an issuer public key
     */
     public IdemixIssuerPublicKey(Idemix.IssuerPublicKey proto) {
        // check for bad input
        if (proto == null) {
            throw new IllegalArgumentException("Cannot create IdemixIssuerPublicKey from null input");
        }
        if (proto.getHAttrsCount() < proto.getAttributeNamesCount()) {
            throw new IllegalArgumentException("Serialized IPk does not contain enough HAttr values");
        }

        AttributeNames = new String[proto.getAttributeNamesCount()];
        for (int i = 0; i < proto.getAttributeNamesCount(); i++) {
            AttributeNames[i] = proto.getAttributeNames(i);
        }

        HAttrs = new ECP[proto.getHAttrsCount()];
        for (int i = 0; i < proto.getHAttrsCount(); i++) {
            HAttrs[i] = IdemixUtils.transformFromProto(proto.getHAttrs(i));
        }

        BarG1 = IdemixUtils.transformFromProto(proto.getBarG1());
        BarG2 = IdemixUtils.transformFromProto(proto.getBarG2());
        HRand = IdemixUtils.transformFromProto(proto.getHRand());
        Hsk = IdemixUtils.transformFromProto(proto.getHSk());
        ProofC = BIG.fromBytes(proto.getProofC().toByteArray());
        ProofS = BIG.fromBytes(proto.getProofS().toByteArray());
        W = IdemixUtils.transformFromProto(proto.getW());

        // Compute Hash of IdemixIssuerPublicKey
        byte[] serializedIpk = toProto().toByteArray();
        Hash = IdemixUtils.bigToBytes(IdemixUtils.hashModOrder(serializedIpk));
    }


    /**
     * check whether the issuer public key is correct
     *
     * @return true iff valid
     */
     public boolean check() {
        // check formalities of IdemixIssuerPublicKey
        if (AttributeNames == null || Hsk == null || HRand == null || HAttrs == null
                || BarG1 == null || BarG1.is_infinity() || BarG2 == null
                || HAttrs.length < AttributeNames.length) {
            return false;
        }

        for (int i = 0; i < AttributeNames.length; i++) {
            if (HAttrs[i] == null) {
                return false;
            }
        }

        // check proofs
        ECP2 t1 = IdemixUtils.genG2.mul(ProofS);
        ECP t2 = BarG1.mul(ProofS);

        t1.add(W.mul(BIG.modneg(ProofC, IdemixUtils.GROUP_ORDER)));
        t2.add(BarG2.mul(BIG.modneg(ProofC, IdemixUtils.GROUP_ORDER)));

        // Generating proofData that will contain 3 elements in G1 (of size 2*FIELD_BYTES+1)and 3 elements in G2 (of size 4 * FIELD_BYTES)
        byte[] proofData = new byte[0];
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(t1));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(t2));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(IdemixUtils.genG2));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(BarG1));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(W));
        proofData = IdemixUtils.append(proofData, IdemixUtils.ecpToBytes(BarG2));

        // Hash proofData to hproofdata and compare with proofC
        return Arrays.equals(IdemixUtils.bigToBytes(IdemixUtils.hashModOrder(proofData)), IdemixUtils.bigToBytes(ProofC));
    }

    /**
     * @return A proto version of this issuer public key
     */
     Idemix.IssuerPublicKey toProto() {

        Idemix.ECP[] ipkHAttrs = new Idemix.ECP[HAttrs.length];
        for (int i = 0; i < HAttrs.length; i++) {
            ipkHAttrs[i] = IdemixUtils.transformToProto(HAttrs[i]);
        }

        return Idemix.IssuerPublicKey.newBuilder()
                .setProofC(ByteString.copyFrom(IdemixUtils.bigToBytes(ProofC)))
                .setProofS(ByteString.copyFrom(IdemixUtils.bigToBytes(ProofS)))
                .setW(IdemixUtils.transformToProto(W))
                .setHSk(IdemixUtils.transformToProto(Hsk))
                .setHRand(IdemixUtils.transformToProto(HRand))
                .addAllAttributeNames(Arrays.asList(AttributeNames))
                .setHash(ByteString.copyFrom(Hash))
                .setBarG1(IdemixUtils.transformToProto(BarG1))
                .setBarG2(IdemixUtils.transformToProto(BarG2))
                .addAllHAttrs(Arrays.asList(ipkHAttrs))
                .build();
    }

    /**
     * @return The names of the attributes certified with this issuer public key
     */
     public String[] getAttributeNames() {
        return AttributeNames;
    }

    protected ECP getHsk() {
        return Hsk;
    }

    protected ECP getHRand() {
        return HRand;
    }

    protected ECP[] getHAttrs() {
        return HAttrs;
    }

    protected ECP2 getW() {
        return W;
    }

    /**
     * @return A digest of this issuer public key
     */
     public byte[] getHash() {
        return Hash;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy