github.com/lzy4123/fabric@v2.1.1+incompatible/idemix/issuerkey.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package idemix
     8  
     9  import (
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/hyperledger/fabric-amcl/amcl"
    12  	"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  // The Issuer secret ISk and public IPk keys are used to issue credentials and
    17  // to verify signatures created using the credentials
    18  
    19  // The Issuer Secret Key is a random exponent (generated randomly from Z*_p)
    20  
    21  // The Issuer Public Key consists of several elliptic curve points (ECP),
    22  // where index 1 corresponds to group G1 and 2 to group G2)
    23  // HSk, HRand, BarG1, BarG2, an ECP array HAttrs, and an ECP2 W,
    24  // and a proof of knowledge of the corresponding secret key
    25  
    26  // NewIssuerKey creates a new issuer key pair taking an array of attribute names
    27  // that will be contained in credentials certified by this issuer (a credential specification)
    28  // See http://eprint.iacr.org/2016/663.pdf Sec. 4.3, for references.
    29  func NewIssuerKey(AttributeNames []string, rng *amcl.RAND) (*IssuerKey, error) {
    30  	// validate inputs
    31  
    32  	// check for duplicated attributes
    33  	attributeNamesMap := map[string]bool{}
    34  	for _, name := range AttributeNames {
    35  		if attributeNamesMap[name] {
    36  			return nil, errors.Errorf("attribute %s appears multiple times in AttributeNames", name)
    37  		}
    38  		attributeNamesMap[name] = true
    39  	}
    40  
    41  	key := new(IssuerKey)
    42  
    43  	// generate issuer secret key
    44  	ISk := RandModOrder(rng)
    45  	key.Isk = BigToBytes(ISk)
    46  
    47  	// generate the corresponding public key
    48  	key.Ipk = new(IssuerPublicKey)
    49  	key.Ipk.AttributeNames = AttributeNames
    50  
    51  	W := GenG2.Mul(ISk)
    52  	key.Ipk.W = Ecp2ToProto(W)
    53  
    54  	// generate bases that correspond to the attributes
    55  	key.Ipk.HAttrs = make([]*ECP, len(AttributeNames))
    56  	for i := 0; i < len(AttributeNames); i++ {
    57  		key.Ipk.HAttrs[i] = EcpToProto(GenG1.Mul(RandModOrder(rng)))
    58  	}
    59  
    60  	// generate base for the secret key
    61  	HSk := GenG1.Mul(RandModOrder(rng))
    62  	key.Ipk.HSk = EcpToProto(HSk)
    63  
    64  	// generate base for the randomness
    65  	HRand := GenG1.Mul(RandModOrder(rng))
    66  	key.Ipk.HRand = EcpToProto(HRand)
    67  
    68  	BarG1 := GenG1.Mul(RandModOrder(rng))
    69  	key.Ipk.BarG1 = EcpToProto(BarG1)
    70  
    71  	BarG2 := BarG1.Mul(ISk)
    72  	key.Ipk.BarG2 = EcpToProto(BarG2)
    73  
    74  	// generate a zero-knowledge proof of knowledge (ZK PoK) of the secret key which
    75  	// is in W and BarG2.
    76  
    77  	// Sample the randomness needed for the proof
    78  	r := RandModOrder(rng)
    79  
    80  	// Step 1: First message (t-values)
    81  	t1 := GenG2.Mul(r) // t1 = g_2^r, cover W
    82  	t2 := BarG1.Mul(r) // t2 = (\bar g_1)^r, cover BarG2
    83  
    84  	// Step 2: Compute the Fiat-Shamir hash, forming the challenge of the ZKP.
    85  	proofData := make([]byte, 18*FieldBytes+3)
    86  	index := 0
    87  	index = appendBytesG2(proofData, index, t1)
    88  	index = appendBytesG1(proofData, index, t2)
    89  	index = appendBytesG2(proofData, index, GenG2)
    90  	index = appendBytesG1(proofData, index, BarG1)
    91  	index = appendBytesG2(proofData, index, W)
    92  	index = appendBytesG1(proofData, index, BarG2)
    93  
    94  	proofC := HashModOrder(proofData)
    95  	key.Ipk.ProofC = BigToBytes(proofC)
    96  
    97  	// Step 3: reply to the challenge message (s-values)
    98  	proofS := Modadd(FP256BN.Modmul(proofC, ISk, GroupOrder), r, GroupOrder) // // s = r + C \cdot ISk
    99  	key.Ipk.ProofS = BigToBytes(proofS)
   100  
   101  	// Hash the public key
   102  	serializedIPk, err := proto.Marshal(key.Ipk)
   103  	if err != nil {
   104  		return nil, errors.Wrap(err, "failed to marshal issuer public key")
   105  	}
   106  	key.Ipk.Hash = BigToBytes(HashModOrder(serializedIPk))
   107  
   108  	// We are done
   109  	return key, nil
   110  }
   111  
   112  // Check checks that this issuer public key is valid, i.e.
   113  // that all components are present and a ZK proofs verifies
   114  func (IPk *IssuerPublicKey) Check() error {
   115  	// Unmarshall the public key
   116  	NumAttrs := len(IPk.GetAttributeNames())
   117  	HSk := EcpFromProto(IPk.GetHSk())
   118  	HRand := EcpFromProto(IPk.GetHRand())
   119  	HAttrs := make([]*FP256BN.ECP, len(IPk.GetHAttrs()))
   120  	for i := 0; i < len(IPk.GetHAttrs()); i++ {
   121  		HAttrs[i] = EcpFromProto(IPk.GetHAttrs()[i])
   122  	}
   123  	BarG1 := EcpFromProto(IPk.GetBarG1())
   124  	BarG2 := EcpFromProto(IPk.GetBarG2())
   125  	W := Ecp2FromProto(IPk.GetW())
   126  	ProofC := FP256BN.FromBytes(IPk.GetProofC())
   127  	ProofS := FP256BN.FromBytes(IPk.GetProofS())
   128  
   129  	// Check that the public key is well-formed
   130  	if NumAttrs < 0 ||
   131  		HSk == nil ||
   132  		HRand == nil ||
   133  		BarG1 == nil ||
   134  		BarG1.Is_infinity() ||
   135  		BarG2 == nil ||
   136  		HAttrs == nil ||
   137  		len(IPk.HAttrs) < NumAttrs {
   138  		return errors.Errorf("some part of the public key is undefined")
   139  	}
   140  	for i := 0; i < NumAttrs; i++ {
   141  		if IPk.HAttrs[i] == nil {
   142  			return errors.Errorf("some part of the public key is undefined")
   143  		}
   144  	}
   145  
   146  	// Verify Proof
   147  
   148  	// Recompute challenge
   149  	proofData := make([]byte, 18*FieldBytes+3)
   150  	index := 0
   151  
   152  	// Recompute t-values using s-values
   153  	t1 := GenG2.Mul(ProofS)
   154  	t1.Add(W.Mul(FP256BN.Modneg(ProofC, GroupOrder))) // t1 = g_2^s \cdot W^{-C}
   155  
   156  	t2 := BarG1.Mul(ProofS)
   157  	t2.Add(BarG2.Mul(FP256BN.Modneg(ProofC, GroupOrder))) // t2 = {\bar g_1}^s \cdot {\bar g_2}^C
   158  
   159  	index = appendBytesG2(proofData, index, t1)
   160  	index = appendBytesG1(proofData, index, t2)
   161  	index = appendBytesG2(proofData, index, GenG2)
   162  	index = appendBytesG1(proofData, index, BarG1)
   163  	index = appendBytesG2(proofData, index, W)
   164  	index = appendBytesG1(proofData, index, BarG2)
   165  
   166  	// Verify that the challenge is the same
   167  	if *ProofC != *HashModOrder(proofData) {
   168  		return errors.Errorf("zero knowledge proof in public key invalid")
   169  	}
   170  
   171  	return IPk.SetHash()
   172  }
   173  
   174  // SetHash appends a hash of a serialized public key
   175  func (IPk *IssuerPublicKey) SetHash() error {
   176  	IPk.Hash = nil
   177  	serializedIPk, err := proto.Marshal(IPk)
   178  	if err != nil {
   179  		return errors.Wrap(err, "Failed to marshal issuer public key")
   180  	}
   181  	IPk.Hash = BigToBytes(HashModOrder(serializedIPk))
   182  	return nil
   183  }