I've been starting to think about how to add support for async crypto engines to snow (like crypto coprocessors, or in my case, the Web Crypto API). The Web Crypto API is particularly difficult to work with together with snow, as one cannot simply spawn another thread to drive snow synchronously since the wasm32-unknown-unknown target doesn't support threading, and Web Workers are a pain to work with.
Adding this support seems difficult to do cleanly in a DRY way, as every function in snow which uses cryptography (which is a lot of them) would need to be made async, and awaits added appropriately. In fact, most of what snow's code does is drive crypto, so having separate copy-paste implementations for a separate async API, for example, would make maintenance pretty painful and error-prone.
Another technique I've seen for supporting both sync and async APIs is using macros like in the redis crate, but personally heavy use of macros is something I'd want to avoid. One good takeaway from the redis API, however, is that snow could add an optional async API by having HandshakeState/TransportState implement new AsyncHandshake/AsyncTransport traits which the user can choose to use if desired.
Another technique found in the mongodb crate is to write the implementation using async/await and have the sync API use some implementation of the block_on function from one of the async runtimes to wait on the Futures returned from the async implementation. In snow's case, assuming the CryptoResolver trait were made to return Futures, block_on could be added to the trait as well so that, if it knows that it returns all synchronous crypto implementations, its block_on implementation could be as dead simple as polling a Future once using noop_waker.
I'm still looking into more techniques for supporting parallel sync & async APIs, but I'd love to hear thoughts on whether any of this seems worthwhile / viable to support in snow.
I've been starting to think about how to add support for async crypto engines to
snow(like crypto coprocessors, or in my case, the Web Crypto API). The Web Crypto API is particularly difficult to work with together withsnow, as one cannot simply spawn another thread to drivesnowsynchronously since thewasm32-unknown-unknowntarget doesn't support threading, and Web Workers are a pain to work with.Adding this support seems difficult to do cleanly in a DRY way, as every function in
snowwhich uses cryptography (which is a lot of them) would need to be madeasync, andawaits added appropriately. In fact, most of whatsnow's code does is drive crypto, so having separate copy-paste implementations for a separate async API, for example, would make maintenance pretty painful and error-prone.Another technique I've seen for supporting both sync and async APIs is using macros like in the
rediscrate, but personally heavy use of macros is something I'd want to avoid. One good takeaway from theredisAPI, however, is thatsnowcould add an optional async API by havingHandshakeState/TransportStateimplement newAsyncHandshake/AsyncTransporttraits which the user can choose touseif desired.Another technique found in the
mongodbcrate is to write the implementation usingasync/awaitand have the sync API use some implementation of theblock_onfunction from one of the async runtimes to wait on theFutures returned from the async implementation. Insnow's case, assuming theCryptoResolvertrait were made to returnFutures,block_oncould be added to the trait as well so that, if it knows that it returns all synchronous crypto implementations, itsblock_onimplementation could be as dead simple as polling aFutureonce usingnoop_waker.I'm still looking into more techniques for supporting parallel sync & async APIs, but I'd love to hear thoughts on whether any of this seems worthwhile / viable to support in
snow.