func benchScalarMult(curve elliptic.Curve, k []byte, n int) { x := curve.Params().Gx y := curve.Params().Gy for i := 0; i < n; i++ { curve.ScalarMult(x, y, k) } }
func DecryptMark(c elliptic.Curve, m *Mark, priv []byte) (int, error) { tx, ty := c.ScalarMult(m.ax, m.ay, priv) tm := big.NewInt(0) tm.Sub(c.Params().P, ty) tm.Mod(tm, c.Params().P) px, py := c.Add(m.bx, m.by, tx, tm) return DiscreteLog(px, py, c, 1<<10) }
func VoteOne(c elliptic.Curve, px *big.Int, py *big.Int) *Checkbox { var err error h := new(Checkbox) h.s, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } h.ax, h.ay = c.ScalarBaseMult(h.s.Bytes()) tx, ty := c.ScalarMult(px, py, h.s.Bytes()) h.bx, h.by = c.Add(tx, ty, c.Params().Gx, c.Params().Gy) //TODO: refactor: lots of similar logic here but parts very //c2, r2 fake, c1 r1 genuine //Form the faked challenge h.c2, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } h.r2, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } //Compute the commitments v3, v4 as the verifier will v3x, v3y := doublescalarmult(c, c.Params().Gx, c.Params().Gy, h.r2.Bytes(), h.ax, h.ay, h.c2.Bytes()) v4x, v4y := doublescalarmult(c, px, py, h.r2.Bytes(), h.bx, h.by, h.c2.Bytes()) //Commit to other side s1, err := rand.Int(rand.Reader, c.Params().N) if err != nil { panic("something deeply wrong") } v1x, v1y := c.ScalarBaseMult(s1.Bytes()) v2x, v2y := c.ScalarMult(px, py, s1.Bytes()) //Compute the total challenge var entries [6][]byte entries[0] = elliptic.Marshal(c, h.ax, h.ay) entries[1] = elliptic.Marshal(c, h.bx, h.by) entries[2] = elliptic.Marshal(c, v1x, v1y) entries[3] = elliptic.Marshal(c, v2x, v2y) entries[4] = elliptic.Marshal(c, v3x, v3y) entries[5] = elliptic.Marshal(c, v4x, v4y) challenge := sha256.Sum256(bytes.Join(entries[:], []byte{})) ctot := big.NewInt(0) ctot.SetBytes(challenge[:]) ctot.Mod(ctot, c.Params().N) h.c1 = big.NewInt(0) h.c1.Sub(ctot, h.c2) h.c1.Mod(h.c1, c.Params().N) //r=s1-c1*h.s t := big.NewInt(0) t.Mul(h.c1, h.s) t.Mod(t, c.Params().N) t.Sub(s1, t) t.Mod(t, c.Params().N) h.r1 = t return h }
// kexECDH performs Elliptic Curve Diffie-Hellman key exchange as // described in RFC 5656, section 4. func (c *ClientConn) kexECDH(curve elliptic.Curve, magics *handshakeMagics, hostKeyAlgo string) (*kexResult, error) { ephKey, err := ecdsa.GenerateKey(curve, c.config.rand()) if err != nil { return nil, err } kexInit := kexECDHInitMsg{ ClientPubKey: elliptic.Marshal(curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), } serialized := marshal(msgKexECDHInit, kexInit) if err := c.writePacket(serialized); err != nil { return nil, err } packet, err := c.readPacket() if err != nil { return nil, err } var reply kexECDHReplyMsg if err = unmarshal(&reply, packet, msgKexECDHReply); err != nil { return nil, err } x, y := elliptic.Unmarshal(curve, reply.EphemeralPubKey) if x == nil { return nil, errors.New("ssh: elliptic.Unmarshal failure") } if !validateECPublicKey(curve, x, y) { return nil, errors.New("ssh: ephemeral server key not on curve") } // generate shared secret secret, _ := curve.ScalarMult(x, y, ephKey.D.Bytes()) hashFunc := ecHash(curve) h := hashFunc.New() writeString(h, magics.clientVersion) writeString(h, magics.serverVersion) writeString(h, magics.clientKexInit) writeString(h, magics.serverKexInit) writeString(h, reply.HostKey) writeString(h, kexInit.ClientPubKey) writeString(h, reply.EphemeralPubKey) K := make([]byte, intLength(secret)) marshalInt(K, secret) h.Write(K) return &kexResult{ H: h.Sum(nil), K: K, HostKey: reply.HostKey, Signature: reply.Signature, Hash: hashFunc, }, nil }
// Generates an ephemeral public key and returns a function that will compute // the shared secret key. Used in the identify module. // // Focuses only on ECDH now, but can be made more general in the future. func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { var curve elliptic.Curve switch curveName { case "P-224": curve = elliptic.P224() case "P-256": curve = elliptic.P256() case "P-384": curve = elliptic.P384() case "P-521": curve = elliptic.P521() } priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) if err != nil { return nil, nil, err } var pubKey bytes.Buffer pubKey.Write(x.Bytes()) pubKey.Write(y.Bytes()) done := func(theirPub []byte) ([]byte, error) { // Verify and unpack node's public key. curveSize := curve.Params().BitSize if len(theirPub) != (curveSize / 4) { return nil, errors.New("Malformed public key.") } bound := (curveSize / 8) x := big.NewInt(0) y := big.NewInt(0) x.SetBytes(theirPub[0:bound]) y.SetBytes(theirPub[bound : bound*2]) if !curve.IsOnCurve(x, y) { return nil, errors.New("Invalid public key.") } // Generate shared secret. secret, _ := curve.ScalarMult(x, y, priv) return secret.Bytes(), nil } return pubKey.Bytes(), done, nil }
func FillBallot(c elliptic.Curve, px *big.Int, py *big.Int, entry int, size int) *Ballot { b := new(Ballot) b.boxes = make([]*Checkbox, size, size) for i := 0; i < size; i++ { if i == entry { b.boxes[i] = VoteOne(c, px, py) } else { b.boxes[i] = VoteZero(c, px, py) } } //TODO: add validation //Let A be the sum of all the A, B the sum of all the B //Then we want log_g(A)=log_h(B-g) ax := big.NewInt(0) ay := big.NewInt(0) bx := big.NewInt(0) by := big.NewInt(0) s := big.NewInt(0) for i := 0; i < size; i++ { ax, ay = c.Add(ax, ay, b.boxes[i].ax, b.boxes[i].ay) bx, by = c.Add(bx, by, b.boxes[i].bx, b.boxes[i].by) s.Add(s, b.boxes[i].s) } s.Mod(s, c.Params().N) k, err := rand.Int(rand.Reader, c.Params().N) if err != nil { panic("Not here, not now") } v1x, v1y := c.ScalarBaseMult(k.Bytes()) v2x, v2y := c.ScalarMult(px, py, k.Bytes()) var commit [4][]byte commit[0] = elliptic.Marshal(c, ax, ay) commit[1] = elliptic.Marshal(c, bx, by) commit[2] = elliptic.Marshal(c, v1x, v1y) commit[3] = elliptic.Marshal(c, v2x, v2y) cb := bytes.Join(commit[:], []byte{}) cbytes := sha256.Sum256(cb[:]) b.c = big.NewInt(0) b.c.SetBytes(cbytes[:]) b.c.Mod(b.c, c.Params().N) b.r = big.NewInt(0) //r=k-c*s b.r.Mul(b.c, s) b.r.Sub(k, b.r) b.r.Mod(b.r, c.Params().N) return b }
// Generates an ephemeral public key and returns a function that will compute // the shared secret key. Used in the identify module. // // Focuses only on ECDH now, but can be made more general in the future. func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { var curve elliptic.Curve switch curveName { case "P-224": curve = elliptic.P224() case "P-256": curve = elliptic.P256() case "P-384": curve = elliptic.P384() case "P-521": curve = elliptic.P521() } priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader) if err != nil { return nil, nil, err } pubKey := elliptic.Marshal(curve, x, y) // log.Debug("GenerateEKeyPair %d", len(pubKey)) done := func(theirPub []byte) ([]byte, error) { // Verify and unpack node's public key. x, y := elliptic.Unmarshal(curve, theirPub) if x == nil { return nil, fmt.Errorf("Malformed public key: %d %v", len(theirPub), theirPub) } if !curve.IsOnCurve(x, y) { return nil, errors.New("Invalid public key.") } // Generate shared secret. secret, _ := curve.ScalarMult(x, y, priv) return secret.Bytes(), nil } return pubKey, done, nil }
func doublescalarmult(c elliptic.Curve, ax *big.Int, ay *big.Int, s1 []byte, bx *big.Int, by *big.Int, s2 []byte) (*big.Int, *big.Int) { t1x, t1y := c.ScalarMult(ax, ay, s1) t2x, t2y := c.ScalarMult(bx, by, s2) return c.Add(t1x, t1y, t2x, t2y) }
func VoteZero(c elliptic.Curve, px *big.Int, py *big.Int) *Checkbox { var err error h := new(Checkbox) h.s, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } h.ax, h.ay = c.ScalarBaseMult(h.s.Bytes()) h.bx, h.by = c.ScalarMult(px, py, h.s.Bytes()) //TODO: get the proof generated //c1, r1 fake, c2, r2 genuine //First compute the missing B-g tx := big.NewInt(0) tx.Set(c.Params().Gx) ty := big.NewInt(0) ty.Set(c.Params().Gy) ty.Neg(ty) ty.Mod(ty, c.Params().P) bgx, bgy := c.Add(tx, ty, h.bx, h.by) //Now fake the challenge h.c1, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } h.r1, err = rand.Int(rand.Reader, c.Params().N) if err != nil { panic("this shouldn't happen") } //Compute v1, v2 as verifier will v1x, v1y := doublescalarmult(c, c.Params().Gx, c.Params().Gy, h.r1.Bytes(), h.ax, h.ay, h.c1.Bytes()) v2x, v2y := doublescalarmult(c, px, py, h.r1.Bytes(), bgx, bgy, h.c1.Bytes()) //Other part of commitment s1, err := rand.Int(rand.Reader, c.Params().N) if err != nil { panic("something is deeply wrong") } v3x, v3y := c.ScalarBaseMult(s1.Bytes()) v4x, v4y := c.ScalarMult(px, py, s1.Bytes()) //Compute total challenge var entries [6][]byte entries[0] = elliptic.Marshal(c, h.ax, h.ay) entries[1] = elliptic.Marshal(c, h.bx, h.by) entries[2] = elliptic.Marshal(c, v1x, v1y) entries[3] = elliptic.Marshal(c, v2x, v2y) entries[4] = elliptic.Marshal(c, v3x, v3y) entries[5] = elliptic.Marshal(c, v4x, v4y) challenge := sha256.Sum256(bytes.Join(entries[:], []byte{})) ctot := big.NewInt(0) ctot.SetBytes(challenge[:]) ctot.Mod(ctot, c.Params().N) h.c2 = big.NewInt(0) h.c2.Sub(ctot, h.c1) h.c2.Mod(h.c2, c.Params().N) //r2=s1-c2*s h.r2 = big.NewInt(0) h.r2.Mul(h.c2, h.s) h.r2.Sub(s1, h.r2) h.r2.Mod(h.r2, c.Params().N) return h }
// kexECDH performs Elliptic Curve Diffie-Hellman key agreement on a // ServerConnection, as documented in RFC 5656, section 4. func (s *ServerConn) kexECDH(curve elliptic.Curve, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { packet, err := s.readPacket() if err != nil { return } var kexECDHInit kexECDHInitMsg if err = unmarshal(&kexECDHInit, packet, msgKexECDHInit); err != nil { return } clientX, clientY := elliptic.Unmarshal(curve, kexECDHInit.ClientPubKey) if clientX == nil { return nil, errors.New("ssh: elliptic.Unmarshal failure") } if !validateECPublicKey(curve, clientX, clientY) { return nil, errors.New("ssh: not a valid EC public key") } // We could cache this key across multiple users/multiple // connection attempts, but the benefit is small. OpenSSH // generates a new key for each incoming connection. ephKey, err := ecdsa.GenerateKey(curve, s.config.rand()) if err != nil { return nil, err } hostKeyBytes := MarshalPublicKey(priv.PublicKey()) serializedEphKey := elliptic.Marshal(curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) // generate shared secret secret, _ := curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) hashFunc := ecHash(curve) h := hashFunc.New() writeString(h, magics.clientVersion) writeString(h, magics.serverVersion) writeString(h, magics.clientKexInit) writeString(h, magics.serverKexInit) writeString(h, hostKeyBytes) writeString(h, kexECDHInit.ClientPubKey) writeString(h, serializedEphKey) K := make([]byte, intLength(secret)) marshalInt(K, secret) h.Write(K) H := h.Sum(nil) // H is already a hash, but the hostkey signing will apply its // own key specific hash algorithm. sig, err := signAndMarshal(priv, s.config.rand(), H) if err != nil { return nil, err } reply := kexECDHReplyMsg{ EphemeralPubKey: serializedEphKey, HostKey: hostKeyBytes, Signature: sig, } serialized := marshal(msgKexECDHReply, reply) if err := s.writePacket(serialized); err != nil { return nil, err } return &kexResult{ H: H, K: K, HostKey: reply.HostKey, Hash: hashFunc, }, nil }
// ComputeShared computes the shared key for the private key material priv and // the x and y public coordinates func ComputeShared(curve elliptic.Curve, x, y *big.Int, priv []byte) []byte { x, _ = curve.ScalarMult(x, y, priv) return x.Bytes() }
func testScalarMult(curve elliptic.Curve, x1, y1, k, ex, ey *big.Int) bool { x, y := curve.ScalarMult(x1, y1, k.Bytes()) return x.Cmp(ex) == 0 && y.Cmp(ey) == 0 }