// 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 }