// Decrypt a message encrypted for a particular anonymity set. // Returns the cleartext message on success, or an error on failure. // // The caller provides the anonymity set for which the message is intended, // and the private key corresponding to one of the public keys in the set. // Decrypt verifies that the message is encrypted correctly for this set - // in particular, that it could be decrypted by ALL of the listed members - // before returning successfully with the decrypted message. // This verification ensures that a malicious sender // cannot de-anonymize a receiver by constructing a ciphertext incorrectly // so as to be decryptable by only some members of the set. // As a side-effect, this verification also ensures plaintext-awareness: // that is, it is infeasible for a sender to construct any ciphertext // that will be accepted by the receiver without knowing the plaintext. // func Decrypt(suite abstract.Suite, ciphertext []byte, anonymitySet Set, mine int, privateKey abstract.Secret, hide bool) ([]byte, error) { // Decrypt and check the encrypted key-header. xb, hdrlen, err := decryptKey(suite, ciphertext, anonymitySet, mine, privateKey, hide) if err != nil { return nil, err } // Determine the message layout cipher := suite.Cipher(xb) maclen := cipher.KeySize() if len(ciphertext) < hdrlen+maclen { return nil, errors.New("ciphertext too short") } hdrhi := hdrlen msghi := len(ciphertext) - maclen // Decrypt the message and check the MAC ctx := ciphertext[hdrhi:msghi] mac := ciphertext[msghi:] msg := make([]byte, len(ctx)) cipher.Message(msg, ctx, ctx) cipher.Partial(mac, mac, nil) if subtle.ConstantTimeAllEq(mac, 0) == 0 { return nil, errors.New("invalid ciphertext: failed MAC check") } return msg, nil }
// Encrypt a message for reading by any member of an explit anonymity set. // The caller supplies one or more keys representing the anonymity set. // If the provided set contains only one public key, // this reduces to conventional single-receiver public-key encryption. // // If hide is true, // Encrypt will produce a uniformly random-looking byte-stream, // which reveals no metadata other than message length // to anyone unable to decrypt the message. // The provided abstract.Suite must support // uniform-representation encoding of public keys for this to work. // func Encrypt(suite abstract.Suite, rand cipher.Stream, message []byte, anonymitySet Set, hide bool) []byte { xb, hdr := encryptKey(suite, rand, anonymitySet, hide) cipher := suite.Cipher(xb) // We now know the ciphertext layout hdrhi := 0 + len(hdr) msghi := hdrhi + len(message) machi := msghi + cipher.KeySize() ciphertext := make([]byte, machi) copy(ciphertext, hdr) // Now encrypt and MAC the message based on the master secret ctx := ciphertext[hdrhi:msghi] mac := ciphertext[msghi:machi] cipher.Message(ctx, message, ctx) cipher.Partial(mac, nil, nil) return ciphertext }