scodec / scodec-bits

Provides immutable datatypes for working with bits and bytes
BSD 3-Clause "New" or "Revised" License
117 stars 58 forks source link

feat: crypto hash functions(md5, sha1, sha256 and hmac) #513

Closed i10416 closed 1 month ago

i10416 commented 1 month ago

This commit adds the following changes

References

i10416 commented 1 month ago

Sorry, I shouldn't use aliases such as "SHA256", which some providers support, but are not officially supported.

mpilquist commented 1 month ago

In fs2, we decided to delegate to Web Crypto on JS and OpenSSL on Native instead of defining these operations in pure Scala. I'd prefer not to include implementations of crypto primitives but I'm interested in your thoughts, as well as feedback from @armanbilge.

i10416 commented 1 month ago

@mpilquist Thank you for your feedback.

I think one of the virtues of scodec-bits is its dependency-free-ness. I admit that pure Scala implementation is neither as performant nor battle-tested as native binding, but it makes build much simpler and brings less dependencies.

I know there is native crypto binding in fs2. https://github.com/typelevel/fs2/pull/3070 However, I felt it is overkill to force those who just want to obtain a hash value from immutable byte array with sensible API across platforms(JVM, JS and Native) to use fs2(and cats-effect or equivalent effect runtime). Crypto hash functions are everywhere, and there could be a situation where people do not want to or cannot use purely functional API.

If scodec-bits provided crypto hash functions, it would allow developers to choose two options. If they want to convert bytes with portable, dependency-free hash functions in synchronous API, they can use scodec-bits. If they want to convert bytes with battle-tested(hence supposed to be secure), performant hash functions in purely functional API, they can use fs2.

I was looking to use hashing functionality in FS2 as I believe it is one of the (if not the) only Scala Native / Scala.js compliant abstraction for hashing. https://github.com/typelevel/fs2/issues/3157#issue-1607022143

armanbilge commented 1 month ago

I think one of the virtues of scodec-bits is its dependency-free-ness.

The good news is that Web Crypto is not a dependency on effectively all modern JS runtimes :) it's part of the built-in APIs on browsers, Node.js, Deno, Bun, etc.

hash functions in synchronous API

JS doesn't provide a synchronous API for hashing because doing compute-intensive operations will block the single-threaded runtime. This is especially problematic in browsers because it can cause a webpage to freeze for users. Further reading: https://javascript.info/event-loop

For Native, we will have to take on a dependency for some platforms, although I believe macOS and Windows include crypto routines in their system APIs. Meanwhile, OpenSSL is ubiquitous on all platforms. Many Scala Native applications will need OpenSSL anyway to access cryptographic routines for TLS/https.


I'd prefer not to include implementations of crypto primitives

I feel the same. We are not cryptography experts and have limited resources to responsibly handle CVEs.

it would allow developers to choose two options. If they want to convert bytes with portable, dependency-free hash functions in synchronous API, they can use scodec-bits. If they want to convert bytes with battle-tested(hence supposed to be secure)

Unfortunately, when you provide options, even experienced developers may inadvertently make the wrong choice. For a real example of this in the Scala.js ecosystem, I encourage you to read https://github.com/scala-js/scala-js/issues/4663#issuecomment-1144594038.

i10416 commented 1 month ago

Thank you for the feedback and explanation. I withdraw this PR. I'll read the links.