Esempio n. 1
0
File: enc.go Progetto: Liamsi/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.Secret,
	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.SecretLen()
	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.Secret()
	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
}