Note that it is probably technically impossible to meet your requirement that both secrets have to be revealed at exactly the same time, if interpreted literally. However, if we interpret this requirement as meaning that each party needs guarantees that the other party selected its own message, before decrypting the message of the other party, then this might be achieved using a scheme by which each party commits to a message without revealing it, before actually sending it.
Note: In order to guarantee that Alice will get $M_B$ when revealing $M_A$, you need a trusted third party. However, if your requirements are consistent with simply giving Alice the ability to abort further interactions with Bob if Bob decides to cheat, the following scheme should be sufficient.
For simplicity, suppose each party has a RSA key pair that can be used for both signing and encryption, and that Alice already has the public key of Bob, and vice versa.
- Alice selects a message $M_A$. Bob selects a message $M_B$.
- Alice selects a symmetric AES key $K_A$. Bob selects a symmetric AES key $K_B$.
- Alice generates $S_A = Sign_{Priv_A}(K_A)$. Bob generates $S_B = Sign_{Priv_B}(K_B)$.
- Alice generates $C_A = AESEnc_{K_A}(M_A)$. Bob generates $C_B = AESEnc_{K_B}(M_B)$.
- Alice sends $S_A,C_A$ to Bob. Bob sends $S_B,C_B$ to Alice.
- Alice generates $T_A = Encrypt_{Publ_B}(K_A)$. Bob generates $T_B = Encrypt_{Publ_A}(K_B)$
- Alice sends $T_A$ to Bob. Bob sends $T_B$ to Alice.
- Alice generates $K'_B = Decrypt_{Priv_A}(T_B)$ and aborts if $Verify_{Publ_B}(S_B,K'_B)$ fails. Bob generates $K'_A = Decrypt_{Priv_B}(T_A)$ and aborts if $Verify_{Publ_A}(S_A,K'_A)$ fails.
- Alice generates $M'_B = AESDec_{K'_B}(C_B)$. Bob generates $M'_A = AESDec_{K'_A}(C_A)$.
The above scheme should only be regarded as a general outline.