// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file defines an implementation of the IBE interfaces using the
// Boneh-Boyen scheme. The paper defining this algorithm (see comments for
// SetupBB1) uses multiplicative groups while the bn256 package used in the
// implementation here defines an additive group. The comments follow the
// notation in the paper while the code uses the bn256 library. For example,
// g^i corresponds to G1.ScalarBaseMult(i).

package ibe

import (
	"crypto/rand"
	"crypto/sha256"
	"errors"
	"fmt"
	"math/big"

	"golang.org/x/crypto/bn256"
)

var errBadCiphertext = errors.New("invalid ciphertext")

const (
	marshaledG1Size = 2 * 32
	marshaledG2Size = 4 * 32
	marshaledGTSize = 12 * 32
)

// Setup creates an ibe.Master based on the BB1 scheme described in "Efficient
// Selective Identity-Based Encryption Without Random Oracles" by Dan Boneh and
// Xavier Boyen (http://crypto.stanford.edu/~dabo/papers/bbibe.pdf).
//
// Specifically, Section 4.3 of the paper is implemented.
func SetupBB1() (Master, error) {
	var (
		m     = &bb1master{params: new(bb1params)}
		pk    = m.params   // shorthand
		g0Hat = &(m.g0Hat) // shorthand
	)

	// Set generators
	pk.g.ScalarBaseMult(big.NewInt(1))
	pk.gHat.ScalarBaseMult(big.NewInt(1))

	// Pick a random alpha and set g1 & g1Hat
	alpha, err := random()
	if err != nil {
		return nil, err
	}
	pk.g1.ScalarBaseMult(alpha)
	pk.g1Hat.ScalarBaseMult(alpha)

	// Pick a random delta and set h and hHat
	delta, err := random()
	if err != nil {
		return nil, err
	}
	pk.h.ScalarBaseMult(delta)
	pk.hHat.ScalarBaseMult(delta)

	// Pick a random beta and set g0Hat.
	beta, err := random()
	if err != nil {
		return nil, err
	}
	alphabeta := new(big.Int).Mul(alpha, beta)
	g0Hat.ScalarBaseMult(alphabeta.Mod(alphabeta, bn256.Order)) // g0Hat = gHat^*(alpha*beta)

	pk.v = bn256.Pair(&pk.g, g0Hat)
	return m, nil
}

type bb1master struct {
	params *bb1params // Public params
	g0Hat  bn256.G2   // Master key
}

func (m *bb1master) Extract(id string) (PrivateKey, error) {
	r, err := random()
	if err != nil {
		return nil, err
	}

	var (
		ret = &bb1PrivateKey{params: m.params}
		// A bunch of shorthands
		d0    = new(bn256.G2)
		g1Hat = &(m.params.g1Hat)
		g0Hat = &(m.g0Hat)
		hHat  = &(m.params.hHat)
		i     = id2bignum(id)
	)
	// ret.d0 = g0Hat * (g1Hat^i * hHat)^r
	d0.ScalarMult(g1Hat, i)
	d0.Add(d0, hHat)
	d0.ScalarMult(d0, r)
	ret.d0.Add(d0, g0Hat)
	ret.d1.ScalarBaseMult(r)
	return ret, nil
}

func (m *bb1master) Params() Params { return m.params }

type bb1params struct {
	g, g1, h          bn256.G1
	gHat, g1Hat, hHat bn256.G2
	v                 *bn256.GT
}

func (e *bb1params) Encrypt(id string, m *Plaintext, C *Ciphertext) error {
	s, err := random()
	if err != nil {
		return err
	}

	var (
		vs    bn256.GT
		tmpG1 bn256.G1
		// Ciphertext C = (A, B, C1)
		A  = C[0:len(m)]
		B  = C[len(m) : len(m)+marshaledG1Size]
		C1 = C[len(m)+marshaledG1Size:]
	)
	vs.ScalarMult(e.v, s)
	pad := sha256.Sum256(vs.Marshal())
	// A = m ⊕ H(v^s)
	for i := range m {
		A[i] = m[i] ^ pad[i]
	}
	// B = g^s
	if err := marshalG1(B, tmpG1.ScalarBaseMult(s)); err != nil {
		return err
	}
	// C1 = (g1^H(id) h)^s
	tmpG1.ScalarMult(&e.g1, id2bignum(id))
	tmpG1.Add(&tmpG1, &e.h)
	tmpG1.ScalarMult(&tmpG1, s)
	if err := marshalG1(C1, &tmpG1); err != nil {
		return err
	}
	return nil
}

type bb1PrivateKey struct {
	params *bb1params // public parameters
	d0, d1 bn256.G2
}

func (k *bb1PrivateKey) Decrypt(C *Ciphertext, m *Plaintext) error {
	var (
		A     = C[0:len(m)]
		B, C1 bn256.G1
	)
	if _, ok := B.Unmarshal(C[len(m) : len(m)+marshaledG1Size]); !ok {
		return errBadCiphertext
	}
	if _, ok := C1.Unmarshal(C[len(m)+marshaledG1Size:]); !ok {
		return errBadCiphertext
	}
	// M = A ⊕ H(e(B, d0)/e(C1,d1))
	var (
		numerator   = bn256.Pair(&B, &k.d0)
		denominator = bn256.Pair(&C1, &k.d1)
		hash        = sha256.Sum256(numerator.Add(numerator, denominator.Neg(denominator)).Marshal())
	)
	for i := range m {
		m[i] = A[i] ^ hash[i]
	}
	return nil
}

// random returns a positive integer in the range [1, bn256.Order)
// (denoted by Zp in http://crypto.stanford.edu/~dabo/papers/bbibe.pdf).
//
// The paper refers to random numbers drawn from Zp*. From a theoretical
// perspective, the uniform distribution over Zp and Zp* start within a
// statistical distance of 1/p (where p=bn256.Order is a ~256bit prime).  Thus,
// drawing uniformly from Zp is no different from Zp*.
func random() (*big.Int, error) {
	for {
		k, err := rand.Int(rand.Reader, bn256.Order)
		if err != nil {
			return nil, err
		}
		if k.Sign() > 0 {
			return k, nil
		}
	}
}

func id2bignum(id string) *big.Int {
	h := sha256.Sum256([]byte(id))
	k := new(big.Int).SetBytes(h[:])
	return k.Mod(k, bn256.Order)
}

// marshalG1 writes the marshaled form of g into dst.
func marshalG1(dst []byte, g *bn256.G1) error {
	src := g.Marshal()
	if len(src) != len(dst) {
		return fmt.Errorf("bn256.G1.Marshal returned a %d byte slice, expected %d: the BB1 IBE implementation is likely broken", len(src), len(dst))
	}
	copy(dst, src)
	return nil
}
