github.com/ronperry/cryptoedge@v0.0.0-20150815114006-cc363e290743/jcc/client.go (about) 1 // Package jcc implements "An ECC-Based Blind Signature Scheme" by Fuh-Gwo Jeng, Tzer-Long Chen and Tzer-Shyong Chen 2 // A lot of the sanity checks performed by the code make no mathematical sense since they are impossible to produce if the code is actually bug-less 3 // Under certain conditions both msg and the image of the msg have valid signatures (implausible) 4 // 5 // Generate key: 6 // Private key == blinding factor (ni) 7 // Blind: 8 // blind message = scalarmult(message,scalarmult(blinding factor, PublicKey)) (POINT) 9 // Sign: 10 // r = nv x blind message (POINT); s = (nv+ns) x blind message (POINT) 11 // ns is the privat key of the signer 12 // record nv,blind message. protect priv-key of signer 13 // Unblind: 14 // s' = s - m x ni x Ps (Ps public key signer) (POINT) 15 // m' = ni(ni-1)m 16 // Verify: 17 // r == s' - m' x Ps 18 // 19 // Public data: 20 // Signer: Public Key. Private key and token remain secret 21 // Client: 22 // Blind() output: bmsg is public and sent to Signer. bfac is secret, needed for unblinding 23 // bfac should be destroyed after unblind (and verification) 24 // Blind() input msg must be retained until unblinding and destroyed after 25 // Signature (r, sb, mb): 26 // From signer -> r 27 // From client -> Output of Unblind(): sb, mb 28 // Verification operates on: Signer public key, Signature(r, sb, mb) 29 // 30 // For more information: http://ojs.academypublisher.com/index.php/jnw/article/viewFile/0508921928/2053 31 // 32 package jcc 33 34 import ( 35 "github.com/ronperry/cryptoedge/eccutil" 36 "math/big" 37 ) 38 39 // MaxLoopCount is the maximum number of tries we do for parameter search 40 const MaxLoopCount = 1000 41 42 // Refactor begin 43 44 // BlindingClient a blinding client 45 type BlindingClient struct { 46 curve *eccutil.Curve 47 PubKey *eccutil.Point 48 } 49 50 // NewBlindingClient returns a new BlindingClient 51 func NewBlindingClient(curve *eccutil.Curve, pubKey *eccutil.Point) *BlindingClient { 52 bc := new(BlindingClient) 53 bc.curve = curve 54 bc.PubKey = pubKey 55 return bc 56 } 57 58 // Blind returns a blinded message and the blinding factor. bmsg is sent to signer (public), bfac is private and needed for unblinding 59 func (client BlindingClient) Blind(msg []byte) (bmsg *eccutil.Point, bfac []byte, err error) { 60 // blind message = scalarmult(message,scalarmult(blinding factor, scalarmult(blindingfactor,basepoint)) (POINT) 61 var loopcount int 62 if len(msg) < 10 { 63 return nil, nil, eccutil.ErrMsgShort 64 } 65 t := new(big.Int) 66 t.SetBytes(msg) 67 _, err = client.curve.TestCoordinate(t) 68 if err != nil { 69 return nil, nil, err 70 } 71 //cparams := client.curve.Params() 72 for { 73 if loopcount > MaxLoopCount { 74 return nil, nil, eccutil.ErrMaxLoop 75 } 76 loopcount++ 77 bfact, bpoint, err := client.curve.GenerateKey() 78 if err != nil { 79 return nil, nil, err 80 } 81 bfac2 := client.curve.ScalarMult(bpoint, bfact) 82 _, err = client.curve.TestPoint(bpoint.X, bpoint.Y, bfac2.X, bfac2.Y) // This cannot really happen 83 if err != nil { 84 return nil, nil, err 85 } 86 _, err = client.curve.TestPoint(bfac2.X, bfac2.Y, client.curve.Params.Gx, client.curve.Params.Gy) 87 if err != nil { 88 continue 89 } 90 bmsgt := client.curve.ScalarMult(bfac2, msg) 91 _, err = client.curve.TestPoint(bpoint.X, bpoint.Y, bmsgt.X, bmsgt.Y) 92 if err != nil { 93 continue 94 } 95 _, err = client.curve.TestPoint(bfac2.X, bfac2.Y, bmsgt.X, bmsgt.Y) // This cannot really happen 96 if err != nil { 97 return nil, nil, err 98 } 99 _, err = client.curve.TestPoint(bmsgt.X, bmsgt.Y, client.curve.Params.Gx, client.curve.Params.Gy) 100 if err != nil { 101 continue 102 } 103 return bmsgt, bfact, nil 104 } 105 } 106 107 // Unblind unblinds a signature. sb and mb are required for verification 108 func (client BlindingClient) Unblind(bfac, msg []byte, s *eccutil.Point) (sb *eccutil.Point, mb []byte) { 109 ni := new(big.Int) 110 m := new(big.Int) 111 mbt := new(big.Int) 112 nim := new(big.Int) 113 114 // Calculate m' = ni(ni-1)*m 115 ni.SetBytes(bfac) 116 m.SetBytes(msg) 117 nim = nim.Mul(ni, nim.Sub(ni, big.NewInt(1))) // ni(ni-1) 118 mbt = mbt.Mul(nim, m) // (ni(ni-1))*m 119 mbt = eccutil.ManyMult(ni, nim.Sub(ni, big.NewInt(1)), m) 120 mbx := mbt.Bytes() 121 122 // Calculate: s' = s - m x ni x Ps (Ps public key signer) (POINT) 123 nit := client.curve.ScalarMult(client.PubKey, bfac) // ni x Ps 124 mt := client.curve.ScalarMult(nit, msg) // m x (ni x Ps) 125 // inverse mt to make substraction 126 mt.Y = mt.Y.Neg(mt.Y) 127 st := client.curve.AddPoints(s, mt) // s - (m x ni x Ps) 128 return st, mbx 129 } 130 131 // Verify a signature 132 func (client BlindingClient) Verify(r, sb *eccutil.Point, mb []byte) bool { 133 // r == s' - m' x Ps 134 c := client.curve.ScalarMult(client.PubKey, mb) // m' x Ps 135 c.Y = c.Y.Neg(c.Y) // neg m' 136 cv := client.curve.AddPoints(sb, c) // s + neg (m x Ps) 137 if r.X.Cmp(cv.X) == 0 && r.Y.Cmp(cv.Y) == 0 { // r == s + neg (m x Ps) ? 138 return true 139 } 140 return false 141 }