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

org.hyperledger.fabric.sdk.identity.IdemixIdentity Maven / Gradle / Ivy

There is a newer version: 2.2.26
Show newest version
/*
 *
 *  Copyright 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.identity;

import java.util.Arrays;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.milagro.amcl.FP256BN.BIG;
import org.apache.milagro.amcl.FP256BN.ECP;
import org.hyperledger.fabric.protos.common.MspPrincipal;
import org.hyperledger.fabric.protos.idemix.Idemix;
import org.hyperledger.fabric.protos.msp.Identities;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.idemix.IdemixIssuerPublicKey;
import org.hyperledger.fabric.sdk.idemix.IdemixSignature;
import org.hyperledger.fabric.sdk.idemix.IdemixUtils;

/**
 * IdemixIdentity is a public serializable part of the IdemixSigningIdentity.
 * It contains an (un)linkable pseudonym, revealed attribute values, and a
 * corresponding proof of possession of an Idemix credential
 */
public class IdemixIdentity implements Identity {

    private static final Log logger = LogFactory.getLog(IdemixIdentity.class);

    // MSP identifier
    private final String mspId;

    // Issuer public key hash
    private final byte[] ipkHash;

    // Idemix Pseudonym
    private final ECP pseudonym;

    // Organization Unit attribute
    private final String ou;

    // Role mask its a bitmask that represent all the roles attached to this identity
    private final int roleMask;

    // Proof of possession of Idemix credential
    // with respect to the pseudonym (nym)
    // and the corresponding attributes (ou, roleMask)
    private final IdemixSignature associationProof;

    /**
     * Create Idemix Identity from a Serialized Identity
     *
     * @param proto
     */
    public IdemixIdentity(Identities.SerializedIdentity proto) throws CryptoException, InvalidArgumentException {
        if (proto == null) {
            throw new InvalidArgumentException("Input must not be null");
        }

        this.mspId = proto.getMspid();

        try {
            logger.trace("Fetching Idemix Proto");
            Identities.SerializedIdemixIdentity idemixProto = Identities.SerializedIdemixIdentity.parseFrom(proto.getIdBytes());

            if (idemixProto == null) {
                throw new IllegalArgumentException("The identity does not contain a serialized idemix identity");
            }
            logger.trace("Deserializing Nym and attribute values");
            this.pseudonym = new ECP(BIG.fromBytes(idemixProto.getNymX().toByteArray()),
                    BIG.fromBytes(idemixProto.getNymY().toByteArray()));

            MspPrincipal.OrganizationUnit ou = MspPrincipal.OrganizationUnit.parseFrom(idemixProto.getOu());
            MspPrincipal.MSPRole role = MspPrincipal.MSPRole.parseFrom(idemixProto.getRole());

            this.ou = ou.getOrganizationalUnitIdentifier();
            this.roleMask = IdemixRoles.getRoleMask(role);
            this.ipkHash = ou.getCertifiersIdentifier().toByteArray();

            logger.trace("Deserializing Proof");
            this.associationProof = new IdemixSignature(Idemix.Signature.parseFrom(idemixProto.getProof().toByteArray()));

        } catch (InvalidProtocolBufferException e) {
            throw new CryptoException("Cannot deserialize MSP ID", e);
        }
    }

    /**
     * Create Idemix Identity from the following inputs:
     *
     * @param mspId is MSP ID sting
     * @param nym   is Identity Mixer Pseudonym
     * @param ou    is OU attribute
     * @param roleMask  is a bitmask that represent all the roles attached to this identity
     * @param proof is Proof
     */
    public IdemixIdentity(String mspId, IdemixIssuerPublicKey ipk, ECP nym, String ou, int roleMask, IdemixSignature proof)
            throws InvalidArgumentException {

        if (mspId == null) {
            throw new InvalidArgumentException("MSP ID must not be null");
        }

        if (mspId.isEmpty()) {
            throw new InvalidArgumentException("MSP ID must not be empty");
        }

        if (ipk == null) {
            throw new InvalidArgumentException("Issuer Public Key must not be empty");
        }

        if (nym == null) {
            throw new InvalidArgumentException("Identity Mixer Pseudonym (nym) must not be null");
        }

        if (ou == null) {
            throw new InvalidArgumentException("OU attribute must not be null");
        }

        if (ou.isEmpty()) {
            throw new InvalidArgumentException("OU attribute must not be empty");
        }

        if (proof == null) {
            throw new InvalidArgumentException("Proof must not be null");
        }


        this.mspId = mspId;
        this.ipkHash = ipk.getHash();
        this.pseudonym = nym;
        this.ou = ou;
        this.roleMask = roleMask;
        this.associationProof = proof;
    }

    /**
     * Serialize Idemix Identity
     */
    @Override
    public Identities.SerializedIdentity createSerializedIdentity() {
        MspPrincipal.OrganizationUnit ou = MspPrincipal.OrganizationUnit.newBuilder()
                .setCertifiersIdentifier(ByteString.copyFrom(this.ipkHash))
                .setMspIdentifier(this.mspId)
                .setOrganizationalUnitIdentifier(this.ou)
                .build();

        //Warning, this does not support multi-roleMask.
        //Serialize the bitmask is the correct way to support multi-roleMask in the future
        MspPrincipal.MSPRole role = MspPrincipal.MSPRole.newBuilder()
                .setRole(IdemixRoles.getMSPRoleFromIdemixRole(this.roleMask))
                .setMspIdentifier(this.mspId)
                .build();

        Identities.SerializedIdemixIdentity serializedIdemixIdentity = Identities.SerializedIdemixIdentity.newBuilder()
                .setProof(ByteString.copyFrom(this.associationProof.toProto().toByteArray()))
                .setOu(ByteString.copyFrom(ou.toByteArray()))
                .setRole(ByteString.copyFrom(role.toByteArray()))
                .setNymY(ByteString.copyFrom(IdemixUtils.bigToBytes(this.pseudonym.getY())))
                .setNymX(ByteString.copyFrom(IdemixUtils.bigToBytes(this.pseudonym.getX())))
                .build();

        return Identities.SerializedIdentity.newBuilder()
                .setIdBytes(ByteString.copyFrom(serializedIdemixIdentity.toByteArray()))
                .setMspid(this.mspId)
                .build();
    }

    public String getOuValue() {
        return this.ou;
    }

    public int getRoleMask() {
        return this.roleMask;
    }

    @Override
    public String toString() {
        return "IdemixIdentity" +
                " [ MSP ID: " + this.mspId +
                " Issuer Public Key Hash: " + Arrays.toString(this.ipkHash) +
                " Pseudonym: " + this.pseudonym.toRawString() +
                " OU: " + this.ou +
                " Role mask: " + this.roleMask +
                " Association Proof: " + this.associationProof.toProto().toString() +
                " ]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy