github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/zkp/serialnumberprivacy/serialnumberprivacy.go (about)

     1  package serialnumberprivacy
     2  
     3  import (
     4  	"errors"
     5  	"github.com/incognitochain/go-incognito-sdk/common"
     6  	"github.com/incognitochain/go-incognito-sdk/privacy"
     7  	"github.com/incognitochain/go-incognito-sdk/privacy/zkp/utils"
     8  )
     9  
    10  type SerialNumberPrivacyStatement struct {
    11  	sn       *privacy.Point // serial number
    12  	comSK    *privacy.Point // commitment to private key
    13  	comInput *privacy.Point // commitment to input of the pseudo-random function
    14  }
    15  
    16  type SNPrivacyWitness struct {
    17  	stmt *SerialNumberPrivacyStatement // statement to be proved
    18  
    19  	sk     *privacy.Scalar // private key
    20  	rSK    *privacy.Scalar // blinding factor in the commitment to private key
    21  	input  *privacy.Scalar // input of pseudo-random function
    22  	rInput *privacy.Scalar // blinding factor in the commitment to input
    23  }
    24  
    25  type SNPrivacyProof struct {
    26  	stmt *SerialNumberPrivacyStatement // statement to be proved
    27  
    28  	tSK    *privacy.Point // random commitment related to private key
    29  	tInput *privacy.Point // random commitment related to input
    30  	tSN    *privacy.Point // random commitment related to serial number
    31  
    32  	zSK     *privacy.Scalar // first challenge-dependent information to open the commitment to private key
    33  	zRSK    *privacy.Scalar // second challenge-dependent information to open the commitment to private key
    34  	zInput  *privacy.Scalar // first challenge-dependent information to open the commitment to input
    35  	zRInput *privacy.Scalar // second challenge-dependent information to open the commitment to input
    36  }
    37  
    38  // ValidateSanity validates sanity of proof
    39  func (proof SNPrivacyProof) ValidateSanity() bool {
    40  	if !proof.stmt.sn.PointValid() {
    41  		return false
    42  	}
    43  	if !proof.stmt.comSK.PointValid() {
    44  		return false
    45  	}
    46  	if !proof.stmt.comInput.PointValid() {
    47  		return false
    48  	}
    49  	if !proof.tSK.PointValid() {
    50  		return false
    51  	}
    52  	if !proof.tInput.PointValid() {
    53  		return false
    54  	}
    55  	if !proof.tSN.PointValid() {
    56  		return false
    57  	}
    58  	if !proof.zSK.ScalarValid() {
    59  		return false
    60  	}
    61  	if !proof.zRSK.ScalarValid() {
    62  		return false
    63  	}
    64  	if !proof.zInput.ScalarValid() {
    65  		return false
    66  	}
    67  	if !proof.zRInput.ScalarValid() {
    68  		return false
    69  	}
    70  	return true
    71  }
    72  
    73  func (proof SNPrivacyProof) isNil() bool {
    74  	if proof.stmt.sn == nil {
    75  		return true
    76  	}
    77  	if proof.stmt.comSK == nil {
    78  		return true
    79  	}
    80  	if proof.stmt.comInput == nil {
    81  		return true
    82  	}
    83  	if proof.tSK == nil {
    84  		return true
    85  	}
    86  	if proof.tInput == nil {
    87  		return true
    88  	}
    89  	if proof.tSN == nil {
    90  		return true
    91  	}
    92  	if proof.zSK == nil {
    93  		return true
    94  	}
    95  	if proof.zRSK == nil {
    96  		return true
    97  	}
    98  	if proof.zInput == nil {
    99  		return true
   100  	}
   101  	return proof.zRInput == nil
   102  }
   103  
   104  // Init inits Proof
   105  func (proof *SNPrivacyProof) Init() *SNPrivacyProof {
   106  	proof.stmt = new(SerialNumberPrivacyStatement)
   107  
   108  	proof.tSK = new(privacy.Point)
   109  	proof.tInput = new(privacy.Point)
   110  	proof.tSN = new(privacy.Point)
   111  
   112  	proof.zSK = new(privacy.Scalar)
   113  	proof.zRSK = new(privacy.Scalar)
   114  	proof.zInput = new(privacy.Scalar)
   115  	proof.zRInput = new(privacy.Scalar)
   116  
   117  	return proof
   118  }
   119  
   120  func (proof SNPrivacyProof) GetComSK() *privacy.Point {
   121  	return proof.stmt.comSK
   122  }
   123  
   124  func (proof SNPrivacyProof) GetComInput() *privacy.Point {
   125  	return proof.stmt.comInput
   126  }
   127  
   128  func (proof SNPrivacyProof) GetSN() *privacy.Point {
   129  	return proof.stmt.sn
   130  }
   131  
   132  // Set sets Statement
   133  func (stmt *SerialNumberPrivacyStatement) Set(
   134  	SN *privacy.Point,
   135  	comSK *privacy.Point,
   136  	comInput *privacy.Point) {
   137  	stmt.sn = SN
   138  	stmt.comSK = comSK
   139  	stmt.comInput = comInput
   140  }
   141  
   142  // Set sets Witness
   143  func (wit *SNPrivacyWitness) Set(
   144  	stmt *SerialNumberPrivacyStatement,
   145  	SK *privacy.Scalar,
   146  	rSK *privacy.Scalar,
   147  	input *privacy.Scalar,
   148  	rInput *privacy.Scalar) {
   149  
   150  	wit.stmt = stmt
   151  	wit.sk = SK
   152  	wit.rSK = rSK
   153  	wit.input = input
   154  	wit.rInput = rInput
   155  }
   156  
   157  // Set sets Proof
   158  func (proof *SNPrivacyProof) Set(
   159  	stmt *SerialNumberPrivacyStatement,
   160  	tSK *privacy.Point,
   161  	tInput *privacy.Point,
   162  	tSN *privacy.Point,
   163  	zSK *privacy.Scalar,
   164  	zRSK *privacy.Scalar,
   165  	zInput *privacy.Scalar,
   166  	zRInput *privacy.Scalar) {
   167  	proof.stmt = stmt
   168  	proof.tSK = tSK
   169  	proof.tInput = tInput
   170  	proof.tSN = tSN
   171  
   172  	proof.zSK = zSK
   173  	proof.zRSK = zRSK
   174  	proof.zInput = zInput
   175  	proof.zRInput = zRInput
   176  }
   177  
   178  func (proof SNPrivacyProof) Bytes() []byte {
   179  	// if proof is nil, return an empty array
   180  	if proof.isNil() {
   181  		return []byte{}
   182  	}
   183  
   184  	var bytes []byte
   185  	bytes = append(bytes, proof.stmt.sn.ToBytesS()...)
   186  	bytes = append(bytes, proof.stmt.comSK.ToBytesS()...)
   187  	bytes = append(bytes, proof.stmt.comInput.ToBytesS()...)
   188  
   189  	bytes = append(bytes, proof.tSK.ToBytesS()...)
   190  	bytes = append(bytes, proof.tInput.ToBytesS()...)
   191  	bytes = append(bytes, proof.tSN.ToBytesS()...)
   192  
   193  	bytes = append(bytes, proof.zSK.ToBytesS()...)
   194  	bytes = append(bytes, proof.zRSK.ToBytesS()...)
   195  	bytes = append(bytes, proof.zInput.ToBytesS()...)
   196  	bytes = append(bytes, proof.zRInput.ToBytesS()...)
   197  
   198  	return bytes
   199  }
   200  
   201  func (proof *SNPrivacyProof) SetBytes(bytes []byte) error {
   202  	if len(bytes) == 0 {
   203  		return errors.New("Bytes array is empty")
   204  	}
   205  
   206  	offset := 0
   207  	var err error
   208  
   209  	proof.stmt.sn = new(privacy.Point)
   210  	proof.stmt.sn, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   211  	if err != nil {
   212  		return err
   213  	}
   214  	offset += privacy.Ed25519KeySize
   215  
   216  	proof.stmt.comSK = new(privacy.Point)
   217  	proof.stmt.comSK, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	offset += privacy.Ed25519KeySize
   223  	proof.stmt.comInput = new(privacy.Point)
   224  	proof.stmt.comInput, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   225  	if err != nil {
   226  		return err
   227  	}
   228  
   229  	offset += privacy.Ed25519KeySize
   230  	proof.tSK = new(privacy.Point)
   231  	proof.tSK, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	offset += privacy.Ed25519KeySize
   237  	proof.tInput = new(privacy.Point)
   238  	proof.tInput, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   239  	if err != nil {
   240  		return err
   241  	}
   242  
   243  	offset += privacy.Ed25519KeySize
   244  	proof.tSN = new(privacy.Point)
   245  	proof.tSN, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   246  	if err != nil {
   247  		return err
   248  	}
   249  
   250  	offset += privacy.Ed25519KeySize
   251  	proof.zSK = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   252  
   253  	offset += privacy.Ed25519KeySize
   254  	proof.zRSK = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize])
   255  
   256  	offset += privacy.Ed25519KeySize
   257  	proof.zInput = new(privacy.Scalar).FromBytesS(bytes[offset : offset+common.BigIntSize])
   258  
   259  	offset += privacy.Ed25519KeySize
   260  	proof.zRInput = new(privacy.Scalar).FromBytesS(bytes[offset : offset+common.BigIntSize])
   261  
   262  	return nil
   263  }
   264  
   265  func (wit SNPrivacyWitness) Prove(mess []byte) (*SNPrivacyProof, error) {
   266  	eSK := privacy.RandomScalar()
   267  	eSND := privacy.RandomScalar()
   268  	dSK := privacy.RandomScalar()
   269  	dSND := privacy.RandomScalar()
   270  	// calculate tSeed = g_SK^eSK * h^dSK
   271  	tSeed := privacy.PedCom.CommitAtIndex(eSK, dSK, privacy.PedersenPrivateKeyIndex)
   272  	// calculate tSND = g_SND^eSND * h^dSND
   273  	tInput := privacy.PedCom.CommitAtIndex(eSND, dSND, privacy.PedersenSndIndex)
   274  	// calculate tSND = g_SK^eSND * h^dSND2
   275  	tOutput := new(privacy.Point).ScalarMult(wit.stmt.sn, new(privacy.Scalar).Add(eSK, eSND))
   276  	// calculate x = hash(tSeed || tInput || tSND2 || tOutput)
   277  	x := new(privacy.Scalar)
   278  	if mess == nil {
   279  		x = utils.GenerateChallenge([][]byte{
   280  			wit.stmt.sn.ToBytesS(),
   281  			wit.stmt.comSK.ToBytesS(),
   282  			tSeed.ToBytesS(),
   283  			tInput.ToBytesS(),
   284  			tOutput.ToBytesS()})
   285  	} else {
   286  		x.FromBytesS(mess)
   287  	}
   288  	// Calculate zSeed = sk * x + eSK
   289  	zSeed := new(privacy.Scalar).Mul(wit.sk, x)
   290  	zSeed.Add(zSeed, eSK)
   291  	//zSeed.Mod(zSeed, privacy.Curve.Params().N)
   292  	// Calculate zRSeed = rSK * x + dSK
   293  	zRSeed := new(privacy.Scalar).Mul(wit.rSK, x)
   294  	zRSeed.Add(zRSeed, dSK)
   295  	//zRSeed.Mod(zRSeed, privacy.Curve.Params().N)
   296  	// Calculate zInput = input * x + eSND
   297  	zInput := new(privacy.Scalar).Mul(wit.input, x)
   298  	zInput.Add(zInput, eSND)
   299  	//zInput.Mod(zInput, privacy.Curve.Params().N)
   300  	// Calculate zRInput = rInput * x + dSND
   301  	zRInput := new(privacy.Scalar).Mul(wit.rInput, x)
   302  	zRInput.Add(zRInput, dSND)
   303  	//zRInput.Mod(zRInput, privacy.Curve.Params().N)
   304  	proof := new(SNPrivacyProof).Init()
   305  	proof.Set(wit.stmt, tSeed, tInput, tOutput, zSeed, zRSeed, zInput, zRInput)
   306  	return proof, nil
   307  }
   308  
   309  func (proof SNPrivacyProof) Verify(mess []byte) (bool, error) {
   310  	// re-calculate x = hash(tSeed || tInput || tSND2 || tOutput)
   311  	x := new(privacy.Scalar)
   312  	if mess == nil {
   313  		x = utils.GenerateChallenge([][]byte{
   314  			proof.tSK.ToBytesS(),
   315  			proof.tInput.ToBytesS(),
   316  			proof.tSN.ToBytesS()})
   317  	} else {
   318  		x.FromBytesS(mess)
   319  	}
   320  
   321  	// Check gSND^zInput * h^zRInput = input^x * tInput
   322  	leftPoint1 := privacy.PedCom.CommitAtIndex(proof.zInput, proof.zRInput, privacy.PedersenSndIndex)
   323  
   324  	rightPoint1 := new(privacy.Point).ScalarMult(proof.stmt.comInput, x)
   325  	rightPoint1.Add(rightPoint1, proof.tInput)
   326  
   327  	if !privacy.IsPointEqual(leftPoint1, rightPoint1) {
   328  		return false, errors.New("verify serial number privacy proof statement 1 failed")
   329  	}
   330  
   331  	// Check gSK^zSeed * h^zRSeed = vKey^x * tSeed
   332  	leftPoint2 := privacy.PedCom.CommitAtIndex(proof.zSK, proof.zRSK, privacy.PedersenPrivateKeyIndex)
   333  
   334  	rightPoint2 := new(privacy.Point).ScalarMult(proof.stmt.comSK, x)
   335  	rightPoint2.Add(rightPoint2, proof.tSK)
   336  
   337  	if !privacy.IsPointEqual(leftPoint2, rightPoint2) {
   338  		return false, errors.New("verify serial number privacy proof statement 2 failed")
   339  	}
   340  
   341  	// Check sn^(zSeed + zInput) = gSK^x * tOutput
   342  	leftPoint3 := new(privacy.Point).ScalarMult(proof.stmt.sn, new(privacy.Scalar).Add(proof.zSK, proof.zInput))
   343  
   344  	rightPoint3 := new(privacy.Point).ScalarMult(privacy.PedCom.G[privacy.PedersenPrivateKeyIndex], x)
   345  	rightPoint3.Add(rightPoint3, proof.tSN)
   346  
   347  	if !privacy.IsPointEqual(leftPoint3, rightPoint3) {
   348  		return false, errors.New("verify serial number privacy proof statement 3 failed")
   349  	}
   350  
   351  	return true, nil
   352  }