コード例 #1
0
ファイル: biffle.go プロジェクト: LegoShrimp/crypto
// Binary shuffle ("biffle") for 2 ciphertexts based on general ZKPs.
func Biffle(suite abstract.Suite, G, H abstract.Point,
	X, Y [2]abstract.Point, rand abstract.Cipher) (
	Xbar, Ybar [2]abstract.Point, prover proof.Prover) {

	// Pick the single-bit permutation.
	bit := int(random.Byte(rand) & 1)

	// Pick a fresh ElGamal blinding factor for each pair
	var beta [2]abstract.Scalar
	for i := 0; i < 2; i++ {
		beta[i] = suite.Scalar().Pick(rand)
	}

	// Create the output pair vectors
	for i := 0; i < 2; i++ {
		pi_i := i ^ bit
		Xbar[i] = suite.Point().Mul(G, beta[pi_i])
		Xbar[i].Add(Xbar[i], X[pi_i])
		Ybar[i] = suite.Point().Mul(H, beta[pi_i])
		Ybar[i].Add(Ybar[i], Y[pi_i])
	}

	or := bifflePred()
	secrets := map[string]abstract.Scalar{
		"beta0": beta[0],
		"beta1": beta[1]}
	points := bifflePoints(suite, G, H, X, Y, Xbar, Ybar)
	choice := map[proof.Predicate]int{or: bit}
	prover = or.Prover(suite, secrets, points, choice)
	return
}
コード例 #2
0
ファイル: encoding.go プロジェクト: nikirill/cothority
// DefaultConstructors gives a default constructor for protobuf out of the global suite
func DefaultConstructors(suite abstract.Suite) protobuf.Constructors {
	constructors := make(protobuf.Constructors)
	var point abstract.Point
	var secret abstract.Scalar
	constructors[reflect.TypeOf(&point).Elem()] = func() interface{} { return suite.Point() }
	constructors[reflect.TypeOf(&secret).Elem()] = func() interface{} { return suite.Scalar() }
	return constructors
}
コード例 #3
0
ファイル: key.go プロジェクト: nikirill/cothority
// ReadScalarHex reads a scalar in hexadecimal from string
func ReadScalarHex(suite abstract.Suite, str string) (abstract.Scalar, error) {
	enc, err := hex.DecodeString(str)
	if err != nil {
		return nil, err
	}
	s := suite.Scalar()
	err = s.UnmarshalBinary(enc)
	return s, err
}
コード例 #4
0
ファイル: sig.go プロジェクト: LegoShrimp/crypto
func signH1(suite abstract.Suite, H1pre abstract.Cipher, PG, PH abstract.Point) abstract.Scalar {
	H1 := H1pre.Clone()
	PGb, _ := PG.MarshalBinary()
	H1.Write(PGb)
	if PH != nil {
		PHb, _ := PH.MarshalBinary()
		H1.Write(PHb)
	}
	H1.Message(nil, nil, nil) // finish message absorption
	return suite.Scalar().Pick(H1)
}
コード例 #5
0
ファイル: schnorr.go プロジェクト: nikirill/cothority
func hash(suite abstract.Suite, r abstract.Point, msg []byte) (abstract.Scalar, error) {
	rBuf, err := r.MarshalBinary()
	if err != nil {
		return nil, err
	}
	cipher := suite.Cipher(rBuf)
	cipher.Message(nil, nil, msg)
	// (re)compute challenge (e)
	e := suite.Scalar().Pick(cipher)

	return e, nil
}
コード例 #6
0
ファイル: packets.go プロジェクト: dedis/cothority
// Verify returns whether the verification of the signature succeeds or not.
// Specifically, it adjusts the signature according to the exception in the
// signature, so it can be verified by dedis/crypto/cosi.
// publics is a slice of all public signatures, and the msg is the msg
// being signed.
func (bs *BFTSignature) Verify(s abstract.Suite, publics []abstract.Point) error {
	if bs == nil || bs.Sig == nil || bs.Msg == nil {
		return errors.New("Invalid signature")
	}
	// compute the aggregate key of all the signers
	aggPublic := s.Point().Null()
	for i := range publics {
		aggPublic.Add(aggPublic, publics[i])
	}
	// compute the reduced public aggregate key (all - exception)
	aggReducedPublic := s.Point().Null().Add(s.Point().Null(), aggPublic)

	// compute the aggregate commit of exception
	aggExCommit := s.Point().Null()
	for _, ex := range bs.Exceptions {
		aggExCommit = aggExCommit.Add(aggExCommit, ex.Commitment)
		aggReducedPublic.Sub(aggReducedPublic, publics[ex.Index])
	}
	// get back the commit to recreate  the challenge
	origCommit := s.Point()
	if err := origCommit.UnmarshalBinary(bs.Sig[0:32]); err != nil {
		return err
	}

	// re create challenge
	h := sha512.New()
	if _, err := origCommit.MarshalTo(h); err != nil {
		return err
	}
	if _, err := aggPublic.MarshalTo(h); err != nil {
		return err
	}
	if _, err := h.Write(bs.Msg); err != nil {
		return err
	}

	// redo like in cosi -k*A + r*B == C
	// only with C being the reduced version
	k := s.Scalar().SetBytes(h.Sum(nil))
	minusPublic := s.Point().Neg(aggReducedPublic)
	ka := s.Point().Mul(minusPublic, k)
	r := s.Scalar().SetBytes(bs.Sig[32:64])
	rb := s.Point().Mul(nil, r)
	left := s.Point().Add(rb, ka)

	right := s.Point().Sub(origCommit, aggExCommit)

	if !left.Equal(right) {
		return errors.New("Commit recreated is not equal to one given")
	}
	return nil
}
コード例 #7
0
ファイル: enc_test.go プロジェクト: LegoShrimp/crypto
func ElGamalEncrypt(suite abstract.Suite, pubkey abstract.Point, message []byte) (
	K, C abstract.Point, remainder []byte) {

	// Embed the message (or as much of it as will fit) into a curve point.
	M, remainder := suite.Point().Pick(message, random.Stream)

	// ElGamal-encrypt the point to produce ciphertext (K,C).
	k := suite.Scalar().Pick(random.Stream) // ephemeral private key
	K = suite.Point().Mul(nil, k)           // ephemeral DH public key
	S := suite.Point().Mul(pubkey, k)       // ephemeral DH shared secret
	C = S.Add(S, M)                         // message blinded with secret
	return
}
コード例 #8
0
ファイル: cosi.go プロジェクト: dedis/cothority
func verifyCommitment(suite abstract.Suite, msg []byte, commitment abstract.Point, challenge abstract.Scalar) error {
	pb, err := commitment.MarshalBinary()
	if err != nil {
		return err
	}
	cipher := suite.Cipher(pb)
	cipher.Message(nil, nil, msg)
	// reconstructed challenge
	reconstructed := suite.Scalar().Pick(cipher)
	if !reconstructed.Equal(challenge) {
		return errors.New("Reconstructed challenge not equal to one given")
	}
	return nil
}
コード例 #9
0
ファイル: skeme.go プロジェクト: LegoShrimp/crypto
// Initialize...
func (sk *SKEME) Init(suite abstract.Suite, rand cipher.Stream,
	lpri PriKey, rpub Set, hide bool) {
	sk.suite = suite
	sk.hide = hide
	sk.lpri, sk.rpub = lpri, rpub

	// Create our Diffie-Hellman keypair
	sk.lx = suite.Scalar().Pick(rand)
	sk.lX = suite.Point().Mul(nil, sk.lx)
	sk.lXb, _ = sk.lX.MarshalBinary()

	// Encrypt and send the DH key to the receiver.
	// This is a deviation from SKEME, to protect message metadata
	// and further harden messages against tampering or active MITM DoS.
	sk.lm = Encrypt(suite, rand, sk.lXb, rpub, hide)
}
コード例 #10
0
ファイル: sig_test.go プロジェクト: LegoShrimp/crypto
func benchGenKeys(suite abstract.Suite,
	nkeys int) ([]abstract.Point, abstract.Scalar) {

	rand := random.Stream

	// Create an anonymity set of random "public keys"
	X := make([]abstract.Point, nkeys)
	for i := range X { // pick random points
		X[i], _ = suite.Point().Pick(nil, rand)
	}

	// Make just one of them an actual public/private keypair (X[mine],x)
	x := suite.Scalar().Pick(rand)
	X[0] = suite.Point().Mul(nil, x)

	return X, x
}
コード例 #11
0
ファイル: enc.go プロジェクト: LegoShrimp/crypto
// XXX belongs in crypto package?
func keyPair(suite abstract.Suite, rand cipher.Stream,
	hide bool) (abstract.Point, abstract.Scalar, []byte) {

	x := suite.Scalar().Pick(rand)
	X := suite.Point().Mul(nil, x)
	if !hide {
		Xb, _ := X.MarshalBinary()
		return X, x, Xb
	}
	Xh := X.(abstract.Hiding)
	for {
		Xb := Xh.HideEncode(rand) // try to encode as uniform blob
		if Xb != nil {
			return X, x, Xb // success
		}
		x.Pick(rand) // try again with a new key
		X.Mul(nil, x)
	}
}
コード例 #12
0
ファイル: sig_test.go プロジェクト: LegoShrimp/crypto
// This simplified implementation of Schnorr Signatures is based on
// crypto/anon/sig.go
// The ring structure is removed and
// The anonimity set is reduced to one public key = no anonimity
func SchnorrSign(suite abstract.Suite, random cipher.Stream, message []byte,
	privateKey abstract.Scalar) []byte {

	// Create random secret v and public point commitment T
	v := suite.Scalar().Pick(random)
	T := suite.Point().Mul(nil, v)

	// Create challenge c based on message and T
	c := hashSchnorr(suite, message, T)

	// Compute response r = v - x*c
	r := suite.Scalar()
	r.Mul(privateKey, c).Sub(v, r)

	// Return verifiable signature {c, r}
	// Verifier will be able to compute v = r + x*c
	// And check that hashElgamal for T and the message == c
	buf := bytes.Buffer{}
	sig := basicSig{c, r}
	suite.Write(&buf, &sig)
	return buf.Bytes()
}
コード例 #13
0
ファイル: cosi.go プロジェクト: LegoShrimp/crypto
// VerifySignature is the method to call to verify a signature issued by a Cosi
// struct. Publics is the WHOLE list of publics keys, the mask at the end of the
// signature will take care of removing the indivual public keys that did not
// participate
func VerifySignature(suite abstract.Suite, publics []abstract.Point, message, sig []byte) error {
	aggCommitBuff := sig[:32]
	aggCommit := suite.Point()
	if err := aggCommit.UnmarshalBinary(aggCommitBuff); err != nil {
		panic(err)
	}
	sigBuff := sig[32:64]
	sigInt := suite.Scalar().SetBytes(sigBuff)
	maskBuff := sig[64:]
	mask := newMask(suite, publics)
	mask.SetMask(maskBuff)
	aggPublic := mask.Aggregate()
	aggPublicMarshal, err := aggPublic.MarshalBinary()
	if err != nil {
		return err
	}

	hash := sha512.New()
	hash.Write(aggCommitBuff)
	hash.Write(aggPublicMarshal)
	hash.Write(message)
	buff := hash.Sum(nil)
	k := suite.Scalar().SetBytes(buff)

	// k * -aggPublic + s * B = k*-A + s*B
	// from s = k * a + r => s * B = k * a * B + r * B <=> s*B = k*A + r*B
	// <=> s*B + k*-A = r*B
	minusPublic := suite.Point().Neg(aggPublic)
	kA := suite.Point().Mul(minusPublic, k)
	sB := suite.Point().Mul(nil, sigInt)
	left := suite.Point().Add(kA, sB)

	if !left.Equal(aggCommit) {
		return errors.New("Signature invalid")
	}

	return nil
}
コード例 #14
0
ファイル: test.go プロジェクト: LegoShrimp/crypto
func TestShuffle(suite abstract.Suite, k int, N int) {

	rand := suite.Cipher(abstract.RandomKey)

	// Create a "server" private/public keypair
	h := suite.Scalar().Pick(rand)
	H := suite.Point().Mul(nil, h)

	// Create a set of ephemeral "client" keypairs to shuffle
	c := make([]abstract.Scalar, k)
	C := make([]abstract.Point, k)
	//	fmt.Println("\nclient keys:")
	for i := 0; i < k; i++ {
		c[i] = suite.Scalar().Pick(rand)
		C[i] = suite.Point().Mul(nil, c[i])
		//		fmt.Println(" "+C[i].String())
	}

	// ElGamal-encrypt all these keypairs with the "server" key
	X := make([]abstract.Point, k)
	Y := make([]abstract.Point, k)
	r := suite.Scalar() // temporary
	for i := 0; i < k; i++ {
		r.Pick(rand)
		X[i] = suite.Point().Mul(nil, r)
		Y[i] = suite.Point().Mul(H, r) // ElGamal blinding factor
		Y[i].Add(Y[i], C[i])           // Encrypted client public key
	}

	// Repeat only the actual shuffle portion for test purposes.
	for i := 0; i < N; i++ {

		// Do a key-shuffle
		Xbar, Ybar, prover := Shuffle(suite, nil, H, X, Y, rand)
		prf, err := proof.HashProve(suite, "PairShuffle", rand, prover)
		if err != nil {
			panic("Shuffle proof failed: " + err.Error())
		}
		//fmt.Printf("proof:\n%s\n",hex.Dump(prf))

		// Check it
		verifier := Verifier(suite, nil, H, X, Y, Xbar, Ybar)
		err = proof.HashVerify(suite, "PairShuffle", verifier, prf)
		if err != nil {
			panic("Shuffle verify failed: " + err.Error())
		}
	}
}
コード例 #15
0
ファイル: schnorr.go プロジェクト: nikirill/cothority
// SignSchnorr creates a Schnorr signature from a msg and a private key
func SignSchnorr(suite abstract.Suite, private abstract.Scalar, msg []byte) (SchnorrSig, error) {
	// using notation from https://en.wikipedia.org/wiki/Schnorr_signature
	// create random secret k and public point commitment r
	k := suite.Scalar().Pick(random.Stream)
	r := suite.Point().Mul(nil, k)

	// create challenge e based on message and r
	e, err := hash(suite, r, msg)
	if err != nil {
		return SchnorrSig{}, err
	}

	// compute response s = k - x*e
	xe := suite.Scalar().Mul(private, e)
	s := suite.Scalar().Sub(k, xe)

	return SchnorrSig{Challenge: e, Response: s}, nil
}
コード例 #16
0
ファイル: sig.go プロジェクト: LegoShrimp/crypto
// Sign creates an optionally anonymous, optionally linkable
// signature on a given message.
//
// The caller supplies one or more public keys representing an anonymity set,
// and the private key corresponding to one of those public keys.
// The resulting signature proves to a verifier that the owner of
// one of these public keys signed the message,
// without revealing which key-holder signed the message,
// offering anonymity among the members of this explicit anonymity set.
// The other users whose keys are listed in the anonymity set need not consent
// or even be aware that they have been included in an anonymity set:
// anyone having a suitable public key may be "conscripted" into a set.
//
// If the provided anonymity set contains only one public key (the signer's),
// then this function produces a traditional non-anonymous signature,
// equivalent in both size and performance to a standard ElGamal signature.
//
// The caller may request either unlinkable or linkable anonymous signatures.
// If linkScope is nil, this function generates an unlinkable signature,
// which contains no information about which member signed the message.
// The anonymity provided by unlinkable signatures is forward-secure,
// in that a signature reveals nothing about which member generated it,
// even if all members' private keys are later released.
// For cryptographic background on unlinkable anonymity-set signatures -
// also known as ring signatures or ad-hoc group signatures -
// see Rivest, "How to Leak a Scalar" at
// http://people.csail.mit.edu/rivest/RivestShamirTauman-HowToLeakAScalar.pdf.
//
// If the caller passes a non-nil linkScope,
// the resulting anonymous signature will be linkable.
// This means that given two signatures produced using the same linkScope,
// a verifier will be able to tell whether
// the same or different anonymity set members produced those signatures.
// In particular, verifying a linkable signature yields a linkage tag.
// This linkage tag has a 1-to-1 correspondence with the signer's public key
// within a given linkScope, but is cryptographically unlinkable
// to either the signer's public key or to linkage tags in other scopes.
// The provided linkScope may be an arbitrary byte-string;
// the only significance these scopes have is whether they are equal or unequal.
// For details on the linkable signature algorithm this function implements,
// see Liu/Wei/Wong,
// "Linkable Spontaneous Anonymous Group Signature for Ad Hoc Groups" at
// http://www.cs.cityu.edu.hk/~duncan/papers/04liuetal_lsag.pdf.
//
// Linkage tags may be used to protect against sock-puppetry or Sybil attacks
// in situations where a verifier needs to know how many distinct members
// of an anonymity set are present or signed messages in a given context.
// It is cryptographically hard for one anonymity set member
// to produce signatures with different linkage tags in the same scope.
// An important and fundamental downside, however, is that
// linkable signatures do NOT offer forward-secure anonymity.
// If an anonymity set member's private key is later released,
// it is trivial to check whether or not that member produced a given signature.
// Also, anonymity set members who did NOT sign a message could
// (voluntarily or under coercion) prove that they did not sign it,
// e.g., simply by signing some other message in that linkage context
// and noting that the resulting linkage tag comes out different.
// Thus, linkable anonymous signatures are not appropriate to use
// in situations where there may be significant risk
// that members' private keys may later be compromised,
// or that members may be persuaded or coerced into revealing whether or not
// they produced a signature of interest.
//
func Sign(suite abstract.Suite, random cipher.Stream, message []byte,
	anonymitySet Set, linkScope []byte, mine int, privateKey abstract.Scalar) []byte {

	// Note that Rivest's original ring construction directly supports
	// heterogeneous rings containing public keys of different types -
	// e.g., a mixture of RSA keys and DSA keys with varying parameters.
	// Our ring signature construction currently supports
	// only homogeneous rings containing compatible keys
	// drawn from the cipher suite (e.g., the same elliptic curve).
	// The upside to this constrint is greater flexibility:
	// e.g., we also easily obtain linkable ring signatures,
	// which are not readily feasible with the original ring construction.

	n := len(anonymitySet)              // anonymity set size
	L := []abstract.Point(anonymitySet) // public keys in anonymity set
	pi := mine

	// If we want a linkable ring signature, produce correct linkage tag,
	// as a pseudorandom base point multiplied by our private key.
	// Liu's scheme specifies the linkScope as a hash of the ring;
	// this is one reasonable choice of linkage scope,
	// but there are others, so we parameterize this choice.
	var linkBase, linkTag abstract.Point
	if linkScope != nil {
		linkStream := suite.Cipher(linkScope)
		linkBase, _ = suite.Point().Pick(nil, linkStream)
		linkTag = suite.Point().Mul(linkBase, privateKey)
	}

	// First pre-hash the parameters to H1
	// that are invariant for different ring positions,
	// so that we don't have to hash them many times.
	H1pre := signH1pre(suite, linkScope, linkTag, message)

	// Pick a random commit for my ring position
	u := suite.Scalar().Pick(random)
	var UB, UL abstract.Point
	UB = suite.Point().Mul(nil, u)
	if linkScope != nil {
		UL = suite.Point().Mul(linkBase, u)
	}

	// Build the challenge ring
	s := make([]abstract.Scalar, n)
	c := make([]abstract.Scalar, n)
	c[(pi+1)%n] = signH1(suite, H1pre, UB, UL)
	var P, PG, PH abstract.Point
	P = suite.Point()
	PG = suite.Point()
	if linkScope != nil {
		PH = suite.Point()
	}
	for i := (pi + 1) % n; i != pi; i = (i + 1) % n {
		s[i] = suite.Scalar().Pick(random)
		PG.Add(PG.Mul(nil, s[i]), P.Mul(L[i], c[i]))
		if linkScope != nil {
			PH.Add(PH.Mul(linkBase, s[i]), P.Mul(linkTag, c[i]))
		}
		c[(i+1)%n] = signH1(suite, H1pre, PG, PH)
		//fmt.Printf("s%d %s\n",i,s[i].String())
		//fmt.Printf("c%d %s\n",(i+1)%n,c[(i+1)%n].String())
	}
	s[pi] = suite.Scalar()
	s[pi].Mul(privateKey, c[pi]).Sub(u, s[pi]) // s_pi = u - x_pi c_pi

	// Encode and return the signature
	buf := bytes.Buffer{}
	if linkScope != nil { // linkable ring signature
		sig := lSig{c[0], s, linkTag}
		suite.Write(&buf, &sig)
	} else { // unlinkable ring signature
		sig := uSig{c[0], s}
		suite.Write(&buf, &sig)
	}
	return buf.Bytes()
}
コード例 #17
0
ファイル: sig_test.go プロジェクト: LegoShrimp/crypto
// Returns a secret that depends on on a message and a point
func hashSchnorr(suite abstract.Suite, message []byte, p abstract.Point) abstract.Scalar {
	pb, _ := p.MarshalBinary()
	c := suite.Cipher(pb)
	c.Message(nil, nil, message)
	return suite.Scalar().Pick(c)
}
コード例 #18
0
ファイル: enc.go プロジェクト: LegoShrimp/crypto
// Decrypt and verify a key encrypted via encryptKey.
// On success, returns the key and the length of the decrypted header.
func decryptKey(suite abstract.Suite, ciphertext []byte, anonymitySet Set,
	mine int, privateKey abstract.Scalar,
	hide bool) ([]byte, int, error) {

	// Decode the (supposed) ephemeral public key from the front
	X := suite.Point()
	var Xb []byte
	if hide {
		Xh := X.(abstract.Hiding)
		hidelen := Xh.HideLen()
		if len(ciphertext) < hidelen {
			return nil, 0, errors.New("ciphertext too short")
		}
		X.(abstract.Hiding).HideDecode(ciphertext[:hidelen])
		Xb = ciphertext[:hidelen]
	} else {
		enclen := X.MarshalSize()
		if len(ciphertext) < enclen {
			return nil, 0, errors.New("ciphertext too short")
		}
		if err := X.UnmarshalBinary(ciphertext[:enclen]); err != nil {
			return nil, 0, err
		}
		Xb = ciphertext[:enclen]
	}
	Xblen := len(Xb)

	// Decode the (supposed) master secret with our private key
	nkeys := len(anonymitySet)
	if mine < 0 || mine >= nkeys {
		panic("private-key index out of range")
	}
	seclen := suite.ScalarLen()
	if len(ciphertext) < Xblen+seclen*nkeys {
		return nil, 0, errors.New("ciphertext too short")
	}
	S := suite.Point().Mul(X, privateKey)
	seed, _ := S.MarshalBinary()
	cipher := suite.Cipher(seed)
	xb := make([]byte, seclen)
	secofs := Xblen + seclen*mine
	cipher.Partial(xb, ciphertext[secofs:secofs+seclen], nil)
	x := suite.Scalar()
	if err := x.UnmarshalBinary(xb); err != nil {
		return nil, 0, err
	}

	// Make sure it reproduces the correct ephemeral public key
	Xv := suite.Point().Mul(nil, x)
	if !X.Equal(Xv) {
		return nil, 0, errors.New("invalid ciphertext")
	}

	// Regenerate and check the rest of the header,
	// to ensure that that any of the anonymitySet members could decrypt it
	hdr := header(suite, X, x, Xb, xb, anonymitySet)
	hdrlen := len(hdr)
	if hdrlen != Xblen+seclen*nkeys {
		panic("wrong header size")
	}
	if subtle.ConstantTimeCompare(hdr, ciphertext[:hdrlen]) == 0 {
		return nil, 0, errors.New("invalid ciphertext")
	}

	return xb, hdrlen, nil
}
コード例 #19
0
ファイル: key.go プロジェクト: nikirill/cothority
// ReadScalar64 takes a Base64-encoded scalar and returns that scalar,
// optionally an error
func ReadScalar64(suite abstract.Suite, r io.Reader) (abstract.Scalar, error) {
	s := suite.Scalar()
	dec := base64.NewDecoder(base64.StdEncoding, r)
	err := suite.Read(dec, &s)
	return s, err
}